/home/liu/actions-runner/_work/ccv/ccv/lib/ccv_algebra.c
Line | Count | Source |
1 | | #include "ccv.h" |
2 | | #include "ccv_internal.h" |
3 | | #if HAVE_ACCELERATE_FRAMEWORK |
4 | | #include <Accelerate/Accelerate.h> |
5 | | #elif HAVE_CBLAS |
6 | | #include <cblas.h> |
7 | | #endif |
8 | | |
9 | | double ccv_trace(ccv_matrix_t* mat) |
10 | 0 | { |
11 | 0 | return 0; |
12 | 0 | } |
13 | | |
14 | | double ccv_norm(ccv_matrix_t* mat, int type) |
15 | 0 | { |
16 | 0 | return 0; |
17 | 0 | } |
18 | | |
19 | | double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int flag) |
20 | 1 | { |
21 | 1 | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
22 | 1 | assert(CCV_GET_CHANNEL(da->type) == CCV_C1); |
23 | 1 | ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(20, "ccv_normalize(%d)", flag), da->sig, CCV_EOF_SIGN); |
24 | 1 | btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_C1 : CCV_GET_DATA_TYPE0 (btype) | CCV_C10 ; |
25 | 1 | ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, btype, sig); |
26 | 1 | assert(db); |
27 | 1 | ccv_object_return_if_cached(db->tb.f64, db); |
28 | 1 | double sum = 0, inv; |
29 | 1 | int i, j; |
30 | 1 | unsigned char* a_ptr = da->data.u8; |
31 | 1 | unsigned char* b_ptr = db->data.u8; |
32 | 1 | switch (flag) |
33 | 1 | { |
34 | 0 | case CCV_L1_NORM: |
35 | 0 | #define for_block(_for_set, _for_get) \ |
36 | 0 | for (i = 0; i < da->rows; i++) \ |
37 | 0 | { \ |
38 | 0 | for (j = 0; j < da->cols; j++) \ |
39 | 0 | sum += fabs((double)_for_get(a_ptr, j)); \ |
40 | 0 | a_ptr += da->step; \ |
41 | 0 | } \ |
42 | 0 | inv = 1.0 / sum; \ |
43 | 0 | a_ptr = da->data.u8; \ |
44 | 0 | for (i = 0; i < da->rows; i++) \ |
45 | 0 | { \ |
46 | 0 | for (j = 0; j < da->cols; j++) \ |
47 | 0 | _for_set(b_ptr, j, _for_get(a_ptr, j) * inv); \ |
48 | 0 | a_ptr += da->step; \ |
49 | 0 | b_ptr += db->step; \ |
50 | 0 | } |
51 | 0 | ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block); |
52 | 0 | #undef for_block |
53 | 0 | break; |
54 | 1 | case CCV_L2_NORM: |
55 | 1 | #define for_block(_for_set, _for_get) \ |
56 | 2 | for (i = 0; 1 i < da->rows; i++1 ) \ |
57 | 1 | { \ |
58 | 11 | for (j = 0; j < da->cols; j++10 ) \ |
59 | 10 | sum += _for_get(a_ptr, j) * _for_get1 (a_ptr, j); \ |
60 | 1 | a_ptr += da->step; \ |
61 | 1 | } \ |
62 | 1 | sum = sqrt(sum); \ |
63 | 1 | inv = 1.0 / sum; \ |
64 | 1 | a_ptr = da->data.u8; \ |
65 | 2 | for (i = 0; i < da->rows; i++1 ) \ |
66 | 1 | { \ |
67 | 11 | for (j = 0; j < da->cols; j++10 ) \ |
68 | 1 | _for_set(b_ptr, j, _for_get(a_ptr, j) * inv); \ |
69 | 1 | a_ptr += da->step; \ |
70 | 1 | b_ptr += db->step; \ |
71 | 1 | } |
72 | 1 | ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block); |
73 | 1 | #undef for_block |
74 | 1 | break; |
75 | 1 | } |
76 | 1 | return db->tb.f64 = sum; |
77 | 1 | } |
78 | | |
79 | | void ccv_sat(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int padding_pattern) |
80 | 3 | { |
81 | 3 | ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(20, "ccv_sat(%d)", padding_pattern), a->sig, CCV_EOF_SIGN); |
82 | 3 | int safe_type = (a->type & CCV_8U) ? (2 (a->rows * a->cols >= 0x808080)2 ? CCV_64S0 : CCV_32S2 ) : (1 (a->type & CCV_32S)1 ? CCV_64S1 : a->type0 ); |
83 | 3 | type = (type == 0) ? CCV_GET_DATA_TYPE(safe_type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE0 (type) | 0 CCV_GET_CHANNEL0 (a->type); |
84 | 3 | int ch = CCV_GET_CHANNEL(a->type); |
85 | 3 | int i, j; |
86 | 3 | unsigned char* a_ptr = a->data.u8; |
87 | 3 | ccv_dense_matrix_t* db; |
88 | 3 | unsigned char* b_ptr; |
89 | 3 | switch (padding_pattern) |
90 | 3 | { |
91 | 1 | case CCV_NO_PADDING: |
92 | 1 | db = *b = ccv_dense_matrix_renew(*b, a->rows, a->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); |
93 | 1 | ccv_object_return_if_cached(, db); |
94 | 1 | b_ptr = db->data.u8; |
95 | 1 | #define for_block(_for_set_b, _for_get_b, _for_get) \ |
96 | 4 | for (j = 0; 1 j < ch; j++3 ) \ |
97 | 1 | _for_set_b(b_ptr, j, _for_get(a_ptr, j)); \ |
98 | 10 | for (j = ch; j < a->cols * ch; j++9 ) \ |
99 | 1 | _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch) + _for_get(a_ptr, j)); \ |
100 | 1 | a_ptr += a->step; \ |
101 | 1 | b_ptr += db->step; \ |
102 | 5 | for (i = 1; i < a->rows; i++4 ) \ |
103 | 4 | { \ |
104 | 16 | for (j = 0; j < ch; j++12 ) \ |
105 | 4 | _for_set_b(b_ptr, j, _for_get_b(b_ptr - db->step, j) + _for_get(a_ptr, j)); \ |
106 | 40 | for (j = ch; j < a->cols * ch; j++36 ) \ |
107 | 4 | _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch) - _for_get_b(b_ptr - db->step, j - ch) + _for_get_b(b_ptr - db->step, j) + _for_get(a_ptr, j)); \ |
108 | 4 | a_ptr += a->step; \ |
109 | 4 | b_ptr += db->step; \ |
110 | 4 | } |
111 | 1 | ccv_matrix_setter_getter(db->type, ccv_matrix_getter, a->type, for_block); |
112 | 1 | #undef for_block |
113 | 1 | break; |
114 | 2 | case CCV_PADDING_ZERO: |
115 | 2 | db = *b = ccv_dense_matrix_renew(*b, a->rows + 1, a->cols + 1, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig); |
116 | 2 | ccv_object_return_if_cached(, db); |
117 | 2 | b_ptr = db->data.u8; |
118 | 2 | #define for_block(_for_set_b, _for_get_b, _for_get) \ |
119 | 1.93k | for (j = 0; 2 j < db->cols * ch; j++1.93k ) \ |
120 | 2 | _for_set_b(b_ptr, j, 0); \ |
121 | 2 | b_ptr += db->step; \ |
122 | 432 | for (i = 0; i < a->rows; i++430 ) \ |
123 | 430 | { \ |
124 | 1.72k | for (j = 0; j < ch; j++1.29k ) \ |
125 | 430 | _for_set_b(b_ptr, j, 0); \ |
126 | 816k | for (j = ch; j < db->cols * ch; j++816k ) \ |
127 | 430 | _for_set_b(b_ptr, j, _for_get_b(b_ptr, j - ch) - _for_get_b(b_ptr - db->step, j - ch) + _for_get_b(b_ptr - db->step, j) + _for_get(a_ptr, j - ch)); \ |
128 | 430 | a_ptr += a->step; \ |
129 | 430 | b_ptr += db->step; \ |
130 | 430 | } |
131 | 2 | ccv_matrix_setter_getter(db->type, ccv_matrix_getter, a->type, for_block); |
132 | 2 | #undef for_block |
133 | 2 | break; |
134 | 3 | } |
135 | 3 | } |
136 | | |
137 | | double ccv_sum(ccv_matrix_t* mat, int flag) |
138 | 3 | { |
139 | 3 | ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat); |
140 | 3 | double sum = 0; |
141 | 3 | unsigned char* m_ptr = dmt->data.u8; |
142 | 3 | int i, j, ch = CCV_GET_CHANNEL(dmt->type); |
143 | 3 | #define for_block(_, _for_get) \ |
144 | 3 | switch (flag) \ |
145 | 3 | { \ |
146 | 2 | case CCV_UNSIGNED: \ |
147 | 203 | for (i = 0; i < dmt->rows; i++201 ) \ |
148 | 201 | { \ |
149 | 60.8k | for (j = 0; j < dmt->cols * ch; j++60.6k ) \ |
150 | 60.6k | sum += fabs((double)(_for_get(m_ptr, j))); \ |
151 | 201 | m_ptr += dmt->step; \ |
152 | 201 | } \ |
153 | 2 | break; \ |
154 | 1 | case CCV_SIGNED: \ |
155 | 1 | default: \ |
156 | 4 | for (i = 0; i < dmt->rows; i++3 ) \ |
157 | 3 | { \ |
158 | 9 | for (j = 0; j < dmt->cols * ch; j++6 ) \ |
159 | 6 | sum += _for_get3 (m_ptr, j); \ |
160 | 3 | m_ptr += dmt->step; \ |
161 | 3 | } \ |
162 | 3 | } |
163 | 3 | ccv_matrix_getter(dmt->type, for_block); |
164 | 3 | #undef for_block |
165 | 3 | return sum; |
166 | 3 | } |
167 | | |
168 | | double ccv_variance(ccv_matrix_t* mat) |
169 | 0 | { |
170 | 0 | ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat); |
171 | 0 | double mean = 0, variance = 0; |
172 | 0 | unsigned char* m_ptr = dmt->data.u8; |
173 | 0 | int i, j, ch = CCV_GET_CHANNEL(dmt->type); |
174 | 0 | #define for_block(_, _for_get) \ |
175 | 0 | for (i = 0; i < dmt->rows; i++) \ |
176 | 0 | { \ |
177 | 0 | for (j = 0; j < dmt->cols * ch; j++) \ |
178 | 0 | { \ |
179 | 0 | mean += _for_get(m_ptr, j); \ |
180 | 0 | variance += _for_get(m_ptr, j) * _for_get(m_ptr, j); \ |
181 | 0 | } \ |
182 | 0 | m_ptr += dmt->step; \ |
183 | 0 | } |
184 | 0 | ccv_matrix_getter(dmt->type, for_block); |
185 | 0 | #undef for_block |
186 | 0 | mean = mean / (dmt->rows * dmt->cols * ch); |
187 | 0 | variance = variance / (dmt->rows * dmt->cols * ch); |
188 | 0 | return variance - mean * mean; |
189 | 0 | } |
190 | | |
191 | | void ccv_multiply(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type) |
192 | 1 | { |
193 | 1 | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
194 | 1 | ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); |
195 | 1 | assert(da->rows == db->rows && da->cols == db->cols && CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type) && CCV_GET_CHANNEL(da->type) == CCV_GET_CHANNEL(db->type)); |
196 | 1 | ccv_declare_derived_signature(sig, da->sig != 0 && db->sig != 0, ccv_sign_with_literal("ccv_multiply"), da->sig, db->sig, CCV_EOF_SIGN); |
197 | 1 | int no_8u_type = (da->type & CCV_8U) ? CCV_32S : da->type0 ; |
198 | 1 | type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE0 (type) | 0 CCV_GET_CHANNEL0 (da->type); |
199 | 1 | ccv_dense_matrix_t* dc = *c = ccv_dense_matrix_renew(*c, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); |
200 | 1 | ccv_object_return_if_cached(, dc); |
201 | 1 | int i, j, ch = CCV_GET_CHANNEL(da->type); |
202 | 1 | unsigned char* aptr = da->data.u8; |
203 | 1 | unsigned char* bptr = db->data.u8; |
204 | 1 | unsigned char* cptr = dc->data.u8; |
205 | 1 | #define for_block(_for_get, _for_set) \ |
206 | 426 | for (i = 0; 1 i < da->rows; i++425 ) \ |
207 | 425 | { \ |
208 | 816k | for (j = 0; j < da->cols * ch; j++816k ) \ |
209 | 425 | _for_set(cptr, j, _for_get(aptr, j) * _for_get(bptr, j)); \ |
210 | 425 | aptr += da->step; \ |
211 | 425 | bptr += db->step; \ |
212 | 425 | cptr += dc->step; \ |
213 | 425 | } |
214 | 1 | ccv_matrix_getter(da->type, ccv_matrix_setter, dc->type, for_block); |
215 | 1 | #undef for_block |
216 | 1 | } |
217 | | |
218 | | void ccv_add(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type) |
219 | 4 | { |
220 | 4 | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
221 | 4 | ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); |
222 | 4 | assert(da->rows == db->rows && da->cols == db->cols && CCV_GET_CHANNEL(da->type) == CCV_GET_CHANNEL(db->type)); |
223 | 4 | ccv_declare_derived_signature(sig, da->sig != 0 && db->sig != 0, ccv_sign_with_literal("ccv_add"), da->sig, db->sig, CCV_EOF_SIGN); |
224 | 4 | int no_8u_type = (da->type & CCV_8U) ? CCV_32S0 : da->type; |
225 | 4 | type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE0 (type) | 0 CCV_GET_CHANNEL0 (da->type); |
226 | 4 | ccv_dense_matrix_t* dc = *c = ccv_dense_matrix_renew(*c, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); |
227 | 4 | ccv_object_return_if_cached(, dc); |
228 | 4 | int i, j, ch = CCV_GET_CHANNEL(da->type); |
229 | 4 | unsigned char* aptr = da->data.u8; |
230 | 4 | unsigned char* bptr = db->data.u8; |
231 | 4 | unsigned char* cptr = dc->data.u8; |
232 | 4 | #define for_block(_for_get_a, _for_get_b, _for_set) \ |
233 | 37 | for (i = 0; 4 i < da->rows; i++33 ) \ |
234 | 33 | { \ |
235 | 69 | for (j = 0; j < da->cols * ch; j++36 ) \ |
236 | 33 | _for_set(cptr, j, _for_get_a(aptr, j) + _for_get_b(bptr, j)); \ |
237 | 33 | aptr += da->step; \ |
238 | 33 | bptr += db->step; \ |
239 | 33 | cptr += dc->step; \ |
240 | 33 | } |
241 | 4 | ccv_matrix_getter_a(da->type, ccv_matrix_getter_b, db->type, ccv_matrix_setter, dc->type, for_block); |
242 | 4 | #undef for_block |
243 | 4 | } |
244 | | |
245 | | void ccv_subtract(ccv_matrix_t* a, ccv_matrix_t* b, ccv_matrix_t** c, int type) |
246 | 1 | { |
247 | 1 | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
248 | 1 | ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); |
249 | 1 | assert(da->rows == db->rows && da->cols == db->cols && CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type) && CCV_GET_CHANNEL(da->type) == CCV_GET_CHANNEL(db->type)); |
250 | 1 | ccv_declare_derived_signature(sig, da->sig != 0 && db->sig != 0, ccv_sign_with_literal("ccv_subtract"), da->sig, db->sig, CCV_EOF_SIGN); |
251 | 1 | int no_8u_type = (da->type & CCV_8U) ? CCV_32S0 : da->type; |
252 | 1 | type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE0 (type) | 0 CCV_GET_CHANNEL0 (da->type); |
253 | 1 | ccv_dense_matrix_t* dc = *c = ccv_dense_matrix_renew(*c, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); |
254 | 1 | ccv_object_return_if_cached(, dc); |
255 | 1 | int i, j, ch = CCV_GET_CHANNEL(da->type); |
256 | 1 | unsigned char* aptr = da->data.u8; |
257 | 1 | unsigned char* bptr = db->data.u8; |
258 | 1 | unsigned char* cptr = dc->data.u8; |
259 | 1 | #define for_block(_for_get, _for_set) \ |
260 | 3 | for (i = 0; 1 i < da->rows; i++2 ) \ |
261 | 2 | { \ |
262 | 6 | for (j = 0; j < da->cols * ch; j++4 ) \ |
263 | 2 | _for_set(cptr, j, _for_get(aptr, j) - _for_get(bptr, j)); \ |
264 | 2 | aptr += da->step; \ |
265 | 2 | bptr += db->step; \ |
266 | 2 | cptr += dc->step; \ |
267 | 2 | } |
268 | 1 | ccv_matrix_getter(da->type, ccv_matrix_setter, dc->type, for_block); |
269 | 1 | #undef for_block |
270 | 1 | } |
271 | | |
272 | | void ccv_scale(ccv_matrix_t* a, ccv_matrix_t** b, int type, double ds) |
273 | 5 | { |
274 | 5 | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
275 | 5 | ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(20, "ccv_scale(%la)", ds), da->sig, CCV_EOF_SIGN); |
276 | 5 | type = (type == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE0 (type) | 0 CCV_GET_CHANNEL0 (da->type); |
277 | 5 | ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); |
278 | 5 | ccv_object_return_if_cached(, db); |
279 | 5 | int i, j, ch = CCV_GET_CHANNEL(da->type); |
280 | 5 | unsigned char* aptr = da->data.u8; |
281 | 5 | unsigned char* bptr = db->data.u8; |
282 | 5 | if (CCV_GET_DATA_TYPE(da->type) == CCV_8U && CCV_GET_DATA_TYPE1 (db->type) == CCV_8U1 ) // specialize for 8U type |
283 | 1 | { |
284 | 1 | unsigned char us[256]; |
285 | 257 | for (i = 0; i < 256; i++256 ) |
286 | 256 | us[i] = ccv_clamp(ds * i, 0, 255); |
287 | 2 | for (i = 0; i < da->rows; i++1 ) |
288 | 1 | { |
289 | 5 | for (j = 0; j < da->cols * ch; j++4 ) |
290 | 4 | bptr[j] = us[aptr[j]]; |
291 | 1 | aptr += da->step; |
292 | 1 | bptr += db->step; |
293 | 1 | } |
294 | 4 | } else { |
295 | 4 | #define for_block(_for_get, _for_set) \ |
296 | 396 | for (i = 0; 4 i < da->rows; i++392 ) \ |
297 | 392 | { \ |
298 | 221k | for (j = 0; j < da->cols * ch; j++220k ) \ |
299 | 392 | _for_set(bptr, j, ds * _for_get(aptr, j)); \ |
300 | 392 | aptr += da->step; \ |
301 | 392 | bptr += db->step; \ |
302 | 392 | } |
303 | 4 | ccv_matrix_getter(da->type, ccv_matrix_setter, db->type, for_block); |
304 | 4 | #undef for_block |
305 | 4 | } |
306 | 5 | } |
307 | | |
308 | | void ccv_gemm(ccv_matrix_t* a, ccv_matrix_t* b, double alpha, ccv_matrix_t* c, double beta, int transpose, ccv_matrix_t** d, int type) |
309 | 3.24k | { |
310 | 3.24k | ccv_dense_matrix_t* da = ccv_get_dense_matrix(a); |
311 | 3.24k | ccv_dense_matrix_t* db = ccv_get_dense_matrix(b); |
312 | 3.24k | ccv_dense_matrix_t* dc = (c == 0) ? 04 : ccv_get_dense_matrix(c)3.24k ; |
313 | | |
314 | 3.24k | assert(CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type) && CCV_GET_CHANNEL(da->type) == 1 && CCV_GET_CHANNEL(db->type) == 1 && ((transpose & CCV_A_TRANSPOSE) ? da->rows : da->cols) == ((transpose & CCV_B_TRANSPOSE) ? db->cols : db->rows)); |
315 | | |
316 | 3.24k | if (dc != 0) |
317 | 3.24k | assert(CCV_GET_DATA_TYPE(dc->type) == CCV_GET_DATA_TYPE(da->type) && CCV_GET_CHANNEL(dc->type) == 1 && ((transpose & CCV_A_TRANSPOSE) ? da->cols : da->rows) == dc->rows && ((transpose & CCV_B_TRANSPOSE) ? db->rows : db->cols) == dc->cols); |
318 | | |
319 | 3.24k | ccv_declare_derived_signature_case(sig, ccv_sign_with_format(20, "ccv_gemm(%d)", transpose), ccv_sign_if(dc == 0 && da->sig != 0 && db->sig != 0, da->sig, db->sig, CCV_EOF_SIGN), ccv_sign_if(dc != 0 && da->sig != 0 && db->sig != 0 && dc->sig != 0, da->sig, db->sig, dc->sig, CCV_EOF_SIGN)); |
320 | 3.24k | type = CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type); |
321 | 3.24k | ccv_dense_matrix_t* dd = *d = ccv_dense_matrix_renew(*d, (transpose & CCV_A_TRANSPOSE) ? da->cols4 : da->rows3.24k , (transpose & CCV_B_TRANSPOSE) ? db->rows7 : db->cols3.23k , type, type, sig); |
322 | 3.24k | ccv_object_return_if_cached(, dd); |
323 | | |
324 | 3.24k | if (dd != dc && dc != 04 ) |
325 | 0 | memcpy(dd->data.u8, dc->data.u8, dc->step * dc->rows); |
326 | 3.24k | else if (dc == 0) // clean up dd if dc is not provided |
327 | 4 | memset(dd->data.u8, 0, dd->step * dd->rows); |
328 | | |
329 | 3.24k | #if (defined HAVE_CBLAS || defined HAVE_ACCELERATE_FRAMEWORK) |
330 | 3.24k | switch (CCV_GET_DATA_TYPE(dd->type)) |
331 | 3.24k | { |
332 | 3.24k | case CCV_32F: |
333 | 3.24k | cblas_sgemm(CblasRowMajor, (transpose & CCV_A_TRANSPOSE) ? CblasTrans3 : CblasNoTrans3.24k , (transpose & CCV_B_TRANSPOSE) ? CblasTrans7 : CblasNoTrans3.23k , dd->rows, dd->cols, (transpose & CCV_A_TRANSPOSE) ? da->rows3 : da->cols3.24k , alpha, da->data.f32, da->cols, db->data.f32, db->cols, beta, dd->data.f32, dd->cols); |
334 | 3.24k | break; |
335 | 1 | case CCV_64F: |
336 | 1 | cblas_dgemm(CblasRowMajor, (transpose & CCV_A_TRANSPOSE) ? CblasTrans : CblasNoTrans0 , (transpose & CCV_B_TRANSPOSE) ? CblasTrans0 : CblasNoTrans, dd->rows, dd->cols, (transpose & CCV_A_TRANSPOSE) ? da->rows : da->cols0 , alpha, da->data.f64, da->cols, db->data.f64, db->cols, beta, dd->data.f64, dd->cols); |
337 | 1 | break; |
338 | 3.24k | } |
339 | | #else |
340 | | assert(0 && "You need a BLAS compatible library for this function, e.g. libatlas."); |
341 | | #endif |
342 | 3.24k | } |