| 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 |
|
|