Annotation of 42BSD/usr.bin/graph/graph.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.