|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <math.h>
4: #include <iplot.h>
5: #define INF 1.e+37
6: #define F .25
7:
8: struct xy {
9: int xlbf; /*flag:explicit lower bound*/
10: int xubf; /*flag:explicit upper bound*/
11: int xqf; /*flag:explicit quantum*/
12: double (*xf)(); /*transform function, e.g. log*/
13: float xa,xb; /*scaling coefficients*/
14: float xlb,xub; /*lower and upper bound*/
15: float xquant; /*quantum*/
16: float xoff; /*screen offset fraction*/
17: float xsize; /*screen fraction*/
18: int xbot,xtop; /*screen coords of border*/
19: float xmult; /*scaling constant*/
20: } xd,yd;
21: struct val {
22: float xv;
23: float yv;
24: int lblptr;
25: } *xx;
26:
27: char *labs;
28: int labsiz;
29:
30: int tick = 50;
31: int top = 4000;
32: int bot = 200;
33: float absbot;
34: int n;
35: int erasf = 1;
36: int gridf = 2;
37: int symbf = 0;
38: int absf = 0;
39: int transf;
40: int equf;
41: int brkf;
42: int ovlay = 1;
43: float dx;
44: char *plotsymb;
45:
46: double atof();
47: #define BSIZ 80
48: char labbuf[BSIZ];
49: char titlebuf[BSIZ];
50:
51: char *modes[] = {
52: "disconnected",
53: "solid",
54: "dotted",
55: "dotdashed",
56: "shortdashed",
57: "longdashed"
58: };
59: int mode = 1;
60: char *realloc();
61: char *malloc();
62:
63: double ident(x)
64: double x;
65: {
66: return(x);
67: }
68:
69: main(argc,argv)
70: char *argv[];
71: {
72:
73: openpl();
74: range(0,0,4096,4096);
75: init(&xd);
76: init(&yd);
77: xd.xsize = yd.xsize = 1.;
78: xx = (struct val *)malloc((unsigned)sizeof(struct val));
79: labs = malloc(1);
80: labs[labsiz++] = 0;
81: setopt(argc,argv);
82: if(erasf)
83: erase();
84: readin();
85: transpose();
86: getlim(&xd,(struct val *)&xx->xv);
87: getlim(&yd,(struct val *)&xx->yv);
88: if(equf) {
89: equilibrate(&xd,&yd);
90: equilibrate(&yd,&xd);
91: }
92: scale(&xd,(struct val *)&xx->xv);
93: scale(&yd,(struct val *)&xx->yv);
94: axes();
95: title();
96: plot();
97: closepl();
98: return(0);
99: }
100:
101: init(p)
102: struct xy *p;
103: {
104: p->xf = ident;
105: p->xmult = 1;
106: }
107:
108: setopt(argc,argv)
109: char *argv[];
110: {
111: char *p1, *p2;
112: float temp;
113:
114: xd.xlb = yd.xlb = INF;
115: xd.xub = yd.xub = -INF;
116: while(--argc > 0) {
117: argv++;
118: again: switch(argv[0][0]) {
119: case '-':
120: argv[0]++;
121: goto again;
122: case 'l': /* label for plot */
123: p1 = titlebuf;
124: if (argc>=2) {
125: argv++;
126: argc--;
127: p2 = argv[0];
128: while (*p1++ = *p2++);
129: }
130: break;
131:
132: case 'd': /*disconnected,obsolete option*/
133: case 'm': /*line mode*/
134: mode = 0;
135: if(!numb(&temp,&argc,&argv))
136: break;
137: if(temp>=sizeof(modes)/sizeof(*modes))
138: mode = 1;
139: else if(temp>=-1)
140: mode = temp;
141: break;
142:
143: case 'o':
144: if(numb(&temp,&argc,&argv) && temp>=1)
145: ovlay = temp;
146: break;
147: case 'a': /*automatic abscissas*/
148: absf = 1;
149: dx = 1;
150: if(!numb(&dx,&argc,&argv))
151: break;
152: if(numb(&absbot,&argc,&argv))
153: absf = 2;
154: break;
155:
156: case 's': /*save screen, overlay plot*/
157: erasf = 0;
158: break;
159:
160: case 'g': /*grid style 0 none, 1 ticks, 2 full*/
161: gridf = 0;
162: if(!numb(&temp,&argc,&argv))
163: temp = argv[0][1]-'0'; /*for caompatibility*/
164: if(temp>=0&&temp<=2)
165: gridf = temp;
166: break;
167:
168: case 'c': /*character(s) for plotting*/
169: if(argc >= 2) {
170: symbf = 1;
171: plotsymb = argv[1];
172: argv++;
173: argc--;
174: }
175: break;
176:
177: case 't': /*transpose*/
178: transf = 1;
179: break;
180: case 'e': /*equal scales*/
181: equf = 1;
182: break;
183: case 'b': /*breaks*/
184: brkf = 1;
185: break;
186: case 'x': /*x limits */
187: limread(&xd,&argc,&argv);
188: break;
189: case 'y':
190: limread(&yd,&argc,&argv);
191: break;
192: case 'h': /*set height of plot */
193: if(!numb(&yd.xsize, &argc,&argv))
194: badarg();
195: break;
196: case 'w': /*set width of plot */
197: if(!numb(&xd.xsize, &argc, &argv))
198: badarg();
199: break;
200: case 'r': /* set offset to right */
201: if(!numb(&xd.xoff, &argc, &argv))
202: badarg();
203: break;
204: case 'u': /*set offset up the screen*/
205: if(!numb(&yd.xoff,&argc,&argv))
206: badarg();
207: break;
208: default:
209: badarg();
210: }
211: }
212: }
213:
214: limread(p, argcp, argvp)
215: register struct xy *p;
216: int *argcp;
217: char ***argvp;
218: {
219: if(*argcp>1 && (*argvp)[1][0]=='l') {
220: (*argcp)--;
221: (*argvp)++;
222: p->xf = log10;
223: }
224: if(!numb(&p->xlb,argcp,argvp))
225: return;
226: p->xlbf = 1;
227: if(!numb(&p->xub,argcp,argvp))
228: return;
229: p->xubf = 1;
230: if(!numb(&p->xquant,argcp,argvp))
231: return;
232: p->xqf = 1;
233: }
234:
235: numb(np, argcp, argvp)
236: int *argcp;
237: float *np;
238: register char ***argvp;
239: {
240: register char c;
241:
242: if(*argcp <= 1)
243: return(0);
244: while((c=(*argvp)[1][0]) == '+')
245: (*argvp)[1]++;
246: if(!(isdigit(c) || c=='-'&&(*argvp)[1][1]<'A' || c=='.'))
247: return(0);
248: *np = atof((*argvp)[1]);
249: (*argcp)--;
250: (*argvp)++;
251: return(1);
252: }
253:
254: readin()
255: {
256: register t,i;
257: struct val *temp;
258:
259: if(absf==1) {
260: if(xd.xlbf)
261: absbot = xd.xlb;
262: else if(xd.xf==log10)
263: absbot = 1;
264: }
265: for(;;) {
266: temp = (struct val *)realloc((char*)xx,
267: (unsigned)(n+ovlay)*sizeof(struct val));
268: if(temp==0)
269: return;
270: xx = temp;
271: if(absf)
272: xx[n].xv = n*dx/ovlay + absbot;
273: else
274: if(!getfloat(&xx[n].xv))
275: return;
276: for(i=0;i<ovlay;i++) {
277: xx[n+i].xv = xx[n].xv;
278: if(!getfloat(&xx[n+i].yv))
279: return;
280: xx[n+i].lblptr = -1;
281: t = getstring();
282: if(t>0)
283: xx[n+i].lblptr = copystring(t);
284: if(t<0 && i+1<ovlay)
285: return;
286: }
287: n += ovlay;
288: if(t<0)
289: return;
290: }
291: }
292:
293: transpose()
294: {
295: register i;
296: float f;
297: struct xy t;
298: if(!transf)
299: return;
300: t = xd; xd = yd; yd = t;
301: for(i= 0;i<n;i++) {
302: f = xx[i].xv; xx[i].xv = xx[i].yv; xx[i].yv = f;
303: }
304: }
305:
306: copystring(k)
307: {
308: register char *temp;
309: register i;
310: int q;
311:
312: temp = realloc(labs,(unsigned)(labsiz+1+k));
313: if(temp==0)
314: return(0);
315: labs = temp;
316: q = labsiz;
317: for(i=0;i<=k;i++)
318: labs[labsiz++] = labbuf[i];
319: return(q);
320: }
321:
322: float
323: modceil(f,t)
324: float f,t;
325: {
326:
327: t = fabs(t);
328: return(ceil(f/t)*t);
329: }
330:
331: float
332: modfloor(f,t)
333: float f,t;
334: {
335: t = fabs(t);
336: return(floor(f/t)*t);
337: }
338:
339: getlim(p,v)
340: register struct xy *p;
341: struct val *v;
342: {
343: register i;
344:
345: i = 0;
346: do {
347: if(!p->xlbf && p->xlb>v[i].xv)
348: p->xlb = v[i].xv;
349: if(!p->xubf && p->xub<v[i].xv)
350: p->xub = v[i].xv;
351: i++;
352: } while(i < n);
353: }
354:
355: struct z {
356: float lb,ub,mult,quant;
357: } setloglim(), setlinlim();
358:
359: setlim(p)
360: register struct xy *p;
361: {
362: float t,delta,sign;
363: struct z z;
364: int mark[50];
365: float lb,ub;
366: int lbf,ubf;
367:
368: lb = p->xlb;
369: ub = p->xub;
370: delta = ub-lb;
371: if(p->xqf) {
372: if(delta*p->xquant <=0 )
373: badarg();
374: return;
375: }
376: sign = 1;
377: lbf = p->xlbf;
378: ubf = p->xubf;
379: if(delta < 0) {
380: sign = -1;
381: t = lb;
382: lb = ub;
383: ub = t;
384: t = lbf;
385: lbf = ubf;
386: ubf = t;
387: }
388: else if(delta == 0) {
389: if(ub > 0) {
390: ub = 2*ub;
391: lb = 0;
392: }
393: else
394: if(lb < 0) {
395: lb = 2*lb;
396: ub = 0;
397: }
398: else {
399: ub = 1;
400: lb = -1;
401: }
402: }
403: if(p->xf==log10 && lb>0 && ub>lb) {
404: z = setloglim(lbf,ubf,lb,ub);
405: p->xlb = z.lb;
406: p->xub = z.ub;
407: p->xmult *= z.mult;
408: p->xquant = z.quant;
409: if(setmark(mark,p)<2) {
410: p->xqf = lbf = ubf = 1;
411: lb = z.lb; ub = z.ub;
412: } else
413: return;
414: }
415: z = setlinlim(lbf,ubf,lb,ub);
416: if(sign > 0) {
417: p->xlb = z.lb;
418: p->xub = z.ub;
419: } else {
420: p->xlb = z.ub;
421: p->xub = z.lb;
422: }
423: p->xmult *= z.mult;
424: p->xquant = sign*z.quant;
425: }
426:
427: struct z
428: setloglim(lbf,ubf,lb,ub)
429: float lb,ub;
430: {
431: float r,s,t;
432: struct z z;
433:
434: for(s=1; lb*s<1; s*=10) ;
435: lb *= s;
436: ub *= s;
437: for(r=1; 10*r<=lb; r*=10) ;
438: for(t=1; t<ub; t*=10) ;
439: z.lb = !lbf ? r : lb;
440: z.ub = !ubf ? t : ub;
441: if(ub/lb<100) {
442: if(!lbf) {
443: if(lb >= 5*z.lb)
444: z.lb *= 5;
445: else if(lb >= 2*z.lb)
446: z.lb *= 2;
447: }
448: if(!ubf) {
449: if(ub*5 <= z.ub)
450: z.ub /= 5;
451: else if(ub*2 <= z.ub)
452: z.ub /= 2;
453: }
454: }
455: z.mult = s;
456: z.quant = r;
457: return(z);
458: }
459:
460: struct z
461: setlinlim(lbf,ubf,xlb,xub)
462: int lbf,ubf;
463: float xlb,xub;
464: {
465: struct z z;
466: float r,s,delta;
467: float ub,lb;
468:
469: loop:
470: ub = xub;
471: lb = xlb;
472: delta = ub - lb;
473: /*scale up by s, a power of 10, so range (delta) exceeds 1*/
474: /*find power of 10 quantum, r, such that delta/10<=r<delta*/
475: r = s = 1;
476: while(delta*s < 10)
477: s *= 10;
478: delta *= s;
479: while(10*r < delta)
480: r *= 10;
481: lb *= s;
482: ub *= s;
483: /*set r=(1,2,5)*10**n so that 3-5 quanta cover range*/
484: if(r>=delta/2)
485: r /= 2;
486: else if(r<delta/5)
487: r *= 2;
488: z.ub = ubf? ub: modceil(ub,r);
489: z.lb = lbf? lb: modfloor(lb,r);
490: if(!lbf && z.lb<=r && z.lb>0) {
491: xlb = 0;
492: goto loop;
493: }
494: else if(!ubf && z.ub>=-r && z.ub<0) {
495: xub = 0;
496: goto loop;
497: }
498: z.quant = r;
499: z.mult = s;
500: return(z);
501: }
502:
503: scale(p)
504: register struct xy *p;
505: {
506: float edge;
507:
508: setlim(p);
509: edge = top-bot;
510: p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb));
511: p->xbot = bot + edge*p->xoff;
512: p->xtop = p->xbot + (top-bot)*p->xsize;
513: p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5;
514: }
515:
516: equilibrate(p,q)
517: struct xy *p,*q;
518: {
519: if(p->xlbf|| /* needn't test xubf; it implies xlbf*/
520: q->xubf&&q->xlb>q->xub)
521: return;
522: if(p->xlb>q->xlb) {
523: p->xlb = q->xlb;
524: p->xlbf = q->xlbf;
525: }
526: if(p->xub<q->xub) {
527: p->xub = q->xub;
528: p->xubf = q->xubf;
529: }
530: }
531:
532: axes()
533: {
534: register i;
535: int mark[50];
536: int xn, yn;
537: if(gridf==0)
538: return;
539:
540: line(xd.xbot,yd.xbot,xd.xtop,yd.xbot);
541: vec(xd.xtop,yd.xtop);
542: vec(xd.xbot,yd.xtop);
543: vec(xd.xbot,yd.xbot);
544:
545: xn = setmark(mark,&xd);
546: for(i=0; i<xn; i++) {
547: if(gridf==2)
548: line(mark[i],yd.xbot,mark[i],yd.xtop);
549: if(gridf==1) {
550: line(mark[i],yd.xbot,mark[i],yd.xbot+tick);
551: line(mark[i],yd.xtop-tick,mark[i],yd.xtop);
552: }
553: }
554: yn = setmark(mark,&yd);
555: for(i=0; i<yn; i++) {
556: if(gridf==2)
557: line(xd.xbot,mark[i],xd.xtop,mark[i]);
558: if(gridf==1) {
559: line(xd.xbot,mark[i],xd.xbot+tick,mark[i]);
560: line(xd.xtop-tick,mark[i],xd.xtop,mark[i]);
561: }
562: }
563: }
564:
565: setmark(xmark,p)
566: int *xmark;
567: register struct xy *p;
568: {
569: int xn = 0;
570: float x,xl,xu;
571: float q;
572: if(p->xf==log10&&!p->xqf) {
573: for(x=p->xquant; x<p->xub; x*=10) {
574: submark(xmark,&xn,x,p);
575: if(p->xub/p->xlb<=100) {
576: submark(xmark,&xn,2*x,p);
577: submark(xmark,&xn,5*x,p);
578: }
579: }
580: } else {
581: xn = 0;
582: q = p->xquant;
583: if(q>0) {
584: xl = modceil(p->xlb+q/6,q);
585: xu = modfloor(p->xub-q/6,q)+q/2;
586: } else {
587: xl = modceil(p->xub-q/6,q);
588: xu = modfloor(p->xlb+q/6,q)-q/2;
589: }
590: for(x=xl; x<=xu; x+=fabs(p->xquant))
591: xmark[xn++] = (*p->xf)(x)*p->xa + p->xb;
592: }
593: return(xn);
594: }
595: submark(xmark,pxn,x,p)
596: int *xmark;
597: int *pxn;
598: float x;
599: struct xy *p;
600: {
601: if(1.001*p->xlb < x && .999*p->xub > x)
602: xmark[(*pxn)++] = log10(x)*p->xa + p->xb;
603: }
604:
605: plot()
606: {
607: int ix,iy;
608: int i,j;
609: int conn;
610:
611: for(j=0;j<ovlay;j++) {
612: switch(mode) {
613: case -1:
614: pen(modes[j%(sizeof modes/sizeof *modes-1)+1]);
615: break;
616: case 0:
617: break;
618: default:
619: pen(modes[mode]);
620: }
621: conn = 0;
622: for(i=j; i<n; i+=ovlay) {
623: if(!conv(xx[i].xv,&xd,&ix) ||
624: !conv(xx[i].yv,&yd,&iy)) {
625: conn = 0;
626: continue;
627: }
628: if(mode!=0) {
629: if(conn != 0)
630: vec(ix,iy);
631: else
632: move(ix,iy);
633: conn = 1;
634: }
635: conn &= symbol(ix,iy,xx[i].lblptr);
636: }
637: }
638: pen(modes[1]);
639: }
640:
641: conv(xv,p,ip)
642: float xv;
643: register struct xy *p;
644: int *ip;
645: {
646: long ix;
647: ix = p->xa*(*p->xf)(xv*p->xmult) + p->xb;
648: if(ix<p->xbot || ix>p->xtop)
649: return(0);
650: *ip = ix;
651: return(1);
652: }
653:
654: getfloat(p)
655: float *p;
656: {
657: register i;
658:
659: i = scanf("%f",p);
660: return(i==1);
661: }
662:
663: getstring()
664: {
665: register i;
666: char junk[20];
667: i = scanf("%1s",labbuf);
668: if(i==-1)
669: return(-1);
670: switch(*labbuf) {
671: default:
672: if(!isdigit(*labbuf)) {
673: ungetc(*labbuf,stdin);
674: i = scanf("%s",labbuf);
675: break;
676: }
677: case '.':
678: case '+':
679: case '-':
680: ungetc(*labbuf,stdin);
681: return(0);
682: case '"':
683: i = scanf("%[^\"\n]",labbuf);
684: scanf("%[\"]",junk);
685: break;
686: }
687: if(i==-1)
688: return(-1);
689: return(strlen(labbuf));
690: }
691:
692:
693: symbol(ix,iy,k)
694: {
695:
696: if(symbf==0&&k<0) {
697: if(mode==0)
698: point(ix,iy);
699: return(1);
700: }
701: else {
702: move(ix,iy);
703: text(k>=0?labs+k:plotsymb);
704: move(ix,iy);
705: return(!brkf|k<0);
706: }
707: }
708:
709: title()
710: {
711: char buf[BSIZ+100];
712: buf[0] = ' ';
713: buf[1] = ' ';
714: buf[2] = ' ';
715: strcpy(buf+3,titlebuf);
716: if(erasf&&gridf) {
717: axlab('x',&xd,buf);
718: strcat(buf,",");
719: axlab('y',&yd,buf);
720: }
721: move(xd.xbot,yd.xbot-60);
722: text(buf);
723: }
724:
725: axlab(c,p,b)
726: char c;
727: struct xy *p;
728: char *b;
729: {
730: char *dir;
731: dir = p->xlb<p->xub? "<=": ">=";
732: sprintf(b+strlen(b), " %g %s %c%s %s %g", p->xlb/p->xmult,
733: dir, c, p->xf==log10?" (log)":"", dir, p->xub/p->xmult);
734: }
735:
736: badarg()
737: {
738: fprintf(stderr,"graph: error in arguments\n");
739: closepl();
740: exit(1);
741: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.