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

Comparing ray/src/util/rcomb.c (file contents):
Revision 2.22 by greg, Tue Jun 4 22:05:23 2024 UTC vs.
Revision 2.35 by greg, Thu Oct 30 16:46:49 2025 UTC

# Line 21 | Line 21 | static const char RCSid[] = "$Id$";
21   #define M_PI    3.14159265358979323846
22   #endif
23  
24 #define MAXCOMP         MAXCSAMP        /* #components we support */
25
24   /* Unary matrix operation(s) */
25   typedef struct {
26          double          cmat[MAXCOMP*MAXCOMP];  /* component transformation */
# Line 64 | Line 62 | int            inchild = -1;                   /* our child ID (-1: parent) */
62  
63   extern int      checksymbolic(ROPMAT *rop);
64  
65 + /* Split input matrices to allow for certain operations */
66   int
67   split_input(ROPMAT *rop)
68   {
# Line 174 | Line 173 | xyzrow(ROPMAT *rop, int r, int p)
173  
174   /* Use the spectral sensitivity function to compute matrix coefficients */
175   void
176 < sensrow(ROPMAT *rop, int r, double (*sf)(SCOLOR sc, int ncs, const float wlpt[4]))
176 > sensrow(ROPMAT *rop, int r, double (*sf)(const SCOLOR sc, int ncs, const float wlpt[4]))
177   {
178          const int       nc = rop->imx.ncomp;
179          int             i;
# Line 196 | Line 195 | checksymbolic(ROPMAT *rop)
195          double          cf = 1;
196          int             i, j;
197                                          /* check suffix => reference file */
198 <        if (strchr(rop->preop.csym, '.') > rop->preop.csym)
198 >        if (strchr(rop->preop.csym, '.') != NULL)
199                  return(checkreffile(rop));
200  
201          if (nc < 3) {
# Line 302 | Line 301 | checksymbolic(ROPMAT *rop)
301          return(1);
302   }
303  
304 + /* Set up color transform for matrix */
305   int
306   get_component_xfm(ROPMAT *rop)
307   {
# Line 385 | Line 385 | get_component_xfm(ROPMAT *rop)
385          return(1);
386   }
387  
388 + /* Apply the given color transform and/or scaling operation */
389   int
390   apply_op(RMATRIX *dst, const RMATRIX *src, const RUNARYOP *ro)
391   {
# Line 404 | Line 405 | apply_op(RMATRIX *dst, const RMATRIX *src, const RUNAR
405          return(1);
406   }
407  
408 + /* Open the associated input file and load/check header */
409   int
410   open_input(ROPMAT *rop)
411   {
# Line 417 | Line 419 | open_input(ROPMAT *rop)
419                  rop->infp = popen(rop->inspec+1, "r");
420          else
421                  rop->infp = fopen(rop->inspec, "rb");
422 <
422 >        
423 >        if (!rop->infp) {
424 >                fprintf(stderr, "Cannot open for reading: %s\n",
425 >                                rop->inspec);
426 >                return(0);
427 >        }
428          if (!rmx_load_header(&rop->imx, rop->infp)) {
429                  fprintf(stderr, "Bad header from: %s\n", rop->inspec);
430                  return(0);
# Line 475 | Line 482 | l_chanin(char *nam)
482          return(mop[mi].rmp->mtx[cur_col*in_ncomp + chan]);
483   }
484  
485 + /* Set up our operations and check consistency */
486   int
487   initialize(RMATRIX *imp)
488   {
# Line 488 | Line 496 | initialize(RMATRIX *imp)
496                  restype = mop[i].rmp->dtype;
497                  if (!imp->dtype || (restype = rmx_newtype(restype, imp->dtype)) > 0)
498                          imp->dtype = restype;
499 <                else
499 >                else if (!nowarn)
500                          fprintf(stderr, "%s: warning - data type mismatch\n",
501                                          mop[i].inspec);
502                  if (!i) {
# Line 522 | Line 530 | initialize(RMATRIX *imp)
530          return(1);
531   }
532  
533 + /* Copy input header information to output header, indented */
534   void
535   output_headinfo(FILE *fp)
536   {
# Line 545 | Line 554 | output_headinfo(FILE *fp)
554          }
555   }
556  
557 + /* Spawn the indicated number of children and return 1 in parent */
558   int
559   spawned_children(int np)
560   {
# Line 552 | Line 562 | spawned_children(int np)
562  
563   #if defined(_WIN32) || defined(_WIN64)
564          if (np > 1) {
565 <                fputs("Warning: only one process under Windows\n", stderr);
565 >                if (!nowarn)
566 >                        fputs("Warning: only one process under Windows\n", stderr);
567                  np = 1;
568          } else
569   #endif
# Line 570 | Line 581 | spawned_children(int np)
581                  }
582          }
583                                  /* prep output row buffer(s) */
584 <        if (mcat || mop[nmats].preop.clen > 0) {
584 >        if (mop[nmats].preop.clen > 0) {
585                  if (!split_input(&mop[nmats]))  /* need separate buffer */
586 <                        return(0);
587 <                if (mop[nmats].preop.clen > 0)
588 <                        mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
578 <                                                mop[nmats].imx.ncomp;
586 >                        goto memerror;
587 >                mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
588 >                                        mop[nmats].imx.ncomp;
589          }
590          mop[nmats].imx.nrows = 1;
591          if (!rmx_prepare(&mop[nmats].imx))
# Line 600 | Line 610 | spawned_children(int np)
610                  goto memerror;
611          for (i = nchildren; i--; ) cproc[i] = sp_inactive;
612          cproc[nchildren-1].flags |= PF_FILT_OUT;
613 <                                /* start each child */
614 <        for (i = 0; i < nchildren; i++) {
615 <                rv = open_process(&cproc[i], NULL);
616 <                if (rv <= 0) break;
607 <        }
613 >                                /* start each child from parent */
614 >        for (i = 0; i < nchildren; i++)
615 >                if ((rv = open_process(&cproc[i], NULL)) <= 0)
616 >                        break;  /* child breaks here */
617          if (rv < 0) {
618 <                perror("fork");
618 >                perror("fork"); /* WTH? */
619                  close_processes(cproc, i);
620                  exit(1);
621          }
622 <        if (rv) {               /* are we the parent? */
623 <                i = nchildren-1;        /* last child is sole reader */
624 <                while (i-- > 0) {
625 <                        close(cproc[i].r);
626 <                        cproc[i].r = -1;
622 >        if (i != nchildren-1) { /* last child is sole reader */
623 >                int     j = i;
624 >                while (j-- > 0) {
625 >                        close(cproc[j].r);
626 >                        cproc[j].r = -1;
627                  }
619                return(1);      /* parent return value */
628          }
629 <        inchild = i;            /* our child index */
629 >        if (rv > 0)
630 >                return(1);      /* parent return value */
631 >
632 >        inchild = i;            /* else set our child index */
633          while (i-- > 0)         /* only parent writes siblings */
634                  close(cproc[i].w);
635  
636 +        i = nmats;              /* close matrix streams (carefully) */
637 +        while (i-- > 0) {
638 +                if (mop[i].infp != stdin) {
639 +                        close(fileno(mop[i].infp));     /* avoid lseek() */
640 +                        fclose(mop[i].infp);            /* ! pclose() */
641 +                }
642 +                mop[i].infp = NULL;
643 +        }
644 +        fpurge(stdin);          /* discard previously buffered input */
645 +
646          if (inchild == nchildren-1)
647                  return(-1);     /* output process return value */
648  
649 <        i = inchild;            /* won't read from siblings */
629 <        while (i-- > 0)
630 <                close(cproc[i].r);
631 <        i = nmats;              /* redirect input matrix streams */
649 >        i = nmats;              /* get matrix rows from parent */
650          while (i-- > 0) {
633                if (mop[i].infp != stdin)
634                        fclose(mop[i].infp);    /* ! pclose() */
651                  mop[i].infp = stdin;
652                  mop[i].imx.dtype = DTrmx_native;
653                  mop[i].imx.pflags &= ~RMF_SWAPIN;
654          }
639        fpurge(stdin);          /* discard any previous matrix input */
655   #ifdef getc_unlocked
656          flockfile(stdin);
657   #endif
# Line 647 | Line 662 | memerror:
662          exit(1);
663   }
664  
665 + /* Run parental feeder loop */
666   int
667   parent_loop(void)
668   {
# Line 668 | Line 684 | parent_loop(void)
684                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
685                          if (cur_row > in_nrows) /* unknown #input rows? */
686                                  break;
687 <                        fprintf(stderr, "%s: parent read error at row %d\n",
687 >                        fprintf(stderr, "%s: load error at row %d\n",
688                                          mop[i].inspec, cur_row);
689                          return(0);
690                  }
# Line 676 | Line 692 | parent_loop(void)
692                  break;
693              for (i = 0; i < nmats; i++)
694                  if (writebuf(wfd, mop[i].imx.mtx, rmx_array_size(&mop[i].imx))
695 <                                        != rmx_array_size(&mop[i].imx))
695 >                                        != rmx_array_size(&mop[i].imx)) {
696 >                        fprintf(stderr, "%s: write error at row %d\n",
697 >                                        mop[i].inspec, cur_row);
698                          return(0);
699 +                }
700          }
701 <        i = close_processes(cproc, nchildren);
701 >        i = close_processes(cproc, nchildren);  /* collect family */
702          free(cproc); cproc = NULL; nchildren = 0;
703          if (i < 0) {
704 <                fputs("Warning: lost child in parent_loop()\n", stderr);
704 >                if (!nowarn)
705 >                        fputs("Warning: lost child process\n", stderr);
706                  return(1);
707          }
708          if (i > 0) {
# Line 690 | Line 710 | parent_loop(void)
710                  return(0);
711          }
712          return(1);                              /* return success! */
693 memerror:
694        fputs("Out of memory in parent_loop()\n", stderr);
695        exit(1);
713   }
714  
715 + /* Main operation loop, may be run in each child */
716   int
717   combine_input(void)
718   {
# Line 706 | Line 724 | combine_input(void)
724          int             co_set;
725          int             i;
726  
727 <        if (mcat && mcat_last &&
728 <                        !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp)))
729 <                goto memerror;
727 >        if (mcat_last && !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp))) {
728 >                fputs("Out of buffer space in combine_input()\n", stderr);
729 >                return(0);
730 >        }
731                                          /* figure out what the user set */
732          co_set = fundefined("co");
733          if (!co_set)
# Line 730 | Line 749 | combine_input(void)
749                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
750                          if (cur_row > in_nrows) /* unknown #input rows? */
751                                  break;
752 <                        fprintf(stderr, "%s: read error at row %d\n",
752 >                        fprintf(stderr, "%s: load error at row %d\n",
753                                          mop[i].inspec, cur_row);
754                          return(0);
755                  }
# Line 776 | Line 795 | combine_input(void)
795              }
796              rmx_free(mres); mres = NULL;
797              if (!rmx_write_data(res->rmp->mtx, res->rmp->ncomp,
798 <                                res->rmp->ncols, res->rmp->dtype, stdout))
798 >                                res->rmp->ncols, res->rmp->dtype, stdout) ||
799 >                                 (inchild >= 0 && fflush(stdout) == EOF)) {
800 >                fprintf(stderr, "Conversion/write error at row %d\n",
801 >                                cur_row);
802                  return(0);
803 <            if (inchild >= 0 && fflush(stdout) == EOF)
782 <                return(0);
803 >            }
804          }
805          return(inchild >= 0 || fflush(stdout) != EOF);
785 memerror:
786        fputs("Out of buffer space in combine_input()\n", stderr);
787        return(0);
806   multerror:
807 <        fputs("Unexpected matrix multiply error in combine_input()\n", stderr);
807 >        fputs("Unexpected matrix multiply error\n", stderr);
808          return(0);
809   }
810  
811 + /* Run output process loop when #processes > 1 */
812   int
813   output_loop(void)
814   {
815          const size_t    row_size = rmx_array_size(mop[nmats].rmp);
797        int             i = nmats;
816          int             cur_child = 0;
817 +        int             i = nmats;
818  
819 <        if (mop[nmats].rmp != &mop[nmats].imx)          /* output is split? */
801 <                rmx_reset(&mop[nmats].imx);
802 <        while (i-- > 0) {                               /* close input matrices */
803 <                fclose(mop[i].infp);            /* ! pclose() */
804 <                mop[i].infp = NULL;
819 >        while (i-- > 0) {                               /* free input buffers */
820                  rmx_reset(&mop[i].imx);
821                  if (mop[i].rmp != &mop[i].imx) {
822                          rmx_free(mop[i].rmp);
823                          mop[i].rmp = &mop[i].imx;
824                  }
825          }
826 +        if (mop[nmats].rmp != &mop[nmats].imx)          /* output is split? */
827 +                rmx_reset(&mop[nmats].imx);
828   #ifdef getc_unlocked
829          flockfile(stdout);                              /* we own this, now */
830   #endif
# Line 817 | Line 834 | output_loop(void)
834                  if (!rv)                                /* out of rows? */
835                          break;
836                  if (rv != row_size) {
837 <                        fputs("Read error in output loop\n", stderr);
837 >                        fputs("Read error\n", stderr);
838                          return(0);
839                  }                                       /* do final conversion */
840                  if (!rmx_write_data(mop[nmats].rmp->mtx, mop[nmats].rmp->ncomp,
841                                  mop[nmats].rmp->ncols, mop[nmats].rmp->dtype, stdout)) {
842 <                        fputs("Conversion/write error in output loop\n", stderr);
842 >                        fputs("Conversion/write error\n", stderr);
843                          return(0);
844                  }
845                  cur_child++;
846 <                cur_child *= (cur_child < inchild);
846 >                cur_child *= (cur_child < inchild);     /* loop over workers */
847          }
848          return(fflush(stdout) != EOF);
849   }
850  
851 + /* Check/convert floating-point arguments following this */
852   int
853   get_factors(double da[], int n, char *av[])
854   {
# Line 841 | Line 859 | get_factors(double da[], int n, char *av[])
859          return(ac);
860   }
861  
862 + /* Resize/reallocate the input array as requested */
863   void
864   resize_inparr(int n2alloc)
865   {
# Line 848 | Line 867 | resize_inparr(int n2alloc)
867  
868          if (n2alloc == nall)
869                  return;
870 <        for (i = nall; i > n2alloc; i--) {
870 >        for (i = nall; i-- > n2alloc; ) {
871                  rmx_reset(&mop[i].imx);
872                  if (mop[i].rmp != &mop[i].imx)
873                          rmx_free(mop[i].rmp);
# Line 874 | Line 893 | main(int argc, char *argv[])
893          int             stdin_used = 0;
894          int             nproc = 1;
895          const char      *mcat_spec = NULL;
896 +        int             transpose_mcat = 0;
897          int             n2comp = 0;
898          uby8            comp_ndx[128];
899          int             i;
# Line 943 | Line 963 | main(int argc, char *argv[])
963                                  }
964                                  break;
965                          case 'C':
966 +                                mcat_last = 0;
967                                  if (!n || isflt(argv[i+1]))
968                                          goto userr;
969                                  defCsym = mop[nmats].preop.csym = argv[++i];
970                                  mop[nmats].preop.clen = 0;
950                                mcat_last = 0;
971                                  break;
972                          case 'c':
973 +                                mcat_last = 0;
974                                  if (n && !isflt(argv[i+1])) {
975                                          mop[nmats].preop.csym = argv[++i];
976                                          mop[nmats].preop.clen = 0;
956                                        mcat_last = 0;
977                                          break;
978                                  }
979                                  if (n > MAXCOMP*MAXCOMP) n = MAXCOMP*MAXCOMP;
# Line 966 | Line 986 | main(int argc, char *argv[])
986                                          goto userr;
987                                  }
988                                  mop[nmats].preop.csym = NULL;
969                                mcat_last = 0;
989                                  break;
990                          case 'm':
991                                  if (!n) goto userr;
992 +                                mcat_last = 1;
993 +                                transpose_mcat = (argv[i][2] == 't');
994                                  if (argv[++i][0] == '-' && !argv[i][1]) {
995                                          if (stdin_used++) goto stdin_error;
996                                          mcat_spec = stdin_name;
997                                  } else
998                                          mcat_spec = argv[i];
978                                mcat_last = 1;
999                                  break;
1000                          default:
1001                                  fprintf(stderr, "%s: unknown option '%s'\n",
# Line 989 | Line 1009 | main(int argc, char *argv[])
1009          }
1010          resize_inparr(nmats+1);         /* extra matrix at end for result */
1011          mop[nmats].inspec = "trailing_ops";
1012 <                                        /* load final concatenation matrix */
1013 <        if (mcat_spec && !(mcat = rmx_load(mcat_spec, RMPnone))) {
1014 <                fprintf(stderr, "%s: error loading concatenation matrix: %s\n",
1015 <                                argv[0], mcat_spec);
1016 <                return(1);
1012 >
1013 >        if (mcat_spec) {                /* load final concatenation matrix? */
1014 >                mcat = rmx_load(mcat_spec);
1015 >                if (!mcat) {
1016 >                        fprintf(stderr, "%s: error loading concatenation matrix: %s\n",
1017 >                                        argv[0], mcat_spec);
1018 >                        return(1);
1019 >                }
1020 >                if (transpose_mcat && !rmx_transpose(mcat)) {
1021 >                        fprintf(stderr, "%s: error transposing concatenation matrix: %s\n",
1022 >                                        argv[0], mcat_spec);
1023 >                        return(1);
1024 >                }
1025          }
1026                                          /* get/check inputs, set constants */
1027          if (!initialize(&mop[nmats].imx))
# Line 1033 | Line 1061 | main(int argc, char *argv[])
1061                          return(1);
1062                  mop[nmats].rmp->ncols = mcat->ncols;
1063          }
1064 + #if DTrmx_native==DTfloat
1065 +        if (outfmt == DTdouble)
1066 +                fprintf(stderr, "%s: warning - writing float result as double\n", argv[0]);
1067 + #endif
1068          newheader("RADIANCE", stdout);  /* write output header */
1069          if (echoheader)
1070                  output_headinfo(stdout);

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)