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