home *** CD-ROM | disk | FTP | other *** search
- /* spline - interpolate points in a tabulated function
-
- Usage...
- usage: spline [infile] [options]
- or: spline infile [outfile] [options]
- options are:
- -a [step [start]] automatic abscissas
- -b break interpolation after each label
- -c general curve
- -i file interpolate at abscissas from the file. Only
- 1st number on each line of file is used -
- rest of line is ignored. Blank lines and
- lines starting with ';' are ignored.
- -n num interpolate over num intervals
- -q increase intervals fourfold
- -s [num [num]] specify slopes at beginning and end
- (where "n" implies "natural" boundary)
- -t num tension in interpolating curve
- -x [min [max]] interpolate from min to max
- -xt -yt -zt take atanh of x, y, or z values before
- interpolating. Data values are restricted
- to (0, 1). (-zt implies -3)
- -xl -yl -zl take log of x, y, or z values before
- interpolating. Data values are positive.
- (-zt implies -3)
- -3 3D curve: x, y, and z given for each points
-
- Notes...
- This program fits a smooth curve through a given set of points,
- using the splines under tension introduced by Schweikert [J.
- Math. and Physics v 45 pp 312-317 (1966)]. They are similar
- to cubic splines, but are less likely to introduce spurious
- inflection points.
-
- History...
- 11 Nov 92 Ver 2.9: -q yields EXACTLY four times the number
- of intervals. ';' anywhere in a data line starts
- a comment. Any line not starting with a number is
- a comment. Abscissas can be either decreasing or
- increasing.
- 10 Nov 92 Ver 2.8: Implemented implicit interpolation
- using zero().
- 31 Oct 92 Ver 2.7: Can specify only one slope.
- 18 Aug 92 Ver 2.6: Correctly handles two point curves.
- 11 Aug 92 Ver 2.5: Echos command line under Turbo C. atanh
- transformations implemented.
- 14 Jan 88 Ver 2.4: Fixed integer multiplication overflow in curv0
- which ruined end of large output files.
- 8 Jan 88 Ver 2.3: Fixed off-by-one bug in curv2 which sometimes
- permitted an out-of-range index near end of curve.
- Output file name can be specified on command line.
- Switches can appear anywhere on command line.
- 6 Jan 88 600 input points permitted.
- -- ver 2.2 --
- 5 Jan 88 numbers printed out with fixed width of 15 characters
- 15 Jun 87 echoes command line to output file.
- -- ver 2.1 --
- 25 Nov 86 3D
- -- ver 2.0 --
- 16 Oct 86 accepts desired abscissas from file.
- -- ver 1.4 --
- 7 Jun 86 echoes a 2-point line.
- 3 Jun 86 -s switch allows specified slopes at ends.
- 2 Jun 86 Ver 1.3: Fixed several embarrassing bugs in -b option.
- -q switch quadruples number of intervals.
- 6 Apr 86 -b switch breaks interpolation at labels.
- 21 Sep 85 Added -xl and -yl switches for taking logs
- 23 Nov 85 Passing lines starting with ';' unchanged, otherwise
- ignoring them.
- Bugs...
- Should have -e command for evenly spaced abscissas.
- -q switch should accept argument for desired fractional
- increase in # points.
- Should accept the output file as an optional second argument.
-
- Author...
- Copyright (c) 1985, 1986 James R. Van Zandt (jrv@mitre-bedford)
-
- All rights reserved.
- This program may be copied for personal, non-profit use only.
-
- Based on algorithms by A. K. Cline [Communications of the ACM
- v 17 n 4 pp 218-223 (Apr 74)].
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #define VERSION "2.9"
-
- #ifndef __TURBOC__
- #define __DESMET__
- #endif
-
- char *RIGHT= "Copyright (c) 1985 - 1992 James R. Van Zandt";
-
- #define TR(a) /* if(debugging) printf a /* debugging printouts */
-
- #define ENTRIES 600
- #define MAXLABELS 50
- #define BUFSIZE 200
-
- double *x, *y, *z, *temp, *xp, *yp, *zp, *path;
- double slp1=0.,slpn=0.,sigma=1.;
- double abscissa=0.;
- double abscissa_step=1.;
- double slope1=0.,slopen=0.; /* slopes supplied by user */
- double xmin=0.;
- double xmax=0.;
- double curv2(), mylog(), tanh(), atanh();
-
- int abscissa_arguments=0;
- int automatic_abscissas=0;
- int breaking=0; /* nonzero if breaking at labels */
- int curve=0; /* nonzero if general curve permitted */
- int debugging=0;
- int given_x=0; /* nonzero if x values are given in a file */
- int given_y=0; /* nonzero if y values are given in a file */
- int given_z=0; /* nonzero if z values are given in a file */
- int given_abscissas=0; /* nonzero if abscissas are given in a file
- (given_abscissas and given_x are equivalent if curve=0) */
- int labels=0; /* number of labels in input data */
- int quadruple=0; /* nonzero if user asking for 4 times the resolution */
- int specified_slope1=0; /* nonzero if first slope specified */
- int specified_slopen=0; /* nonzero if final slope specified */
- int threed=0; /* nonzero if 3D curve (x, y, and z given for each point) */
- int xlog=0; /* nonzero if taking log of x values */
- int ylog=0; /* nonzero if taking log of y values */
- int zlog=0; /* nonzero if taking log of z values */
- int xtanh=0; /* nonzero if taking tanh of x values */
- int ytanh=0; /* nonzero if taking tanh of y values */
- int ztanh=0; /* nonzero if taking tanh of z values */
-
- int x_arguments=0;
- int n; /* number of entries in x, y, yp, and temp */
- int index_array[MAXLABELS]; /* indexes into x and y */
- int *p_data=index_array;
- int total=100;
-
- FILE *ifile=stdin, *afile, *ofile=stdout;
-
- char buf[BUFSIZE];
- char *label_array[MAXLABELS];
- char **p_text=label_array;
- char newline[]="\n", nothing[]="", *leadin;
-
- main(argc,argv) int argc; char **argv;
- { int nn,origin;
- read_data(argc,argv);
- if(breaking && labels)
- {origin=0;
- while(labels--)
- {p_data[0] -= origin;
- nn=p_data[0]+1;
- if(quadruple) total=(nn-1)*4;
- if(nn) curv0(nn,total);
- origin += nn;
- path += nn;
- x += nn;
- y += nn;
- p_data++;
- p_text++;
- }
- }
- else
- {if(quadruple) total=(n-1)*4;
- curv0(n,total);
- }
- if(ofile!=stdout) fclose(ofile);
- }
-
- curv0(n,requested)
- int n,requested;
- { int i, j, each, stop, seg=0, regressing=0;
- double s, ds, xx, yy, zz;
- char *t;
-
- if(n<3)
- {for (j=0; j<n; j++)
- {xx=x[j]; if(xlog) xx=exp(xx); if(xtanh) xx = tanh(xx);
- yy=y[j]; if(ylog) yy=exp(yy); if(ytanh) yy = tanh(yy);
- fprintf(ofile, "%15.6g %15.6g ",xx,yy);
- if(threed)
- {zz=z[n-1]; if(zlog) zz=exp(zz); if(ztanh) zz = tanh(zz);
- fprintf(ofile, "%15.6g ",zz);
- }
- if(j==p_data[seg]) fputs(p_text[seg++], ofile);
- fputc('\n', ofile);
- }
- return;
- }
- if(path[n-1] < path[0])
- {reverse_array(x, n);
- reverse_array(y, n);
- if(threed) reverse_array(z, n);
- }
- for(i=1; i<n; i++) if(path[i]<=path[i-1]) regressing++;
- if (regressing)
- {fprintf(stderr,"ERROR: independent variable not strictly increasing\n");
- return;
- }
- if (curve && (xmin<0. || xmax>1.))
- {fprintf(stderr,"ERROR: independent variable not in range 0 to 1\n");
- return;
- }
- if(curve)
- {curv1(path,x,xp,n); curv1(path,y,yp,n);
- if(threed) curv1(path,z,zp,n);
- }
- else
- {slp1=slope1; slpn=slopen; curv1(x,y,yp,n);
- if(threed)
- {slp1=slpn=0.; curv1(x,z,zp,n);
- }
- }
- s=path[0];
- seg=0;
- if(requested<n) requested=n;
- if(given_abscissas || given_x || given_y || given_z)
- { /* abscissas specified in a file */
- int mini, maxi, numbers;
- double *target, *given, given_min, given_max, dif, tolerance, p=0.;
- char *inversion=0, *init_zero();
-
- leadin=nothing;
- if(given_x){target = &xx; given = x;}
- if(given_y){target = &yy; given = y;}
- if(given_z){target = &zz; given = z;}
- if(given_x || given_y || given_z)
- {given_min = given_max = given[0];
- mini = maxi = 0;
- for (i = 1; i < n; i++)
- {if(given[i] < given_min) given_min = given[mini=i];
- if(given[i] > given_max) given_max = given[maxi=i];
- }
- }
- while(fgets(buf,BUFSIZE,afile))
- {if(t = strchr(buf, ';'))
- *t = 0; /* ';' starts a comment */
- t=buf;
- while(*t && isspace(*t)) t++;
- if(*t == 0) continue; /* skip blank lines */
- numbers=sscanf(buf,"%lf",&s);
- if(numbers==0) continue; /* skip comment line */
-
- if(given_abscissas)
- {if(xlog) s=mylog(s);
- if(xtanh) s = atanh(s);
- if(s<path[0] || path[n-1]<s) continue; /* don't extrapolate */
- value(s, &xx, &yy, &zz, n);
- goto PRINTIT;
- }
- if(given_x)
- {if(xlog) s = mylog(s);
- else if(xtanh) s = atanh(s);
- }
- if(given_y)
- {if(ylog) s = mylog(s);
- else if(ytanh) s = atanh(s);
- }
- if(given_z)
- {if(zlog) s = mylog(s);
- else if(ztanh) s = atanh(s);
- }
- if((given_max - s)*(given_min - s) > 0.) continue; /* hopeless */
- inversion = init_zero(&p, inversion);
- p = path[mini]; zero(given_min - s, inversion);
- p = path[maxi]; zero(given_max - s, inversion);
- if(fabs(s) < 1.e-10) tolerance = 1.e-20;
- else tolerance = fabs(s)*1.e-6;
- do
- {value(p, &xx, &yy, &zz, n);
- dif = *target - s;
- if(fabs(dif) <= tolerance) goto PRINTIT;
- } while(!zero(dif, inversion));
- continue; /* search failed */
- PRINTIT:
-
- if(threed)
- fprintf(ofile, "%s%15.6g %15.6g %15.6g", leadin, xx, yy, zz);
- else
- fprintf(ofile, "%s%15.6g %15.6g", leadin, xx, yy);
- leadin=newline;
- }
- if(breaking && labels) fprintf(ofile, " %s\n",p_text[0]);
- else fprintf(ofile, " \"\"\n");
- rewind(afile);
- }
- else if(x_arguments==2) /* specific range was requested */
- {ds=(xmax-xmin)/requested;
- if(curve)
- {ds*=(path[n-1]-path[0]);
- s=xmin*(path[n-1]-path[0])+path[0];
- }
- else s=xmin;
- for(i=requested+1; i; i--)
- {value(s,&xx,&yy,&zz,n);
- if(threed) fprintf(ofile, "%15.6g %15.6g %15.6g ", xx, yy, zz);
- else fprintf(ofile, "%15.6g %15.6g ", xx, yy);
- if(j==p_data[seg]) fputs(p_text[seg++], ofile);
- fputc('\n', ofile);
- s+=ds;
- }
- }
- else /* spline for entire curve was requested */
- {for (i=j=0; j<n-1; j++)
- {stop=(int)((long)requested*(j+1)/(n-1));
- ds=(path[j+1]-path[j])/(stop-i);
- for ( ; i<stop; i++)
- {value(s,&xx,&yy,&zz,n);
- if(threed) fprintf(ofile, "%15.6g %15.6g %15.6g ", xx, yy, zz);
- else fprintf(ofile, "%15.6g %15.6g ",xx,yy);
- if(j==p_data[seg]) fputs(p_text[seg++], ofile);
- fputc('\n', ofile);
- s+=ds;
- }
- }
- xx=x[n-1]; if(xlog) xx=exp(xx); if(xtanh) xx = tanh(xx);
- yy=y[n-1]; if(ylog) yy=exp(yy); if(ytanh) yy = tanh(yy);
- if(threed)
- {zz=z[n-1]; if(zlog) zz=exp(zz); if(ztanh) zz = tanh(zz);
- fprintf(ofile, "%15.6g %15.6g %15.6g ", xx, yy, zz);
- }
- else fprintf(ofile, "%15.6g %15.6g ",xx,yy);
- if(j==p_data[seg]) fputs(p_text[seg++], ofile);
- fputc('\n', ofile);
- }
- }
-
- value(s,q,r,v,n) double s,*q,*r,*v; int n;
- { TR(("\nvalue(%f,,,%d)\n", s, n));
- if(curve)
- {*q=curv2(path,x,xp,s,n);
- *r=curv2(path,y,yp,s,n);
- if(threed) *v=curv2(path,z,zp,s,n);
- }
- else
- {*q=s;
- *r=curv2(x,y,yp,s,n);
- if(threed) *v=curv2(x,z,zp,s,n);
- }
- if(xlog) *q=exp(*q); if(xtanh) *q = tanh(*q);
- if(ylog) *r=exp(*r); if(ytanh) *r = tanh(*r);
- if(zlog) *v=exp(*v); if(ztanh) *v = tanh(*v);
- }
-
- char *gmem(n) int n;
- { char *p, *malloc();
- p=malloc(n);
- if(p==0)
- {fprintf(stderr, "out of memory"); exit(1);
- }
- return p;
- }
-
- reverse_array(x, n) double x[]; int n;
- {
- int i, j;
- double t;
- j = n - 1;
- for (i = 0; i < j; i++, j--)
- {
- t = x[i]; x[i] = x[j]; x[j] = t;
- }
- }
-
- read_data(argc,argv) int argc; char **argv;
- { int i, j, length, skipping, ac, numbers;
- double xx, yy, zz, ss, d, *pd, sum;
- char *s, *t, **av;
-
- x=path=(double *)gmem(ENTRIES*sizeof(double));
- y=(double *)gmem(ENTRIES*sizeof(double));
- argc--; argv++;
- /* handle switches on command line */
- ac=argc; av=argv; argc=0;
- while(ac>0)
- {if(**av=='?') help();
- if(**av=='-')
- {i=get_parameter(ac, av);
- av += i; ac -= i;
- }
- else {argv[argc++] = *av++; ac--;}
- }
- if(argc)
- {ifile=fopen(*argv,"r");
- if(ifile==0) {fprintf(stderr, "file %s not found\n",*argv); exit();}
- argc--; argv++;
- }
- if(argc)
- {unlink(*argv);
- ofile=fopen(*argv,"w");
- if(ofile==0) {fprintf(stderr, "can't open file %s\n",*argv); exit();}
- argc--; argv++;
- }
-
- fprint_cmd(ofile, "; spline %s\n");
-
- if(given_x && !curve){given_abscissas = 1; given_x = 0;}
- if(given_abscissas && curve){given_x = 1; given_abscissas = 0;}
- if(threed)
- z=(double *)gmem(ENTRIES*sizeof(double));
- if(sigma<=0.)
- {fprintf(stderr,"ERROR: tension must be positive\n");
- exit(1);
- }
- if((specified_slope1 || specified_slopen) && curve)
- {fprintf(stderr,"ERROR: slopes can\'t be specified for general curve\n");
- exit(1);
- }
- sigma *= -1.;
- if(xlog && !curve)
- {if(x_arguments>1) xmax=mylog(xmax);
- if(x_arguments>=1) xmin=mylog(xmin);
- }
- if(xtanh && !curve)
- {if(x_arguments>1) xmax=atanh(xmax);
- if(x_arguments>=1) xmin=atanh(xmin);
- }
- if(automatic_abscissas && abscissa_arguments<2 && x_arguments>=1)
- abscissa=xmin;
- p_data[0]=-1;
- skipping=2;
- if(automatic_abscissas) skipping--;
- if(threed) skipping++;
- i=0;
- while(i<ENTRIES)
- {if(fgets(buf,BUFSIZE,ifile)==0)break;
- if(buf[0]==';') {fprintf(ofile, "%s",buf); continue;} /* echo comment */
- buf[strlen(buf)-1]=0; /* zero out the line feed */
- if(t = strchr(buf, ';')) *t = 0; /* ';' starts a comment */
- t=buf;
- while(*t && isspace(*t)) t++;
- if(*t == 0) continue; /* skip blank lines */
- if(automatic_abscissas)
- {x[i]=abscissa;
- abscissa+=abscissa_step;
- if(threed) numbers=sscanf(buf,"%lf %lf",&y[i],&z[i]);
- else numbers=sscanf(buf,"%lf",&y[i]);
- if(numbers==0) continue;
- if(ylog) y[i]=mylog(y[i]);
- if(ytanh) y[i]=atanh(y[i]);
- if(zlog) z[i]=mylog(z[i]);
- if(ztanh) z[i]=atanh(z[i]);
- }
- else
- {if(threed) numbers=sscanf(buf,"%lf %lf %lf",&x[i],&y[i],&z[i]);
- else numbers=sscanf(buf,"%lf %lf",&x[i],&y[i]);
- if(numbers==0) continue;
- if(xlog) x[i]=mylog(x[i]); if(xtanh) x[i] = atanh(x[i]);
- if(ylog) y[i]=mylog(y[i]); if(ytanh) y[i] = atanh(y[i]);
- if(zlog) z[i]=mylog(z[i]); if(ztanh) z[i] = atanh(z[i]);
- }
- s=buf; /* start looking for label */
- for (j=skipping; j--; )
- {while(*s==' ')s++; /* skip a number */
- while(*s && (*s!=' '))s++;
- }
- while(*s==' ')s++;
- if((length=strlen(s))&&(labels<MAXLABELS))
- {if(*s=='\"') /* label in quotes */
- {t=s+1;
- while(*t && (*t!='\"')) t++;
- t++;
- }
- else /* label without quotes */
- {t=s;
- while(*t && (*t!=' '))t++;
- }
- *t=0;
- length=t-s;
- p_data[labels]=i;
- p_text[labels]=gmem(length+1);
- strcpy(p_text[labels++],s);
- }
- i++;
- }
- n=i;
- if(n==ENTRIES)
- fprintf(stderr, "WARNING: only the first %d input points are used\n",
- ENTRIES);
- if(breaking && (!labels || p_data[labels-1]!=n-1))
- {p_data[labels]=i-1;
- p_text[labels]=gmem(1);
- *p_text[labels++]=0;
- }
- yp=(double *)gmem(n*sizeof(double));
- temp=(double *)gmem(n*sizeof(double));
- if(threed)
- zp=(double *)gmem(n*sizeof(double));
- if(curve)
- {xp=(double *)gmem(n*sizeof(double));
- path=(double *)gmem(n*sizeof(double));
- path[0]=sum=0.;
- if(threed)
- for (i=1; i<n; i++)
- {xx=x[i]-x[i-1];
- yy=y[i]-y[i-1];
- zz=z[i]-z[i-1];
- path[i]=(sum+=sqrt(xx*xx + yy*yy + zz*zz));
- }
- else
- for (i=1; i<n; i++)
- {xx=x[i]-x[i-1];
- yy=y[i]-y[i-1];
- path[i]=(sum+=sqrt(xx*xx + yy*yy));
- }
- /* for(i=0; i<n; i++)
- printf("path[%d]=%g x[%d]=%g \n",i,path[i],i,x[i]); */
- }
- }
-
-
- /* get_parameter - process one command line option
- (return # parameters used) */
- get_parameter(argc,argv) int argc; char **argv;
- { int i;
- if(streq(*argv,"-a"))
- {i=get_double(argc,argv,2,&abscissa_step,&abscissa,&abscissa);
- abscissa_arguments=i-1;
- automatic_abscissas=1;
- return i;
- }
- else if(streq(*argv,"-b")) {breaking=1; return 1;}
- else if(streq(*argv,"-c")) {curve=1; return 1;}
- else if(streq(*argv,"-d")) {debugging=1; return 1;}
- else if(streq(*argv,"-i"))
- {if(argc>1)
- {afile=fopen(argv[1],"r");
- if(afile==0)
- {fprintf(stderr,"can\'t open abscissa file %s",argv[1]);
- exit(1);
- }
- given_abscissas=1;
- }
- return 2;
- }
- else if(streq(*argv,"-ix"))
- {if(argc>1)
- {afile=fopen(argv[1],"r");
- if(afile==0)
- {fprintf(stderr,"can\'t open abscissa file %s",argv[1]);
- exit(1);
- }
- given_x=1;
- }
- return 2;
- }
- else if(streq(*argv,"-iy"))
- {if(argc>1)
- {afile=fopen(argv[1],"r");
- if(afile==0)
- {fprintf(stderr,"can\'t open abscissa file %s",argv[1]);
- exit(1);
- }
- given_y=1;
- }
- return 2;
- }
- else if(streq(*argv,"-iz"))
- {if(argc>1)
- {afile=fopen(argv[1],"r");
- if(afile==0)
- {fprintf(stderr,"can\'t open abscissa file %s",argv[1]);
- exit(1);
- }
- threed=given_z=1;
- }
- return 2;
- }
- else if(streq(*argv,"-n"))
- {if((argc>1) && numeric(argv[1])) total=atoi(argv[1]);
- return 2;
- }
- else if(streq(*argv,"-q")) {quadruple=1; return 1;}
- else if(streq(*argv,"-t"))
- {return(get_double(argc,argv,1,&sigma,&abscissa,&abscissa));
- }
- else if(streq(*argv,"-s"))
- {if(streq(argv[1], "n")) i = 2;
- else
- {i = get_double(argc, argv, 1, &slope1,&slopen,&slopen);
- if(i == 1) return 1;
- specified_slope1 = 1;
- }
- argv++;
- argc--;
- if(streq(argv[1], "n")) i++;
- else
- {i += get_double(argc, argv, 1, &slopen,&slopen,&slopen) - 1;
- if(i > 2) specified_slopen = 1;
- }
- return i;
- }
- else if(streq(*argv,"-x"))
- {i=get_double(argc,argv,2,&xmin,&xmax,&xmax);
- x_arguments=i-1;
- return i;
- }
- else if(streq(*argv,"-xl")) {xlog=1; return 1;}
- else if(streq(*argv,"-yl")) {ylog=1; return 1;}
- else if(streq(*argv,"-zl")) {zlog=1; threed=1; return 1;}
- else if(streq(*argv,"-xt")) {xtanh=1; return 1;}
- else if(streq(*argv,"-yt")) {ytanh=1; return 1;}
- else if(streq(*argv,"-zt")) {ztanh=1; threed=1; return 1;}
- else if(streq(*argv,"-3")) {threed=1; return 1;}
- else gripe(argv);
- }
-
- get_double(argc,argv,permitted,a,b,c)
- int argc,permitted; char **argv; double *a,*b,*c;
- { int i=1;
- if((permitted--)>0 && (argc>i) && numeric(argv[i])) *a=atof(argv[i++]);
- if((permitted--)>0 && (argc>i) && numeric(argv[i])) *b=atof(argv[i++]);
- if((permitted--)>0 && (argc>i) && numeric(argv[i])) *c=atof(argv[i++]);
- return i;
- }
-
- int streq(a,b) char *a,*b;
- { while(*a)
- {if(*a!=*b)return 0;
- a++; b++;
- }
- return 1;
- }
-
- gripe_arg(s) char *s;
- { fprintf(stderr,"argument missing for switch %s",s);
- help();
- }
-
- gripe(argv) char **argv;
- { fprintf(stderr,*argv); fprintf(stderr," isn\'t a legal argument \n\n");
- help();
- }
-
- char *message[]=
- {"spline version ", VERSION,
- "\nusage: spline [infile] [options]\n",
- "or: spline infile [outfile] [options]\n",
- "options are:\n",
- " -a [step [start]] automatic abscissas \n",
- " -b break interpolation after each label \n",
- " -c general curve \n",
- " -i file explicit interpolation at abscissas from the file\n",
- " -ix file\n",
- " -iy file\n",
- " -iz file implicit interpolation at values from the file\n",
- " -n num interpolate over num intervals \n",
- " -q increase intervals fourfold \n",
- " -s [num [num]] specify slopes at beginning and end \n",
- " (\"n\" for \"natural\")\n",
- " -t num tension in interpolating curve \n",
- " -x [min [max]] interpolate from min to max \n",
- " -xt -yt -zt take atanh of x, y, or z values before\n",
- " interpolating. Data values are restricted\n",
- " to (0, 1). (-zt implies -3)\n",
- " -xl -yl -zl take log of x, y, or z values before\n",
- " interpolating. Data values are positive. \n",
- " (-zt implies -3)\n",
- " -3 3D curve: x, y, and z given for each points\n",
- 0
- };
-
- help()
- { char **s;
- for (s=message; *s; s++) printf(*s);
- exit();
- }
-
- numeric(s) char *s;
- { char c;
- while(c=*s++)
- {if((c<='9' && c>='0') || c=='+' || c=='-' || c=='.') continue;
- return 0;
- }
- return 1;
- }
-
- curv1(x,y,yp,n) double *x,*y,*yp; int n;
- { int i;
- double c1,c2,c3,deln,delnm1,delnn,dels,delx1,delx2,delx12;
- double diag1,diag2,diagin,dx1,dx2,exps;
- double sigmap,sinhs,sinhin,slpp1,slppn,spdiag;
-
- delx1=x[1] - x[0];
- dx1=(y[1] - y[0])/delx1;
-
- if(specified_slope1) slpp1 = slp1;
- else if(n!=2)
- {delx2= x[2] - x[1];
- delx12= x[2] - x[0];
- c1= -(delx12 + delx1)/delx12/delx1;
- c2= delx12/delx1/delx2;
- c3= -delx1/delx12/delx2;
- slpp1= c1*y[0] + c2*y[1] + c3*y[2];
- }
- else yp[0] = yp[1] = 0.;
-
- if(specified_slopen) slppn = slpn;
- else if(n!=2)
- {deln= x[n-1] - x[n-2];
- delnm1= x[n-2] - x[n-3];
- delnn= x[n-1] - x[n-3];
- c1= (delnn + deln)/delnn/deln;
- c2= -delnn/deln/delnm1;
- c3= deln/delnn/delnm1;
- slppn= c3*y[n-3] + c2*y[n-2] + c1*y[n-1];
- }
- else yp[0] = yp[1] = 0.;
- /* denormalize tension factor */
- sigmap=fabs(sigma)*(n-1)/(x[n-1]-x[0]);
- /* set up right hand side and tridiagonal system for
- yp and perform forward elimination */
- dels=sigmap*delx1;
- exps=exp(dels);
- sinhs=.5*(exps-1./exps);
- sinhin=1./(delx1*sinhs);
- diag1=sinhin*(dels*.5*(exps+1./exps)-sinhs);
- diagin=1./diag1;
- yp[0]=diagin*(dx1-slpp1);
- spdiag=sinhin*(sinhs-dels);
- temp[0]=diagin*spdiag;
- if(n!=2)
- {for(i=1; i<=n-2; i++)
- {delx2=x[i+1]-x[i];
- dx2=(y[i+1]-y[i])/delx2;
- dels=sigmap*delx2;
- exps=exp(dels);
- sinhs=.5*(exps-1./exps);
- sinhin=1./(delx2*sinhs);
- diag2=sinhin*(dels*(.5*(exps+1./exps))-sinhs);
- diagin=1./(diag1+diag2-spdiag*temp[i-1]);
- yp[i]=diagin*(dx2-dx1-spdiag*yp[i-1]);
- spdiag=sinhin*(sinhs-dels);
- temp[i]=diagin*spdiag;
- dx1=dx2;
- diag1=diag2;
- }
- }
- diagin=1./(diag1-spdiag*temp[n-2]);
- yp[n-1]=diagin*(slppn-dx2-spdiag*yp[n-2]);
- /* perform back substitution */
- for (i=n-2; i>=0; i--) yp[i] -= temp[i]*yp[i+1];
- }
-
-
- double curv2(x,y,yp,t,n) double *x,*y,*yp,t; int n;
- { int i,j;
- static int i1=1;
- double del1,del2,dels,exps,exps1,s,sigmap,sinhd1,sinhd2,sinhs;
-
- TR(("curv2( , , ,%f,%d)\n", t, n));
- s=x[n-1]-x[0];
- sigmap=fabs(sigma)*(n-1)/s;
- i=i1;
- if(i>n) i=1; /* want: x[i-1] <= t < x[i], 0 < i < n */
- while(i<n-1 && t>=x[i]) i++;
- while(i>1 && x[i-1]>t) i--;
- TR((" i=%d: x[i-1]=%f <= t=%f < x[i]=%f\n", i, x[i-1], t, x[i]));
- i1=i;
- del1=t-x[i-1];
- del2=x[i]-t;
- dels=x[i] - x[i-1];
- exps1=exp(sigmap*del1); sinhd1=.5*(exps1-1./exps1);
- exps= exp(sigmap*del2); sinhd2=.5*(exps-1./exps);
- exps=exps1*exps; sinhs=.5*(exps-1./exps);
- return ((yp[i]*sinhd1 + yp[i-1]*sinhd2)/sinhs +
- ((y[i] - yp[i])*del1 + (y[i-1] - yp[i-1])*del2)/dels);
- }
-
- double mylog(x) double x;
- { if(x>0.) return log(x);
- fprintf(stderr,"can't take log of nonpositive number");
- exit(1);
- return 0.;
- }
-
- /* return hyperbolic tangent of x */
- double tanh(x) double x;
- { double t;
- t = exp(x);
- return (t - 1./t)/(t + 1./t);
- }
-
- /* return inverse hyperbolic tangent of x */
- double atanh(x) double x;
- { if(x <= 0. || x >= 1.)
- {fprintf(stderr, "can't transform %f", x);
- exit(1);
- }
- return log(sqrt((1.+x)/(1.-x)));
- }
-
- /* write out the command line */
- fprint_cmd(fp, format)
- FILE *fp; /* pointer to output file */
- char *format; /* desired print format, possibly including program name */
- {
- #ifdef __DESMET__
- char buf[129];
- int i=0;
-
- _lmove(129, 130, _showcs()-0x10, &buf, _showds());
- buf[128]=13;
- while(buf[i] != 13) i++;
- buf[i]=0;
- fprintf(fp, format, buf);
- #endif
-
- #ifdef __TURBOC__
- #include <dos.h>
- char buf[129];
- char far *bufptr;
- int i=0;
-
- bufptr = buf;
- movedata(_psp, 130, FP_SEG(bufptr), FP_OFF(bufptr), 129);
- buf[128]=13;
- while(buf[i] != 13) i++;
- buf[i]=0;
- fprintf(fp, format, buf);
- #endif
- }
-