|
|
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.