305 |
|
static CMATRIX * |
306 |
|
cm_multiply(const CMATRIX *cm1, const CMATRIX *cm2) |
307 |
|
{ |
308 |
+ |
char *rowcheck=NULL, *colcheck=NULL; |
309 |
|
CMATRIX *cmr; |
310 |
|
int dr, dc, i; |
311 |
|
|
314 |
|
cmr = cm_alloc(cm1->nrows, cm2->ncols); |
315 |
|
if (cmr == NULL) |
316 |
|
return(NULL); |
317 |
+ |
/* optimization: check for zero rows & cols */ |
318 |
+ |
if (((cm1->nrows > 5) | (cm2->ncols > 5)) & (cm1->ncols > 5)) { |
319 |
+ |
static const COLOR czero; |
320 |
+ |
rowcheck = (char *)calloc(cmr->nrows, 1); |
321 |
+ |
for (dr = cm1->nrows*(rowcheck != NULL); dr--; ) |
322 |
+ |
for (dc = cm1->ncols; dc--; ) |
323 |
+ |
if (memcmp(cm_lval(cm1,dr,dc), czero, sizeof(COLOR))) { |
324 |
+ |
rowcheck[dr] = 1; |
325 |
+ |
break; |
326 |
+ |
} |
327 |
+ |
colcheck = (char *)calloc(cmr->ncols, 1); |
328 |
+ |
for (dc = cm2->ncols*(colcheck != NULL); dc--; ) |
329 |
+ |
for (dr = cm2->nrows; dr--; ) |
330 |
+ |
if (memcmp(cm_lval(cm2,dr,dc), czero, sizeof(COLOR))) { |
331 |
+ |
colcheck[dc] = 1; |
332 |
+ |
break; |
333 |
+ |
} |
334 |
+ |
} |
335 |
|
for (dr = 0; dr < cmr->nrows; dr++) |
336 |
|
for (dc = 0; dc < cmr->ncols; dc++) { |
337 |
|
COLORV *dp = cm_lval(cmr,dr,dc); |
338 |
|
dp[0] = dp[1] = dp[2] = 0; |
339 |
+ |
if (rowcheck != NULL && !rowcheck[dr]) |
340 |
+ |
continue; |
341 |
+ |
if (colcheck != NULL && !colcheck[dc]) |
342 |
+ |
continue; |
343 |
|
for (i = 0; i < cm1->ncols; i++) { |
344 |
|
const COLORV *cp1 = cm_lval(cm1,dr,i); |
345 |
|
const COLORV *cp2 = cm_lval(cm2,i,dc); |
348 |
|
dp[2] += cp1[2] * cp2[2]; |
349 |
|
} |
350 |
|
} |
351 |
+ |
if (rowcheck != NULL) free(rowcheck); |
352 |
+ |
if (colcheck != NULL) free(colcheck); |
353 |
|
return(cmr); |
354 |
|
} |
355 |
|
|