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: }

Defined functions

axes defined in line 501; used 1 times
  • in line 88
axlab defined in line 683; used 2 times
badarg defined in line 693; used 6 times
conv defined in line 601; used 2 times
copystring defined in line 289; used 1 times
getfloat defined in line 614; used 2 times
getlim defined in line 322; used 1 times
getstring defined in line 623; used 1 times
ident defined in line 64; used 1 times
  • in line 99
init defined in line 96; used 2 times
limread defined in line 202; used 2 times
main defined in line 70; never used
modceil defined in line 305; used 3 times
modfloor defined in line 314; used 3 times
numb defined in line 223; used 11 times
plot defined in line 574; used 1 times
  • in line 90
readin defined in line 242; used 1 times
  • in line 84
scale defined in line 486; used 2 times
setlim defined in line 342; used 1 times
setlinlim defined in line 443; used 2 times
setloglim defined in line 410; used 2 times
setmark defined in line 534; used 3 times
setopt defined in line 103; used 1 times
  • in line 81
submark defined in line 564; used 3 times
symbol defined in line 653; used 1 times
title defined in line 669; used 1 times
  • in line 89
transpose defined in line 276; used 1 times
  • in line 85

Defined variables

absbot defined in line 36; used 4 times
absf defined in line 41; used 4 times
bot defined in line 35; used 3 times
brkf defined in line 43; used 2 times
dx defined in line 44; used 3 times
erasf defined in line 38; used 3 times
gridf defined in line 39; used 8 times
labbuf defined in line 49; used 9 times
labs defined in line 30; used 6 times
labsiz defined in line 31; used 4 times
mode defined in line 60; used 7 times
modes defined in line 52; used 4 times
n defined in line 37; used 11 times
plotsymb defined in line 45; used 2 times
sccsid defined in line 2; never used
symbf defined in line 40; used 2 times
tick defined in line 33; used 4 times
titlebuf defined in line 50; used 3 times
top defined in line 34; used 2 times
transf defined in line 42; used 2 times
xd defined in line 23; used 28 times
xx defined in line 28; used 17 times
yd defined in line 23; used 25 times

Defined struct's

val defined in line 24; used 18 times
xy defined in line 11; used 20 times
z defined in line 338; used 10 times

Defined macros

BSIZ defined in line 48; used 2 times
F defined in line 9; never used
INF defined in line 8; used 2 times
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5916
Valid CSS Valid XHTML 1.0 Strict