107 |
|
static CMATRIX * |
108 |
|
cm_load(const char *fname, int nrows, int ncols, int dtype) |
109 |
|
{ |
110 |
– |
CMATRIX *cm; |
110 |
|
FILE *fp = stdin; |
111 |
+ |
CMATRIX *cm; |
112 |
|
|
113 |
|
if (ncols <= 0) |
114 |
|
error(USER, "Non-positive number of columns"); |
118 |
|
sprintf(errmsg, "cannot open file '%s'", fname); |
119 |
|
error(SYSTEM, errmsg); |
120 |
|
} |
121 |
+ |
#ifdef getc_unlocked |
122 |
+ |
flockfile(fp); |
123 |
+ |
#endif |
124 |
|
if (dtype != DTascii) |
125 |
< |
SET_FILE_BINARY(fp); |
125 |
> |
SET_FILE_BINARY(fp); /* doesn't really work */ |
126 |
|
if (dtype == DTfromHeader) |
127 |
|
dtype = getDTfromHeader(fp); |
128 |
|
switch (dtype) { |
161 |
|
cm = cm_alloc(guessrows, ncols); |
162 |
|
} else |
163 |
|
cm = cm_alloc(nrows, ncols); |
164 |
< |
if (cm == NULL) |
164 |
> |
if (cm == NULL) /* XXX never happens */ |
165 |
|
return(NULL); |
166 |
|
if (dtype == DTascii) { /* read text file */ |
167 |
|
int maxrow = (nrows > 0 ? nrows : 32000); |
236 |
|
cvp += 3; |
237 |
|
} |
238 |
|
} |
239 |
< |
if (getc(fp) != EOF) { |
239 |
> |
if (fgetc(fp) != EOF) { |
240 |
|
sprintf(errmsg, |
241 |
|
"unexpected data at end of binary file %s", |
242 |
|
fname); |
245 |
|
} |
246 |
|
if (fp != stdin) |
247 |
|
fclose(fp); |
248 |
+ |
#ifdef getc_unlocked |
249 |
+ |
else |
250 |
+ |
funlockfile(fp); |
251 |
+ |
#endif |
252 |
|
return(cm); |
253 |
|
EOFerror: |
254 |
< |
sprintf(errmsg, "unexpected EOF reading %s", |
248 |
< |
fname); |
254 |
> |
sprintf(errmsg, "unexpected EOF reading %s", fname); |
255 |
|
error(USER, errmsg); |
256 |
|
not_handled: |
257 |
|
error(INTERNAL, "unhandled data size or length in cm_load()"); |
266 |
|
int dr; |
267 |
|
|
268 |
|
if ((c < 0) | (c >= cm->ncols)) |
269 |
< |
return(NULL); |
269 |
> |
error(INTERNAL, "column requested outside matrix"); |
270 |
|
cvr = cm_alloc(cm->nrows, 1); |
271 |
|
if (cvr == NULL) |
272 |
|
return(NULL); |
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 |
|
|
618 |
|
int |
619 |
|
main(int argc, char *argv[]) |
620 |
|
{ |
621 |
+ |
int skyfmt = DTascii; |
622 |
|
int nsteps = 1; |
623 |
|
char *ofspec = NULL; |
624 |
|
FILE *ofp = stdout; |
628 |
|
|
629 |
|
progname = argv[0]; |
630 |
|
/* get options */ |
631 |
< |
for (a = 1; a < argc-1 && argv[a][0] == '-'; a++) |
632 |
< |
switch (argv[0][1]) { |
631 |
> |
for (a = 1; a < argc && argv[a][0] == '-'; a++) |
632 |
> |
switch (argv[a][1]) { |
633 |
|
case 'n': |
634 |
|
nsteps = atoi(argv[++a]); |
635 |
|
if (nsteps <= 0) |
638 |
|
case 'o': |
639 |
|
ofspec = argv[++a]; |
640 |
|
break; |
641 |
+ |
case 'i': |
642 |
+ |
switch (argv[a][2]) { |
643 |
+ |
case 'f': |
644 |
+ |
skyfmt = DTfloat; |
645 |
+ |
break; |
646 |
+ |
case 'd': |
647 |
+ |
skyfmt = DTdouble; |
648 |
+ |
break; |
649 |
+ |
case 'a': |
650 |
+ |
skyfmt = DTascii; |
651 |
+ |
break; |
652 |
+ |
default: |
653 |
+ |
goto userr; |
654 |
+ |
} |
655 |
+ |
break; |
656 |
|
default: |
657 |
|
goto userr; |
658 |
|
} |
663 |
|
CMATRIX *smtx, *Dmat, *Tmat, *imtx; |
664 |
|
COLOR tLamb; |
665 |
|
/* get sky vector/matrix */ |
666 |
< |
smtx = cm_load(argv[a+3], 0, nsteps, DTascii); |
666 |
> |
smtx = cm_load(argv[a+3], 0, nsteps, skyfmt); |
667 |
|
/* load BSDF */ |
668 |
|
Tmat = cm_loadBSDF(argv[a+1], tLamb); |
669 |
|
/* load Daylight matrix */ |
680 |
|
} |
681 |
|
cm_free(imtx); |
682 |
|
} else { /* sky vector/matrix only */ |
683 |
< |
cmtx = cm_load(argv[a+1], 0, nsteps, DTascii); |
683 |
> |
cmtx = cm_load(argv[a+1], 0, nsteps, skyfmt); |
684 |
|
} |
685 |
|
/* prepare output stream */ |
686 |
|
if ((ofspec != NULL) & (nsteps == 1) && hasNumberFormat(ofspec)) { |
768 |
|
cm_free(cmtx); |
769 |
|
return(0); |
770 |
|
userr: |
771 |
< |
fprintf(stderr, "Usage: %s [-n nsteps][-o ospec] DCspec [skyf]\n", |
771 |
> |
fprintf(stderr, "Usage: %s [-n nsteps][-o ospec][-i{f|d}] DCspec [skyf]\n", |
772 |
|
progname); |
773 |
< |
fprintf(stderr, " or: %s [-n nsteps][-o ospec] Vspec Tbsdf.xml Dmat.dat [skyf]\n", |
773 |
> |
fprintf(stderr, " or: %s [-n nsteps][-o ospec][-i{f|d}] Vspec Tbsdf.xml Dmat.dat [skyf]\n", |
774 |
|
progname); |
775 |
|
return(1); |
776 |
|
} |