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

Comparing ray/src/util/rmatrix.c (file contents):
Revision 2.13 by greg, Mon May 4 20:53:21 2015 UTC vs.
Revision 2.37 by greg, Wed Sep 4 00:03:05 2019 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   #include <stdlib.h>
10   #include <string.h>
11   #include <fcntl.h>
12 + #include <errno.h>
13 + #include "rtio.h"
14 + #include "platform.h"
15   #include "resolu.h"
16 + #include "paths.h"
17   #include "rmatrix.h"
18  
19   static char     rmx_mismatch_warn[] = "WARNING: data type mismatch\n";
# Line 24 | Line 28 | rmx_alloc(int nr, int nc, int n)
28                  return(NULL);
29          dnew = (RMATRIX *)malloc(sizeof(RMATRIX)-sizeof(dnew->mtx) +
30                                          sizeof(dnew->mtx[0])*(n*nr*nc));
31 <        if (dnew == NULL)
31 >        if (!dnew)
32                  return(NULL);
33          dnew->nrows = nr; dnew->ncols = nc; dnew->ncomp = n;
34          dnew->dtype = DTdouble;
35 +        dnew->swapin = 0;
36          dnew->info = NULL;
37          return(dnew);
38   }
# Line 46 | Line 51 | rmx_free(RMATRIX *rm)
51   int
52   rmx_newtype(int dtyp1, int dtyp2)
53   {
54 <        if ((dtyp1==DTxyze) | (dtyp1==DTrgbe) && dtyp1 != dtyp2)
54 >        if ((dtyp1==DTxyze) | (dtyp1==DTrgbe) |
55 >                        (dtyp2==DTxyze) | (dtyp2==DTrgbe)
56 >                        && dtyp1 != dtyp2)
57                  return(0);
58          if (dtyp1 < dtyp2)
59                  return(dtyp1);
# Line 57 | Line 64 | rmx_newtype(int dtyp1, int dtyp2)
64   int
65   rmx_addinfo(RMATRIX *rm, const char *info)
66   {
67 <        if (!info || !*info)
67 >        if (!rm || !info || !*info)
68                  return(0);
69          if (!rm->info) {
70                  rm->info = (char *)malloc(strlen(info)+1);
# Line 75 | Line 82 | static int
82   get_dminfo(char *s, void *p)
83   {
84          RMATRIX *ip = (RMATRIX *)p;
85 <        char    fmt[64];
85 >        char    fmt[MAXFMTLEN];
86          int     i;
87  
88          if (headidval(fmt, s))
# Line 92 | Line 99 | get_dminfo(char *s, void *p)
99                  ip->ncols = atoi(s+6);
100                  return(0);
101          }
102 +        if ((i = isbigendian(s)) >= 0) {
103 +                ip->swapin = (nativebigendian() != i);
104 +                return(0);
105 +        }
106          if (!formatval(fmt, s)) {
107                  rmx_addinfo(ip, s);
108                  return(0);
# Line 108 | Line 119 | static int
119   rmx_load_ascii(RMATRIX *rm, FILE *fp)
120   {
121          int     i, j, k;
122 < #ifdef _WIN32
112 <        _setmode(fileno(fp), _O_TEXT);
113 < #endif
122 >
123          for (i = 0; i < rm->nrows; i++)
124              for (j = 0; j < rm->ncols; j++)
125                  for (k = 0; k < rm->ncomp; k++)
# Line 131 | Line 140 | rmx_load_float(RMATRIX *rm, FILE *fp)
140          }
141          for (i = 0; i < rm->nrows; i++)
142              for (j = 0; j < rm->ncols; j++) {
143 <                if (fread(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
143 >                if (getbinary(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
144                      return(0);
145 +                if (rm->swapin)
146 +                    swap32((char *)val, rm->ncomp);
147                  for (k = rm->ncomp; k--; )
148                       rmx_lval(rm,i,j,k) = val[k];
149              }
# Line 142 | Line 153 | rmx_load_float(RMATRIX *rm, FILE *fp)
153   static int
154   rmx_load_double(RMATRIX *rm, FILE *fp)
155   {
156 <        int     i, j, k;
146 <        double  val[100];
156 >        int     i, j;
157  
148        if (rm->ncomp > 100) {
149                fputs("Unsupported # components in rmx_load_double()\n", stderr);
150                exit(1);
151        }
158          for (i = 0; i < rm->nrows; i++)
159              for (j = 0; j < rm->ncols; j++) {
160 <                if (fread(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
160 >                if (getbinary(&rmx_lval(rm,i,j,0), sizeof(double), rm->ncomp, fp) != rm->ncomp)
161                      return(0);
162 <                for (k = rm->ncomp; k--; )
163 <                     rmx_lval(rm,i,j,k) = val[k];
162 >                if (rm->swapin)
163 >                    swap64((char *)&rmx_lval(rm,i,j,0), rm->ncomp);
164              }
165          return(1);
166   }
# Line 165 | Line 171 | rmx_load_rgbe(RMATRIX *rm, FILE *fp)
171          COLOR   *scan = (COLOR *)malloc(sizeof(COLOR)*rm->ncols);
172          int     i, j;
173  
174 <        if (scan == NULL)
174 >        if (!scan)
175                  return(0);
176          for (i = 0; i < rm->nrows; i++) {
177              if (freadscan(scan, rm->ncols, fp) < 0) {
# Line 190 | Line 196 | rmx_load(const char *inspec)
196          RMATRIX         dinfo;
197          RMATRIX         *dnew;
198  
199 <        if (inspec == NULL) {                   /* reading from stdin? */
199 >        if (!inspec) {                          /* reading from stdin? */
200                  inspec = "<stdin>";
201 < #ifdef _WIN32
196 <                _setmode(fileno(stdin), _O_BINARY);
197 < #endif
201 >                SET_FILE_BINARY(stdin);
202          } else if (inspec[0] == '!') {
203 <                if ((fp = popen(inspec+1, "r")) == NULL)
203 >                if (!(fp = popen(inspec+1, "r")))
204                          return(NULL);
205 < #ifdef _WIN32
202 <                _setmode(fileno(fp), _O_BINARY);
203 < #endif
205 >                SET_FILE_BINARY(fp);
206          } else {
207                  const char      *sp = inspec;   /* check suffix */
208                  while (*sp)
# Line 209 | Line 211 | rmx_load(const char *inspec)
211                          --sp;
212                  if (!strcasecmp(sp, "XML")) {   /* assume it's a BSDF */
213                          CMATRIX *cm = cm_loadBTDF((char *)inspec);
214 <                        if (cm == NULL)
214 >                        if (!cm)
215                                  return(NULL);
216                          dnew = rmx_from_cmatrix(cm);
217                          cm_free(cm);
218 +                        dnew->dtype = DTascii;
219                          return(dnew);
220                  }
221                                                  /* else open it ourselves */
222 <                if ((fp = fopen(inspec, "rb")) == NULL)
222 >                if (!(fp = fopen(inspec, "rb")))
223                          return(NULL);
224          }
225   #ifdef getc_unlocked
# Line 224 | Line 227 | rmx_load(const char *inspec)
227   #endif
228          dinfo.nrows = dinfo.ncols = dinfo.ncomp = 0;
229          dinfo.dtype = DTascii;                  /* assumed w/o FORMAT */
230 +        dinfo.swapin = 0;
231          dinfo.info = NULL;
232          if (getheader(fp, get_dminfo, &dinfo) < 0) {
233                  fclose(fp);
# Line 243 | Line 247 | rmx_load(const char *inspec)
247                  }
248          }
249          dnew = rmx_alloc(dinfo.nrows, dinfo.ncols, dinfo.ncomp);
250 <        if (dnew == NULL) {
250 >        if (!dnew) {
251                  fclose(fp);
252                  return(NULL);
253          }
254          dnew->info = dinfo.info;
255          switch (dinfo.dtype) {
256          case DTascii:
257 +                SET_FILE_TEXT(fp);
258                  if (!rmx_load_ascii(dnew, fp))
259                          goto loaderr;
260                  dnew->dtype = DTascii;          /* should leave double? */
261                  break;
262          case DTfloat:
263 +                dnew->swapin = dinfo.swapin;
264                  if (!rmx_load_float(dnew, fp))
265                          goto loaderr;
266                  dnew->dtype = DTfloat;
267                  break;
268          case DTdouble:
269 +                dnew->swapin = dinfo.swapin;
270                  if (!rmx_load_double(dnew, fp))
271                          goto loaderr;
272                  dnew->dtype = DTdouble;
# Line 296 | Line 303 | loaderr:                                       /* should report error? */
303   static int
304   rmx_write_ascii(const RMATRIX *rm, FILE *fp)
305   {
306 +        const char      *fmt = (rm->dtype == DTfloat) ? " %.7e" :
307 +                        (rm->dtype == DTrgbe) | (rm->dtype == DTxyze) ? " %.3e" :
308 +                                " %.15e" ;
309          int     i, j, k;
310 < #ifdef _WIN32
301 <        _setmode(fileno(fp), _O_TEXT);
302 < #endif
310 >
311          for (i = 0; i < rm->nrows; i++) {
312              for (j = 0; j < rm->ncols; j++) {
313                  for (k = 0; k < rm->ncomp; k++)
314 <                    fprintf(fp, " %.15e", rmx_lval(rm,i,j,k));
314 >                    fprintf(fp, fmt, rmx_lval(rm,i,j,k));
315                  fputc('\t', fp);
316              }
317              fputc('\n', fp);
# Line 325 | Line 333 | rmx_write_float(const RMATRIX *rm, FILE *fp)
333              for (j = 0; j < rm->ncols; j++) {
334                  for (k = rm->ncomp; k--; )
335                      val[k] = (float)rmx_lval(rm,i,j,k);
336 <                if (fwrite(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
336 >                if (putbinary(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
337                          return(0);
338              }
339          return(1);
# Line 334 | Line 342 | rmx_write_float(const RMATRIX *rm, FILE *fp)
342   static int
343   rmx_write_double(const RMATRIX *rm, FILE *fp)
344   {
345 <        int     i, j, k;
338 <        double  val[100];
345 >        int     i, j;
346  
340        if (rm->ncomp > 100) {
341                fputs("Unsupported # components in rmx_write_double()\n", stderr);
342                exit(1);
343        }
347          for (i = 0; i < rm->nrows; i++)
348 <            for (j = 0; j < rm->ncols; j++) {
349 <                for (k = rm->ncomp; k--; )
347 <                    val[k] = rmx_lval(rm,i,j,k);
348 <                if (fwrite(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp)
348 >            for (j = 0; j < rm->ncols; j++)
349 >                if (putbinary(&rmx_lval(rm,i,j,0), sizeof(double), rm->ncomp, fp) != rm->ncomp)
350                          return(0);
350            }
351          return(1);
352   }
353  
354   static int
355   rmx_write_rgbe(const RMATRIX *rm, FILE *fp)
356   {
357 <        COLOR   *scan = (COLOR *)malloc(sizeof(COLOR)*rm->ncols);
357 >        COLR    *scan = (COLR *)malloc(sizeof(COLR)*rm->ncols);
358          int     i, j;
359  
360 <        if (scan == NULL)
360 >        if (!scan)
361                  return(0);
362          for (i = 0; i < rm->nrows; i++) {
363              for (j = rm->ncols; j--; )
364 <                setcolor(scan[j],       rmx_lval(rm,i,j,0),
364 >                setcolr(scan[j],        rmx_lval(rm,i,j,0),
365                                          rmx_lval(rm,i,j,1),
366                                          rmx_lval(rm,i,j,2)      );
367 <            if (fwritescan(scan, rm->ncols, fp) < 0) {
367 >            if (fwritecolrs(scan, rm->ncols, fp) < 0) {
368                  free(scan);
369                  return(0);
370              }
# Line 380 | Line 380 | rmx_write(const RMATRIX *rm, int dtype, FILE *fp)
380          RMATRIX *mydm = NULL;
381          int     ok = 1;
382  
383 <        if ((rm == NULL) | (fp == NULL))
383 >        if (!rm | !fp)
384                  return(0);
385 + #ifdef getc_unlocked
386 +        flockfile(fp);
387 + #endif
388                                                  /* complete header */
389          if (rm->info)
390                  fputs(rm->info, fp);
# Line 401 | Line 404 | rmx_write(const RMATRIX *rm, int dtype, FILE *fp)
404                          return(0);
405                  cmtx[0] = cmtx[1] = cmtx[2] = 1;
406                  mydm = rmx_transform(rm, 3, cmtx);
407 <                if (mydm == NULL)
407 >                if (!mydm)
408                          return(0);
409                  rm = mydm;
410          }
411 +        if ((dtype == DTfloat) | (dtype == DTdouble))
412 +                fputendian(fp);                 /* important to record */
413          fputformat((char *)cm_fmt_id[dtype], fp);
414          fputc('\n', fp);
415          switch (dtype) {                        /* write data */
# Line 426 | Line 431 | rmx_write(const RMATRIX *rm, int dtype, FILE *fp)
431                  return(0);
432          }
433          ok &= (fflush(fp) == 0);
434 <        rmx_free(mydm);
434 > #ifdef getc_unlocked
435 >        funlockfile(fp);
436 > #endif
437 >        if (mydm)
438 >                rmx_free(mydm);
439          return(ok);
440   }
441  
# Line 437 | Line 446 | rmx_identity(const int dim, const int n)
446          RMATRIX *rid = rmx_alloc(dim, dim, n);
447          int     i, k;
448  
449 <        if (rid == NULL)
449 >        if (!rid)
450                  return(NULL);
451          memset(rid->mtx, 0, sizeof(rid->mtx[0])*n*dim*dim);
452          for (i = dim; i--; )
# Line 452 | Line 461 | rmx_copy(const RMATRIX *rm)
461   {
462          RMATRIX *dnew;
463  
464 <        if (rm == NULL)
464 >        if (!rm)
465                  return(NULL);
466          dnew = rmx_alloc(rm->nrows, rm->ncols, rm->ncomp);
467 <        if (dnew == NULL)
467 >        if (!dnew)
468                  return(NULL);
469          rmx_addinfo(dnew, rm->info);
470          dnew->dtype = rm->dtype;
# Line 471 | Line 480 | rmx_transpose(const RMATRIX *rm)
480          RMATRIX *dnew;
481          int     i, j, k;
482  
483 <        if (rm == NULL)
483 >        if (!rm)
484                  return(0);
485 +        if ((rm->nrows == 1) | (rm->ncols == 1)) {
486 +                dnew = rmx_copy(rm);
487 +                if (!dnew)
488 +                        return(NULL);
489 +                dnew->nrows = rm->ncols;
490 +                dnew->ncols = rm->nrows;
491 +                return(dnew);
492 +        }
493          dnew = rmx_alloc(rm->ncols, rm->nrows, rm->ncomp);
494 <        if (dnew == NULL)
494 >        if (!dnew)
495                  return(NULL);
496          if (rm->info) {
497                  rmx_addinfo(dnew, rm->info);
# Line 495 | Line 512 | rmx_multiply(const RMATRIX *m1, const RMATRIX *m2)
512          RMATRIX *mres;
513          int     i, j, k, h;
514  
515 <        if ((m1 == NULL) | (m2 == NULL) ||
499 <                        (m1->ncomp != m2->ncomp) | (m1->ncols != m2->nrows))
515 >        if (!m1 | !m2 || (m1->ncomp != m2->ncomp) | (m1->ncols != m2->nrows))
516                  return(NULL);
517          mres = rmx_alloc(m1->nrows, m2->ncols, m1->ncomp);
518 <        if (mres == NULL)
518 >        if (!mres)
519                  return(NULL);
520          i = rmx_newtype(m1->dtype, m2->dtype);
521          if (i)
# Line 511 | Line 527 | rmx_multiply(const RMATRIX *m1, const RMATRIX *m2)
527                  for (k = mres->ncomp; k--; ) {
528                      long double d = 0;
529                      for (h = m1->ncols; h--; )
530 <                        d += (long double)rmx_lval(m1,i,h,k) *
515 <                                (long double)rmx_lval(m2,h,j,k);
530 >                        d += rmx_lval(m1,i,h,k) * rmx_lval(m2,h,j,k);
531                      rmx_lval(mres,i,j,k) = (double)d;
532                  }
533          return(mres);
534   }
535  
536 + /* Element-wise multiplication (or division) of m2 into m1 */
537 + int
538 + rmx_elemult(RMATRIX *m1, const RMATRIX *m2, int divide)
539 + {
540 +        int     zeroDivides = 0;
541 +        int     i, j, k;
542 +
543 +        if (!m1 | !m2 || (m1->ncols != m2->ncols) | (m1->nrows != m2->nrows))
544 +                return(0);
545 +        if ((m2->ncomp > 1) & (m2->ncomp != m1->ncomp))
546 +                return(0);
547 +        i = rmx_newtype(m1->dtype, m2->dtype);
548 +        if (i)
549 +                m1->dtype = i;
550 +        else
551 +                rmx_addinfo(m1, rmx_mismatch_warn);
552 +        for (i = m1->nrows; i--; )
553 +            for (j = m1->ncols; j--; )
554 +                if (divide) {
555 +                    double      d;
556 +                    if (m2->ncomp == 1) {
557 +                        d = rmx_lval(m2,i,j,0);
558 +                        if (d == 0) {
559 +                            ++zeroDivides;
560 +                            for (k = m1->ncomp; k--; )
561 +                                rmx_lval(m1,i,j,k) = 0;
562 +                        } else {
563 +                            d = 1./d;
564 +                            for (k = m1->ncomp; k--; )
565 +                                rmx_lval(m1,i,j,k) *= d;
566 +                        }
567 +                    } else
568 +                        for (k = m1->ncomp; k--; ) {
569 +                            d = rmx_lval(m2,i,j,k);
570 +                            if (d == 0) {
571 +                                ++zeroDivides;
572 +                                rmx_lval(m1,i,j,k) = 0;
573 +                            } else
574 +                                rmx_lval(m1,i,j,k) /= d;
575 +                        }
576 +                } else {
577 +                    if (m2->ncomp == 1) {
578 +                        const double    d = rmx_lval(m2,i,j,0);
579 +                        for (k = m1->ncomp; k--; )
580 +                            rmx_lval(m1,i,j,k) *= d;
581 +                    } else
582 +                        for (k = m1->ncomp; k--; )
583 +                            rmx_lval(m1,i,j,k) *= rmx_lval(m2,i,j,k);
584 +                }
585 +        if (zeroDivides) {
586 +                rmx_addinfo(m1, "WARNING: zero divide(s) corrupted results\n");
587 +                errno = ERANGE;
588 +        }
589 +        return(1);
590 + }
591 +
592   /* Sum second matrix into first, applying scale factor beforehand */
593   int
594   rmx_sum(RMATRIX *msum, const RMATRIX *madd, const double sf[])
# Line 525 | Line 596 | rmx_sum(RMATRIX *msum, const RMATRIX *madd, const doub
596          double  *mysf = NULL;
597          int     i, j, k;
598  
599 <        if ((msum == NULL) | (madd == NULL) ||
599 >        if (!msum | !madd ||
600                          (msum->nrows != madd->nrows) |
601                          (msum->ncols != madd->ncols) |
602                          (msum->ncomp != madd->ncomp))
603                  return(0);
604 <        if (sf == NULL) {
604 >        if (!sf) {
605                  mysf = (double *)malloc(sizeof(double)*msum->ncomp);
606 <                if (mysf == NULL)
606 >                if (!mysf)
607                          return(0);
608                  for (k = msum->ncomp; k--; )
609                          mysf[k] = 1;
# Line 547 | Line 618 | rmx_sum(RMATRIX *msum, const RMATRIX *madd, const doub
618              for (j = msum->ncols; j--; )
619                  for (k = msum->ncomp; k--; )
620                       rmx_lval(msum,i,j,k) += sf[k] * rmx_lval(madd,i,j,k);
621 <
622 <        free(mysf);
621 >        if (mysf)
622 >                free(mysf);
623          return(1);
624   }
625  
# Line 558 | Line 629 | rmx_scale(RMATRIX *rm, const double sf[])
629   {
630          int     i, j, k;
631  
632 <        if ((rm == NULL) | (sf == NULL))
632 >        if (!rm | !sf)
633                  return(0);
634          for (i = rm->nrows; i--; )
635              for (j = rm->ncols; j--; )
636                  for (k = rm->ncomp; k--; )
637                      rmx_lval(rm,i,j,k) *= sf[k];
638  
639 +        if (rm->info)
640 +                rmx_addinfo(rm, "Applied scalar\n");
641          return(1);
642   }
643  
# Line 575 | Line 648 | rmx_transform(const RMATRIX *msrc, int n, const double
648          int     i, j, ks, kd;
649          RMATRIX *dnew;
650  
651 <        if ((msrc == NULL) | (n <= 0) | (cmat == NULL))
651 >        if (!msrc | (n <= 0) | !cmat)
652                  return(NULL);
653          dnew = rmx_alloc(msrc->nrows, msrc->ncols, n);
654 <        if (dnew == NULL)
654 >        if (!dnew)
655                  return(NULL);
656 +        if (msrc->info) {
657 +                char    buf[128];
658 +                sprintf(buf, "Applied %dx%d matrix transform\n",
659 +                                dnew->ncomp, msrc->ncomp);
660 +                rmx_addinfo(dnew, msrc->info);
661 +                rmx_addinfo(dnew, buf);
662 +        }
663          dnew->dtype = msrc->dtype;
664          for (i = dnew->nrows; i--; )
665              for (j = dnew->ncols; j--; )
# Line 599 | Line 679 | rmx_from_cmatrix(const CMATRIX *cm)
679          int     i, j;
680          RMATRIX *dnew;
681  
682 <        if (cm == NULL)
682 >        if (!cm)
683                  return(NULL);
684          dnew = rmx_alloc(cm->nrows, cm->ncols, 3);
685 <        if (dnew == NULL)
685 >        if (!dnew)
686                  return(NULL);
687          dnew->dtype = DTfloat;
688          for (i = dnew->nrows; i--; )
# Line 622 | Line 702 | cm_from_rmatrix(const RMATRIX *rm)
702          int     i, j;
703          CMATRIX *cnew;
704  
705 <        if (rm == NULL || rm->ncomp != 3)
705 >        if (!rm || rm->ncomp != 3)
706                  return(NULL);
707          cnew = cm_alloc(rm->nrows, rm->ncols);
708 <        if (cnew == NULL)
708 >        if (!cnew)
709                  return(NULL);
710          for (i = cnew->nrows; i--; )
711              for (j = cnew->ncols; j--; ) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines