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

Comparing ray/src/util/rcomb.c (file contents):
Revision 2.20 by greg, Tue Jun 4 21:23:11 2024 UTC vs.
Revision 2.28 by greg, Fri Mar 28 00:06:36 2025 UTC

# Line 21 | Line 21 | static const char RCSid[] = "$Id$";
21   #define M_PI    3.14159265358979323846
22   #endif
23  
24 + #ifndef MAXCOMP
25   #define MAXCOMP         MAXCSAMP        /* #components we support */
26 + #endif
27  
28   /* Unary matrix operation(s) */
29   typedef struct {
# Line 62 | Line 64 | SUBPROC                *cproc = NULL;                  /* child process array */
64   int             nchildren = 0;                  /* # of child processes */
65   int             inchild = -1;                   /* our child ID (-1: parent) */
66  
67 < static int      checksymbolic(ROPMAT *rop);
67 > extern int      checksymbolic(ROPMAT *rop);
68  
69 < static int
69 > int
70   split_input(ROPMAT *rop)
71   {
72          if (rop->rmp == &rop->imx && !(rop->rmp = rmx_copy(&rop->imx))) {
# Line 76 | Line 78 | split_input(ROPMAT *rop)
78   }
79  
80   /* Check/set transform based on a reference input file */
81 < static int
81 > int
82   checkreffile(ROPMAT *rop)
83   {
84          static const char       *curRF = NULL;
# Line 139 | Line 141 | checkreffile(ROPMAT *rop)
141   }
142  
143   /* Compute conversion row from spectrum to one channel of RGB */
144 < static void
144 > void
145   rgbrow(ROPMAT *rop, int r, int p)
146   {
147          const int       nc = rop->imx.ncomp;
# Line 156 | Line 158 | rgbrow(ROPMAT *rop, int r, int p)
158   }
159  
160   /* Compute conversion row from spectrum to one channel of XYZ */
161 < static void
161 > void
162   xyzrow(ROPMAT *rop, int r, int p)
163   {
164          const int       nc = rop->imx.ncomp;
# Line 173 | Line 175 | xyzrow(ROPMAT *rop, int r, int p)
175   }
176  
177   /* Use the spectral sensitivity function to compute matrix coefficients */
178 < static void
179 < sensrow(ROPMAT *rop, int r, double (*sf)(SCOLOR sc, int ncs, const float wlpt[4]))
178 > void
179 > sensrow(ROPMAT *rop, int r, double (*sf)(const SCOLOR sc, int ncs, const float wlpt[4]))
180   {
181          const int       nc = rop->imx.ncomp;
182          int             i;
# Line 188 | Line 190 | sensrow(ROPMAT *rop, int r, double (*sf)(SCOLOR sc, in
190   }
191  
192   /* Check/set symbolic transform */
193 < static int
193 > int
194   checksymbolic(ROPMAT *rop)
195   {
196          const int       nc = rop->imx.ncomp;
# Line 302 | Line 304 | checksymbolic(ROPMAT *rop)
304          return(1);
305   }
306  
307 < static int
307 > int
308   get_component_xfm(ROPMAT *rop)
309   {
310          int     i, j;
# Line 385 | Line 387 | get_component_xfm(ROPMAT *rop)
387          return(1);
388   }
389  
390 < static int
390 > int
391   apply_op(RMATRIX *dst, const RMATRIX *src, const RUNARYOP *ro)
392   {
393          if (ro->clen > 0) {
# Line 404 | Line 406 | apply_op(RMATRIX *dst, const RMATRIX *src, const RUNAR
406          return(1);
407   }
408  
409 < static int
409 > int
410   open_input(ROPMAT *rop)
411   {
412          int     outtype;
# Line 426 | Line 428 | open_input(ROPMAT *rop)
428   }
429  
430   /* Return nominal wavelength associated with input component (return nm) */
431 < static double
431 > double
432   l_wavelength(char *nam)
433   {
434          double  comp = argument(1);
# Line 450 | Line 452 | l_wavelength(char *nam)
452   }
453  
454   /* Return ith input with optional channel selector */
455 < static double
455 > double
456   l_chanin(char *nam)
457   {
458          double  inp = argument(1);
# Line 475 | Line 477 | l_chanin(char *nam)
477          return(mop[mi].rmp->mtx[cur_col*in_ncomp + chan]);
478   }
479  
480 < static int
480 > int
481   initialize(RMATRIX *imp)
482   {
483          int     i;
# Line 488 | Line 490 | initialize(RMATRIX *imp)
490                  restype = mop[i].rmp->dtype;
491                  if (!imp->dtype || (restype = rmx_newtype(restype, imp->dtype)) > 0)
492                          imp->dtype = restype;
493 <                else
493 >                else if (!nowarn)
494                          fprintf(stderr, "%s: warning - data type mismatch\n",
495                                          mop[i].inspec);
496                  if (!i) {
# Line 522 | Line 524 | initialize(RMATRIX *imp)
524          return(1);
525   }
526  
527 < static void
527 > void
528   output_headinfo(FILE *fp)
529   {
530          int     i;
# Line 545 | Line 547 | output_headinfo(FILE *fp)
547          }
548   }
549  
550 < static int
549 < output_loop(void)
550 < {
551 <        const size_t    row_size = rmx_array_size(mop[nmats].rmp);
552 <        int             i = nmats;
553 <        int             cur_child = 0;
554 <
555 <        if (mop[nmats].rmp != &mop[nmats].imx)          /* output is split? */
556 <                rmx_reset(&mop[nmats].imx);
557 <        while (i-- > 0) {                               /* close input matrices */
558 <                fclose(mop[i].infp);            /* ! pclose() */
559 <                mop[i].infp = NULL;
560 <                rmx_reset(&mop[i].imx);
561 <                if (mop[i].rmp != &mop[i].imx) {
562 <                        rmx_free(mop[i].rmp);
563 <                        mop[i].rmp = &mop[i].imx;
564 <                }
565 <        }
566 < #ifdef getc_unlocked
567 <        flockfile(stdout);                              /* we own this, now */
568 < #endif
569 <        for ( ; ; ) {                                   /* loop until no more */
570 <                ssize_t         rv;
571 <                rv = readbuf(cproc[cur_child].r, mop[nmats].rmp->mtx, row_size);
572 <                if (!rv)                                /* out of rows? */
573 <                        break;
574 <                if (rv != row_size) {
575 <                        fputs("Read error in output loop\n", stderr);
576 <                        return(0);
577 <                }                                       /* do final conversion */
578 <                if (!rmx_write_data(mop[nmats].rmp->mtx, mop[nmats].rmp->ncomp,
579 <                                mop[nmats].rmp->ncols, mop[nmats].rmp->dtype, stdout)) {
580 <                        fputs("Conversion/write error in output loop\n", stderr);
581 <                        return(0);
582 <                }
583 <                cur_child++;
584 <                cur_child *= (cur_child < inchild);
585 <        }
586 <        return(fflush(stdout) != EOF);
587 < }
588 <
589 < static int
550 > int
551   spawned_children(int np)
552   {
553          int     i, rv;
554  
555   #if defined(_WIN32) || defined(_WIN64)
556          if (np > 1) {
557 <                fputs("Warning: only one process under Windows\n", stderr);
557 >                if (!nowarn)
558 >                        fputs("Warning: only one process under Windows\n", stderr);
559                  np = 1;
560          } else
561   #endif
# Line 611 | Line 573 | spawned_children(int np)
573                  }
574          }
575                                  /* prep output row buffer(s) */
576 <        if (mcat || mop[nmats].preop.clen > 0) {
576 >        if (mop[nmats].preop.clen > 0) {
577                  if (!split_input(&mop[nmats]))  /* need separate buffer */
578 <                        return(0);
579 <                if (mop[nmats].preop.clen > 0)
580 <                        mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
619 <                                                mop[nmats].imx.ncomp;
578 >                        goto memerror;
579 >                mop[nmats].rmp->ncomp = mop[nmats].preop.clen /
580 >                                        mop[nmats].imx.ncomp;
581          }
582          mop[nmats].imx.nrows = 1;
583          if (!rmx_prepare(&mop[nmats].imx))
# Line 641 | Line 602 | spawned_children(int np)
602                  goto memerror;
603          for (i = nchildren; i--; ) cproc[i] = sp_inactive;
604          cproc[nchildren-1].flags |= PF_FILT_OUT;
605 <                                /* start each child */
606 <        for (i = 0; i < nchildren; i++) {
607 <                rv = open_process(&cproc[i], NULL);
608 <                if (rv <= 0) break;
648 <        }
605 >                                /* start each child from parent */
606 >        for (i = 0; i < nchildren; i++)
607 >                if ((rv = open_process(&cproc[i], NULL)) <= 0)
608 >                        break;  /* child breaks here */
609          if (rv < 0) {
610 <                perror("fork");
610 >                perror("fork"); /* WTH? */
611                  close_processes(cproc, i);
612                  exit(1);
613          }
614 <        if (rv) {               /* are we the parent? */
615 <                i = nchildren-1;        /* last child is sole reader */
616 <                while (i-- > 0)
617 <                        close(cproc[i].r);
618 <                return(1);      /* parent return value */
614 >        if (i != nchildren-1) { /* last child is sole reader */
615 >                int     j = i;
616 >                while (j-- > 0) {
617 >                        close(cproc[j].r);
618 >                        cproc[j].r = -1;
619 >                }
620          }
621 <        inchild = i;            /* our child index */
621 >        if (rv > 0)
622 >                return(1);      /* parent return value */
623 >
624 >        inchild = i;            /* else set our child index */
625          while (i-- > 0)         /* only parent writes siblings */
626                  close(cproc[i].w);
627  
628 <        if (inchild == nchildren-1)     /* last child sequences output */
629 <                exit(output_loop() ? 0 : 1);
628 >        i = nmats;              /* close matrix streams (carefully) */
629 >        while (i-- > 0) {
630 >                if (mop[i].infp != stdin) {
631 >                        close(fileno(mop[i].infp));     /* avoid lseek() */
632 >                        fclose(mop[i].infp);            /* ! pclose() */
633 >                }
634 >                mop[i].infp = NULL;
635 >        }
636 >        fpurge(stdin);          /* discard previously buffered input */
637  
638 <        i = inchild;            /* won't read from siblings */
639 <        while (i-- > 0)
640 <                close(cproc[i].r);
641 <        i = nmats;              /* close input matrix streams */
638 >        if (inchild == nchildren-1)
639 >                return(-1);     /* output process return value */
640 >
641 >        i = nmats;              /* get matrix rows from parent */
642          while (i-- > 0) {
672                if (mop[i].infp != stdin)
673                        fclose(mop[i].infp);    /* ! pclose() */
643                  mop[i].infp = stdin;
644                  mop[i].imx.dtype = DTrmx_native;
645                  mop[i].imx.pflags &= ~RMF_SWAPIN;
646          }
678        fpurge(stdin);          /* discard any previous matrix input */
647   #ifdef getc_unlocked
648          flockfile(stdin);
649   #endif
# Line 686 | Line 654 | memerror:
654          exit(1);
655   }
656  
657 < static int
657 > int
658   parent_loop(void)
659   {
660          int     i;
# Line 707 | Line 675 | parent_loop(void)
675                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
676                          if (cur_row > in_nrows) /* unknown #input rows? */
677                                  break;
678 <                        fprintf(stderr, "%s: parent read error at row %d\n",
678 >                        fprintf(stderr, "%s: load error at row %d\n",
679                                          mop[i].inspec, cur_row);
680                          return(0);
681                  }
# Line 715 | Line 683 | parent_loop(void)
683                  break;
684              for (i = 0; i < nmats; i++)
685                  if (writebuf(wfd, mop[i].imx.mtx, rmx_array_size(&mop[i].imx))
686 <                                        != rmx_array_size(&mop[i].imx))
686 >                                        != rmx_array_size(&mop[i].imx)) {
687 >                        fprintf(stderr, "%s: write error at row %d\n",
688 >                                        mop[i].inspec, cur_row);
689                          return(0);
690 +                }
691          }
692 <        i = close_processes(cproc, nchildren);
692 >        i = close_processes(cproc, nchildren);  /* collect family */
693          free(cproc); cproc = NULL; nchildren = 0;
694          if (i < 0) {
695 <                fputs("Warning: lost child in parent_loop()\n", stderr);
695 >                if (!nowarn)
696 >                        fputs("Warning: lost child process\n", stderr);
697                  return(1);
698          }
699          if (i > 0) {
# Line 729 | Line 701 | parent_loop(void)
701                  return(0);
702          }
703          return(1);                              /* return success! */
732 memerror:
733        fputs("Out of memory in parent_loop()\n", stderr);
734        exit(1);
704   }
705  
706 < static int
706 > int
707   combine_input(void)
708   {
709          const int       row0 = (inchild >= 0)*inchild;
# Line 745 | Line 714 | combine_input(void)
714          int             co_set;
715          int             i;
716  
717 <        if (mcat && mcat_last &&
718 <                        !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp)))
719 <                goto memerror;
717 >        if (mcat_last && !(tmp = rmx_alloc(1, res->imx.ncols, res->rmp->ncomp))) {
718 >                fputs("Out of buffer space in combine_input()\n", stderr);
719 >                return(0);
720 >        }
721                                          /* figure out what the user set */
722          co_set = fundefined("co");
723          if (!co_set)
# Line 769 | Line 739 | combine_input(void)
739                  if (!rmx_load_row(mop[i].imx.mtx, &mop[i].imx, mop[i].infp)) {
740                          if (cur_row > in_nrows) /* unknown #input rows? */
741                                  break;
742 <                        fprintf(stderr, "%s: read error at row %d\n",
742 >                        fprintf(stderr, "%s: load error at row %d\n",
743                                          mop[i].inspec, cur_row);
744                          return(0);
745                  }
# Line 815 | Line 785 | combine_input(void)
785              }
786              rmx_free(mres); mres = NULL;
787              if (!rmx_write_data(res->rmp->mtx, res->rmp->ncomp,
788 <                                res->rmp->ncols, res->rmp->dtype, stdout))
788 >                                res->rmp->ncols, res->rmp->dtype, stdout) ||
789 >                                 (inchild >= 0 && fflush(stdout) == EOF)) {
790 >                fprintf(stderr, "Conversion/write error at row %d\n",
791 >                                cur_row);
792                  return(0);
793 <            if (inchild >= 0 && fflush(stdout) == EOF)
821 <                return(0);
793 >            }
794          }
795          return(inchild >= 0 || fflush(stdout) != EOF);
824 memerror:
825        fputs("Out of buffer space in combine_input()\n", stderr);
826        return(0);
796   multerror:
797 <        fputs("Unexpected matrix multiply error in combine_input()\n", stderr);
797 >        fputs("Unexpected matrix multiply error\n", stderr);
798          return(0);
799   }
800  
801 < static int
801 > int
802 > output_loop(void)
803 > {
804 >        const size_t    row_size = rmx_array_size(mop[nmats].rmp);
805 >        int             cur_child = 0;
806 >        int             i = nmats;
807 >
808 >        while (i-- > 0) {                               /* free input buffers */
809 >                rmx_reset(&mop[i].imx);
810 >                if (mop[i].rmp != &mop[i].imx) {
811 >                        rmx_free(mop[i].rmp);
812 >                        mop[i].rmp = &mop[i].imx;
813 >                }
814 >        }
815 >        if (mop[nmats].rmp != &mop[nmats].imx)          /* output is split? */
816 >                rmx_reset(&mop[nmats].imx);
817 > #ifdef getc_unlocked
818 >        flockfile(stdout);                              /* we own this, now */
819 > #endif
820 >        for ( ; ; ) {                                   /* loop until no more */
821 >                ssize_t         rv;
822 >                rv = readbuf(cproc[cur_child].r, mop[nmats].rmp->mtx, row_size);
823 >                if (!rv)                                /* out of rows? */
824 >                        break;
825 >                if (rv != row_size) {
826 >                        fputs("Read error\n", stderr);
827 >                        return(0);
828 >                }                                       /* do final conversion */
829 >                if (!rmx_write_data(mop[nmats].rmp->mtx, mop[nmats].rmp->ncomp,
830 >                                mop[nmats].rmp->ncols, mop[nmats].rmp->dtype, stdout)) {
831 >                        fputs("Conversion/write error\n", stderr);
832 >                        return(0);
833 >                }
834 >                cur_child++;
835 >                cur_child *= (cur_child < inchild);     /* loop over workers */
836 >        }
837 >        return(fflush(stdout) != EOF);
838 > }
839 >
840 > int
841   get_factors(double da[], int n, char *av[])
842   {
843          int     ac;
# Line 839 | Line 847 | get_factors(double da[], int n, char *av[])
847          return(ac);
848   }
849  
850 < static void
850 > void
851   resize_inparr(int n2alloc)
852   {
853          int     i;
854  
855          if (n2alloc == nall)
856                  return;
857 <        for (i = nall; i > n2alloc; i--) {
857 >        for (i = nall; i-- > n2alloc; ) {
858                  rmx_reset(&mop[i].imx);
859                  if (mop[i].rmp != &mop[i].imx)
860                          rmx_free(mop[i].rmp);
# Line 941 | Line 949 | main(int argc, char *argv[])
949                                  }
950                                  break;
951                          case 'C':
952 +                                mcat_last = 0;
953                                  if (!n || isflt(argv[i+1]))
954                                          goto userr;
955                                  defCsym = mop[nmats].preop.csym = argv[++i];
956                                  mop[nmats].preop.clen = 0;
948                                mcat_last = 0;
957                                  break;
958                          case 'c':
959 +                                mcat_last = 0;
960                                  if (n && !isflt(argv[i+1])) {
961                                          mop[nmats].preop.csym = argv[++i];
962                                          mop[nmats].preop.clen = 0;
954                                        mcat_last = 0;
963                                          break;
964                                  }
965                                  if (n > MAXCOMP*MAXCOMP) n = MAXCOMP*MAXCOMP;
# Line 964 | Line 972 | main(int argc, char *argv[])
972                                          goto userr;
973                                  }
974                                  mop[nmats].preop.csym = NULL;
967                                mcat_last = 0;
975                                  break;
976                          case 'm':
977 +                                mcat_last = 1;
978                                  if (!n) goto userr;
979                                  if (argv[++i][0] == '-' && !argv[i][1]) {
980                                          if (stdin_used++) goto stdin_error;
981                                          mcat_spec = stdin_name;
982                                  } else
983                                          mcat_spec = argv[i];
976                                mcat_last = 1;
984                                  break;
985                          default:
986                                  fprintf(stderr, "%s: unknown option '%s'\n",
# Line 1042 | Line 1049 | main(int argc, char *argv[])
1049                  return(1);
1050          }
1051          doptimize(1);                   /* optimize definitions */
1052 <        if (spawned_children(nproc))    /* running in parent process? */
1052 >        i = spawned_children(nproc);    /* create multiple processes if requested */
1053 >        if (i > 0)                      /* running in parent process? */
1054                  return(parent_loop() ? 0 : 1);
1055 <                                        /* process & write rows */
1055 >        if (i < 0)                      /* running in output process? */
1056 >                return(output_loop() ? 0 : 1);
1057 >                                        /* else we are a worker process */
1058          return(combine_input() ? 0 : 1);
1059   stdin_error:
1060          fprintf(stderr, "%s: %s used for more than one input\n",

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines