Annotation of 40BSD/cmd/graph/graph.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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