ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/cmatrix.c
(Generate patch)

Comparing ray/src/util/cmatrix.c (file contents):
Revision 2.4 by greg, Thu May 29 17:28:09 2014 UTC vs.
Revision 2.18 by greg, Tue Aug 30 14:52:46 2016 UTC

# Line 8 | Line 8 | static const char RCSid[] = "$Id$";
8   */
9  
10   #include <ctype.h>
11 + #include "platform.h"
12   #include "standard.h"
13   #include "cmatrix.h"
14   #include "platform.h"
15 + #include "paths.h"
16   #include "resolu.h"
17  
18   const char      *cm_fmt_id[] = {
19 <                        "unknown", "ascii", "float", "double",
20 <                        COLRFMT, CIEFMT
19 >                        "unknown", "ascii", COLRFMT, CIEFMT,
20 >                        "float", "double"
21                  };
22  
23   const int       cm_elem_size[] = {
# Line 39 | Line 41 | cm_alloc(int nrows, int ncols)
41          return(cm);
42   }
43  
44 + static void
45 + adjacent_ra_sizes(size_t bounds[2], size_t target)
46 + {
47 +        bounds[0] = 0; bounds[1] = 2048;
48 +        while (bounds[1] < target) {
49 +                bounds[0] = bounds[1];
50 +                bounds[1] += bounds[1]>>1;
51 +        }
52 + }
53 +
54   /* Resize color coefficient matrix */
55   CMATRIX *
56   cm_resize(CMATRIX *cm, int nrows)
57   {
58 +        size_t  old_size, new_size, ra_bounds[2];
59 +
60          if (nrows == cm->nrows)
61                  return(cm);
62          if (nrows <= 0) {
63                  cm_free(cm);
64                  return(NULL);
65          }
66 <        cm = (CMATRIX *)realloc(cm, sizeof(CMATRIX) +
67 <                        sizeof(COLOR)*(nrows*cm->ncols - 1));
68 <        if (cm == NULL)
69 <                error(SYSTEM, "out of memory in cm_resize()");
66 >        old_size = sizeof(CMATRIX) + sizeof(COLOR)*(cm->nrows*cm->ncols - 1);
67 >        adjacent_ra_sizes(ra_bounds, old_size);
68 >        new_size = sizeof(CMATRIX) + sizeof(COLOR)*(nrows*cm->ncols - 1);
69 >        if (nrows < cm->nrows ? new_size <= ra_bounds[0] :
70 >                                new_size > ra_bounds[1]) {
71 >                adjacent_ra_sizes(ra_bounds, new_size);
72 >                cm = (CMATRIX *)realloc(cm, ra_bounds[1]);
73 >                if (cm == NULL)
74 >                        error(SYSTEM, "out of memory in cm_resize()");
75 >        }
76          cm->nrows = nrows;
77          return(cm);
78   }
79  
80 + typedef struct {
81 +        int     dtype;          /* data type */
82 +        int     nrows, ncols;   /* matrix size */
83 +        char    *err;           /* error message */
84 + } CMINFO;               /* header info record */
85 +
86   static int
87 < getDT(char *s, void *p)
87 > get_cminfo(char *s, void *p)
88   {
89 +        CMINFO  *ip = (CMINFO *)p;
90          char    fmt[32];
91          int     i;
92 <        
92 >
93 >        if (!strncmp(s, "NCOMP=", 6) && atoi(s+6) != 3) {
94 >                ip->err = "unexpected # components (must be 3)";
95 >                return(-1);
96 >        }
97 >        if (!strncmp(s, "NROWS=", 6)) {
98 >                ip->nrows = atoi(s+6);
99 >                return(0);
100 >        }
101 >        if (!strncmp(s, "NCOLS=", 6)) {
102 >                ip->ncols = atoi(s+6);
103 >                return(0);
104 >        }
105          if (!formatval(fmt, s))
106                  return(0);
107          for (i = 1; i < DTend; i++)
108                  if (!strcmp(fmt, cm_fmt_id[i]))
109 <                        *((int *)p) = i;
109 >                        ip->dtype = i;
110          return(0);
111   }
112  
113 < /* Load header to obtain data type */
114 < int
115 < getDTfromHeader(FILE *fp)
113 > /* Load header to obtain/check data type and number of columns */
114 > char *
115 > cm_getheader(int *dt, int *nr, int *nc, FILE *fp)
116   {
117 <        int     dt = DTfromHeader;
118 <        
119 <        if (getheader(fp, getDT, &dt) < 0)
120 <                error(SYSTEM, "header read error");
121 <        if (dt == DTfromHeader)
122 <                error(USER, "missing data format in header");
123 <        return(dt);
117 >        CMINFO  cmi;
118 >                                                /* read header */
119 >        cmi.dtype = DTfromHeader;
120 >        cmi.nrows = cmi.ncols = 0;
121 >        cmi.err = "unexpected EOF in header";
122 >        if (getheader(fp, get_cminfo, &cmi) < 0)
123 >                return(cmi.err);
124 >        if (dt != NULL) {                       /* get/check data type? */
125 >                if (cmi.dtype == DTfromHeader) {
126 >                        if (*dt == DTfromHeader)
127 >                                return("missing/unknown data format in header");
128 >                } else if (*dt == DTfromHeader)
129 >                        *dt = cmi.dtype;
130 >                else if (*dt != cmi.dtype)
131 >                        return("unexpected data format in header");
132 >        }
133 >        if (nr != NULL) {                       /* get/check #rows? */
134 >                if (*nr <= 0)
135 >                        *nr = cmi.nrows;
136 >                else if ((cmi.nrows > 0) & (*nr != cmi.nrows))
137 >                        return("unexpected row count in header");
138 >        }
139 >        if (nc != NULL) {                       /* get/check #columns? */
140 >                if (*nc <= 0)
141 >                        *nc = cmi.ncols;
142 >                else if ((cmi.ncols > 0) & (*nc != cmi.ncols))
143 >                        return("unexpected column count in header");
144 >        }
145 >        return(NULL);
146   }
147  
148 < /* Allocate and load a matrix from the given file (or stdin if NULL) */
148 > /* Allocate and load a matrix from the given input (or stdin if NULL) */
149   CMATRIX *
150 < cm_load(const char *fname, int nrows, int ncols, int dtype)
150 > cm_load(const char *inspec, int nrows, int ncols, int dtype)
151   {
152 <        FILE    *fp = stdin;
153 <        CMATRIX *cm;
152 >        const int       ROWINC = 2048;
153 >        FILE            *fp = stdin;
154 >        CMATRIX         *cm;
155  
156 <        if (ncols <= 0)
157 <                error(USER, "Non-positive number of columns");
158 <        if (fname == NULL)
159 <                fname = "<stdin>";
160 <        else if ((fp = fopen(fname, "r")) == NULL) {
161 <                sprintf(errmsg, "cannot open file '%s'", fname);
156 >        if (inspec == NULL)
157 >                inspec = "<stdin>";
158 >        else if (inspec[0] == '!') {
159 >                fp = popen(inspec+1, "r");
160 >                if (fp == NULL) {
161 >                        sprintf(errmsg, "cannot start command '%s'", inspec);
162 >                        error(SYSTEM, errmsg);
163 >                }
164 >        } else if ((fp = fopen(inspec, "r")) == NULL) {
165 >                sprintf(errmsg, "cannot open file '%s'", inspec);
166                  error(SYSTEM, errmsg);
167          }
168   #ifdef getc_unlocked
# Line 104 | Line 170 | cm_load(const char *fname, int nrows, int ncols, int d
170   #endif
171          if (dtype != DTascii)
172                  SET_FILE_BINARY(fp);            /* doesn't really work */
173 <        if (dtype == DTfromHeader)
174 <                dtype = getDTfromHeader(fp);
173 >        if (!dtype | !ncols) {                  /* expecting header? */
174 >                char    *err = cm_getheader(&dtype, &nrows, &ncols, fp);
175 >                if (err != NULL)
176 >                        error(USER, err);
177 >                if (ncols <= 0)
178 >                        error(USER, "unspecified number of columns");
179 >        }
180          switch (dtype) {
181          case DTascii:
182          case DTfloat:
# Line 116 | Line 187 | cm_load(const char *fname, int nrows, int ncols, int d
187          }
188          if (nrows <= 0) {                       /* don't know length? */
189                  int     guessrows = 147;        /* usually big enough */
190 <                if ((dtype != DTascii) & (fp != stdin)) {
190 >                if ((dtype != DTascii) & (fp != stdin) & (inspec[0] != '!')) {
191                          long    startpos = ftell(fp);
192                          if (fseek(fp, 0L, SEEK_END) == 0) {
193                                  long    endpos = ftell(fp);
# Line 126 | Line 197 | cm_load(const char *fname, int nrows, int ncols, int d
197                                  if ((endpos - startpos) % (ncols*elemsiz)) {
198                                          sprintf(errmsg,
199                                          "improper length for binary file '%s'",
200 <                                                        fname);
200 >                                                        inspec);
201                                          error(USER, errmsg);
202                                  }
203                                  guessrows = (endpos - startpos)/(ncols*elemsiz);
204                                  if (fseek(fp, startpos, SEEK_SET) < 0) {
205                                          sprintf(errmsg,
206                                                  "fseek() error on file '%s'",
207 <                                                        fname);
207 >                                                        inspec);
208                                          error(SYSTEM, errmsg);
209                                  }
210                                  nrows = guessrows;      /* we're confident */
# Line 149 | Line 220 | cm_load(const char *fname, int nrows, int ncols, int d
220                  int     r, c;
221                  for (r = 0; r < maxrow; r++) {
222                      if (r >= cm->nrows)                 /* need more space? */
223 <                        cm = cm_resize(cm, 2*cm->nrows);
223 >                        cm = cm_resize(cm, cm->nrows+ROWINC);
224                      for (c = 0; c < ncols; c++) {
225                          COLORV  *cv = cm_lval(cm,r,c);
226 <                        if (fscanf(fp, COLSPEC, cv, cv+1, cv+2) != 3)
226 >                        if (fscanf(fp, COLSPEC, cv, cv+1, cv+2) != 3) {
227                                  if ((nrows <= 0) & (r > 0) & !c) {
228                                          cm = cm_resize(cm, maxrow=r);
229                                          break;
230                                  } else
231                                          goto EOFerror;
232 +                        }
233                      }
234                  }
235                  while ((c = getc(fp)) != EOF)
236                          if (!isspace(c)) {
237                                  sprintf(errmsg,
238 <                                "unexpected data at end of ascii file %s",
239 <                                                fname);
238 >                                "unexpected data at end of ascii input '%s'",
239 >                                                inspec);
240                                  error(WARNING, errmsg);
241                                  break;
242                          }
# Line 172 | Line 244 | cm_load(const char *fname, int nrows, int ncols, int d
244                  if (sizeof(COLOR) == cm_elem_size[dtype]) {
245                          int     nread = 0;
246                          do {                            /* read all we can */
247 <                                nread += fread(cm->cmem + 3*nread,
247 >                                nread += getbinary(cm->cmem + 3*nread,
248                                                  sizeof(COLOR),
249                                                  cm->nrows*cm->ncols - nread,
250                                                  fp);
251                                  if (nrows <= 0) {       /* unknown length */
252                                          if (nread == cm->nrows*cm->ncols)
253                                                          /* need more space? */
254 <                                                cm = cm_resize(cm, 2*cm->nrows);
254 >                                                cm = cm_resize(cm, cm->nrows+ROWINC);
255                                          else if (nread && !(nread % cm->ncols))
256                                                          /* seem to be  done */
257                                                  cm = cm_resize(cm, nread/cm->ncols);
# Line 197 | Line 269 | cm_load(const char *fname, int nrows, int ncols, int d
269                          if (n <= 0)
270                                  goto not_handled;
271                          while (n--) {
272 <                                if (fread(dc, sizeof(double), 3, fp) != 3)
272 >                                if (getbinary(dc, sizeof(double), 3, fp) != 3)
273                                          goto EOFerror;
274                                  copycolor(cvp, dc);
275                                  cvp += 3;
# Line 210 | Line 282 | cm_load(const char *fname, int nrows, int ncols, int d
282                          if (n <= 0)
283                                  goto not_handled;
284                          while (n--) {
285 <                                if (fread(fc, sizeof(float), 3, fp) != 3)
285 >                                if (getbinary(fc, sizeof(float), 3, fp) != 3)
286                                          goto EOFerror;
287                                  copycolor(cvp, fc);
288                                  cvp += 3;
# Line 218 | Line 290 | cm_load(const char *fname, int nrows, int ncols, int d
290                  }
291                  if (fgetc(fp) != EOF) {
292                                  sprintf(errmsg,
293 <                                "unexpected data at end of binary file %s",
294 <                                                fname);
293 >                                "unexpected data at end of binary input '%s'",
294 >                                                inspec);
295                                  error(WARNING, errmsg);
296                  }
297          }
298 <        if (fp != stdin)
299 <                fclose(fp);
298 >        if (fp != stdin) {
299 >                if (inspec[0] != '!')
300 >                        fclose(fp);
301 >                else if (pclose(fp)) {
302 >                        sprintf(errmsg, "error running command '%s'", inspec);
303 >                        error(WARNING, errmsg);
304 >                }
305 >        }
306   #ifdef getc_unlocked
307          else
308                  funlockfile(fp);
309   #endif
310          return(cm);
311   EOFerror:
312 <        sprintf(errmsg, "unexpected EOF reading %s", fname);
312 >        sprintf(errmsg, "unexpected EOF reading %s", inspec);
313          error(USER, errmsg);
314   not_handled:
315          error(INTERNAL, "unhandled data size or length in cm_load()");
# Line 325 | Line 403 | cm_multiply(const CMATRIX *cm1, const CMATRIX *cm2)
403                  for (i = 0; i < cm1->ncols; i++) {
404                      const COLORV        *cp1 = cm_lval(cm1,dr,i);
405                      const COLORV        *cp2 = cm_lval(cm2,i,dc);
406 <                    res[0] += cp1[0] * cp2[0];
407 <                    res[1] += cp1[1] * cp2[1];
408 <                    res[2] += cp1[2] * cp2[2];
406 >                    res[0] += (double)cp1[0] * cp2[0];
407 >                    res[1] += (double)cp1[1] * cp2[1];
408 >                    res[2] += (double)cp1[2] * cp2[2];
409                  }
410                  copycolor(dp, res);
411              }
# Line 357 | Line 435 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
435                  if (sizeof(COLOR) == cm_elem_size[dtype]) {
436                          r = cm->ncols*cm->nrows;
437                          while (r > 0) {
438 <                                c = fwrite(mp, sizeof(COLOR), r, fp);
438 >                                c = putbinary(mp, sizeof(COLOR), r, fp);
439                                  if (c <= 0)
440                                          return(0);
441                                  mp += 3*c;
# Line 368 | Line 446 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
446                          r = cm->ncols*cm->nrows;
447                          while (r--) {
448                                  copycolor(dc, mp);
449 <                                if (fwrite(dc, sizeof(double), 3, fp) != 3)
449 >                                if (putbinary(dc, sizeof(double), 3, fp) != 3)
450                                          return(0);
451                                  mp += 3;
452                          }
# Line 377 | Line 455 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
455                          r = cm->ncols*cm->nrows;
456                          while (r--) {
457                                  copycolor(fc, mp);
458 <                                if (fwrite(fc, sizeof(float), 3, fp) != 3)
458 >                                if (putbinary(fc, sizeof(float), 3, fp) != 3)
459                                          return(0);
460                                  mp += 3;
461                          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines