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