Back to index

radiance  4R0+20100331
tabfunc.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: tabfunc.c,v 1.6 2005/11/12 06:14:51 greg Exp $";
00003 #endif
00004 /*
00005  * Put tabular data into functions suitable for cal programs.
00006  *
00007  *     2/2/95 Greg Ward
00008  */
00009 
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <math.h>
00014 #include <ctype.h>
00015 #include <sys/types.h>
00016 
00017 #include "rtprocess.h" /* getpid() */
00018 #include "rtmath.h"
00019 #include "rtio.h"
00020 
00021 #define  isdelim(c)  (isspace(c) || (c)==',')
00022 
00023 #define  MAXTAB             1024          /* maximum number of data rows */
00024 #define  MAXLINE     4096          /* maximum line width (characters) */
00025 #define  OUTFMT             "%.7g"        /* output format conversion string */
00026 
00027 int    interpolate = 0;
00028 char   *progname;
00029 char   **func;
00030 int    nfuncs;
00031 
00032 RREAL  abscissa[MAXTAB];           /* independent values (first column) */
00033 RREAL  (*ordinate)[MAXTAB];        /* dependent values (other columns) */
00034 int    tabsize = 0;                /* final table size (number of rows) */
00035 char   locID[16];                  /* local identifier (for uniqueness) */
00036 
00037 /*extern char *fgets(), *fskip(), *absc_exp();*/
00038 
00039 static void load_data(FILE *fp);
00040 static void print_funcs(char *xe);
00041 static void putlist(register RREAL *av, int al, register int pos);
00042 static char * absc_exp(void);
00043 
00044 int
00045 main(
00046 int    argc,
00047 char   **argv
00048 )
00049 {
00050        progname = argv[0];
00051        argv++;
00052        argc--;
00053        if (argc && !strcmp(argv[0], "-i")) {
00054               interpolate++;
00055               puts("interp_arr2`(i,x,f):(i+1-x)*f(i)+(x-i)*f(i+1);");
00056               puts("interp_arr`(x,f):if(x-1,if(f(0)-x,interp_arr2`(floor(x),x,f),f(f(0))),f(1));");
00057               argv++;
00058               argc--;
00059        }
00060        if (!argc || argv[0][0] == '-') {
00061               fprintf(stderr, "Usage: %s [-i] func1 [func2 ..]\n", progname);
00062               exit(1);
00063        }
00064        func = argv;
00065        nfuncs = argc;
00066        ordinate = (RREAL (*)[MAXTAB])malloc(nfuncs*MAXTAB*sizeof(RREAL));
00067        if (ordinate == NULL) {
00068               fprintf(stderr, "%s: not enough memory\n", progname);
00069               exit(1);
00070        }
00071        sprintf(locID, "p%d", getpid());
00072        load_data(stdin);
00073        print_funcs(absc_exp());
00074        exit(0);
00075 }
00076 
00077 
00078 static void
00079 load_data(                  /* load tabular data from fp */
00080 FILE   *fp
00081 )
00082 {
00083        int    lineno;
00084        char   *err;
00085        char   inpbuf[MAXLINE];
00086        register char *cp;
00087        register int  i;
00088 
00089        tabsize = lineno = 0;
00090        inpbuf[MAXLINE-2] = '\n';
00091        while (fgets(inpbuf, MAXLINE, fp) != NULL) {
00092               lineno++;
00093               if (inpbuf[MAXLINE-2] != '\n') {
00094                      err = "line too long";
00095                      goto fatal;
00096               }
00097               if (tabsize >= MAXTAB-1) {
00098                      err = "too many rows";
00099                      goto fatal;
00100               }
00101               if ((cp = fskip(inpbuf)) == NULL)
00102                      continue;            /* skip non-data lines */
00103               abscissa[tabsize] = atof(inpbuf);
00104               for (i = 0; i < nfuncs; i++) {
00105                      while (isdelim(*cp))
00106                             cp++;
00107                      if (!*cp) {
00108                             err = "too few columns";
00109                             goto fatal;
00110                      }
00111                      ordinate[i][tabsize] = atof(cp);
00112                      if ((cp = fskip(cp)) == NULL) {
00113                             err = "bad floating-point format";
00114                             goto fatal;
00115                      }
00116               }
00117               tabsize++;
00118        }
00119        return;
00120 fatal:
00121        fprintf(stderr, "%s: input line %d: %s\n", progname, lineno, err);
00122        exit(1);
00123 }
00124 
00125 
00126 static char *
00127 absc_exp(void)                     /* produce expression for abscissa */
00128 {
00129        static char   ourexp[64];
00130        double step, eps;
00131        int    uniform, increasing;
00132        register int  i;
00133 
00134        if (tabsize < 2)
00135               return("1");
00136        step = abscissa[1] - abscissa[0];
00137        eps = ((increasing = (step > 0)) ? 1e-3 : -1e-3) * step;
00138        uniform = 1;
00139        for (i = 2; i < tabsize; i++) {
00140               if (uniform && fabs((abscissa[i]-abscissa[i-1]) - step) > eps)
00141                      uniform = 0;
00142               if (!uniform && (abscissa[i-1] < abscissa[i]) != increasing) {
00143                      fprintf(stderr, "%s: input not a function\n",
00144                                    progname);
00145                      exit(1);
00146               }
00147        }
00148        if (uniform) {
00149               if (increasing && fabs(step - 1) < eps) {
00150                      if (fabs(abscissa[0] - 1) < eps)
00151                             strcpy(ourexp, "x");
00152                      else
00153                             sprintf(ourexp, "x-%g", abscissa[0]-1);
00154               } else if (fabs(abscissa[0]) < eps)
00155                      sprintf(ourexp, "x/%g+1", step);
00156               else
00157                      sprintf(ourexp, "(x-%g)/%g+1", abscissa[0], step);
00158        } else {
00159               printf("X`%s(i):select(i,", locID);
00160               putlist(abscissa, tabsize, 20);
00161               puts(");");
00162               if (increasing) {
00163                      printf("fx`%s(x):if(x-%g,if(%g-x,fx2`%s(x,%d),%d),1);\n",
00164                                    locID, abscissa[0], abscissa[tabsize-1],
00165                                    locID, tabsize, tabsize);
00166                      printf("fx2`%s(x,i):if(x-X`%s(i),\n", locID, locID);
00167               } else {
00168                      printf("fx`%s(x):if(%g-x,if(x-%g,fx2`%s(x,%d),%d),1);\n",
00169                                    locID, abscissa[0], abscissa[tabsize-1],
00170                                    locID, tabsize, tabsize);
00171                      printf("fx2`%s(x,i):if(X`%s(i)-x,\n", locID, locID);
00172               }
00173               printf("\ti+(x-X`%s(i))/(X`%s(i+1)-X`%s(i)),\n",
00174                             locID, locID, locID);
00175               printf("\tfx2`%s(x,i-1));\n", locID);
00176               sprintf(ourexp, "fx`%s(x)", locID);
00177        }
00178        return(ourexp);
00179 }
00180 
00181 
00182 static void
00183 print_funcs(                /* print functions */
00184 char   *xe
00185 )
00186 {
00187        int    xelen;
00188        register int  i;
00189 
00190        xelen = strlen(xe);
00191        for (i = 0; i < nfuncs; i++) {
00192               if ((func[i][0] == '\0') | (func[i][0] == '0'))
00193                      continue;
00194               if (interpolate) {
00195                      printf("%s`%s(i):select(i,", func[i], locID);
00196                      putlist(ordinate[i], tabsize,
00197                                    27+strlen(func[i]));
00198                      puts(");");
00199                      printf("%s(x):interp_arr`(%s,%s`%s);\n",
00200                                    func[i], xe, func[i], locID);
00201               } else {
00202                      printf("%s(x):select(%s,", func[i], xe);
00203                      putlist(ordinate[i], tabsize, strlen(func[i])+xelen+12);
00204                      puts(");");
00205               }
00206        }
00207 }
00208 
00209 
00210 static void
00211 putlist(             /* put out array of values */
00212 register RREAL       *av,
00213 int    al,
00214 register int  pos
00215 )
00216 {
00217        char   obuf[32];
00218        int    len;
00219 
00220        while (al--) {
00221               sprintf(obuf, OUTFMT, *av++);
00222               pos += (len = strlen(obuf)+1);
00223               if (pos >= 64) {
00224                      putchar('\n');
00225                      pos = len;
00226               }
00227               fputs(obuf, stdout);
00228               if (al)
00229                      putchar(',');
00230        }
00231 }