Annotation of 43BSD/contrib/B/src/bint/b1tlt.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
                      2: 
                      3: /*
                      4:   $Header: b1tlt.c,v 1.4 85/08/22 16:53:20 timo Exp $
                      5: */
                      6: 
                      7: /* generic routines for B texts, lists and tables */
                      8: 
                      9: #include "b.h"
                     10: #include "b0fea.h"
                     11: #include "b1obj.h"
                     12: #ifndef INTEGRATION
                     13: #include "b0con.h"
                     14: #include "b1btr.h"
                     15: #include "b1val.h"
                     16: #endif
                     17: #include "b1tlt.h"
                     18: #include "b3err.h"
                     19: 
                     20: #ifndef INTEGRATION
                     21: 
                     22: /* From b1lta.c */
                     23: int l2size();
                     24: value l2min(), l2max();
                     25: 
                     26: Visible value mk_elt() { /* {}, internal only */
                     27:        value e = grab_tlt(ELT, Lt);
                     28:        Root(e) = Bnil;
                     29:        return e;
                     30: }
                     31: 
                     32: Visible bool empty(v) value v; { /* #v=0, internal only */
                     33:        switch (Type(v)) {
                     34:        case ELT:
                     35:        case Lis:
                     36:        case Tex:
                     37:        case Tab:
                     38:                return Root(v) EQ Bnil;
                     39:        default:
                     40:                return No;
                     41:                /* Some routines must test empty(t) end return an error
                     42:                   message if it fails, before testing Type(t).
                     43:                   In this way, they won't give the wrong error message. */
                     44:        }
                     45: }
                     46: 
                     47: /* return size of (number of items in) dependent tree */
                     48: 
                     49: Hidden value treesize(pnode) btreeptr pnode; {
                     50:     int psize;
                     51:     value vsize, childsize, u;
                     52:     intlet l;
                     53:     psize = Size(pnode);
                     54:     if (psize EQ Bigsize) {
                     55:        switch (Flag(pnode)) {        
                     56:        case Inner:
                     57:            vsize = mk_integer((int) Lim(pnode));
                     58:            for (l = 0; l <= Lim(pnode); l++) {
                     59:                childsize = treesize(Ptr(pnode, l));
                     60:                u = vsize;
                     61:                vsize = sum(vsize, childsize);
                     62:                release(u);
                     63:                release(childsize);
                     64:            }
                     65:            break;
                     66:        case Irange: 
                     67:            u = diff(Upbval(pnode), Lwbval(pnode));
                     68:            vsize = sum(u, one);
                     69:            release(u);
                     70:            break;
                     71:        case Bottom: 
                     72:        case Crange: 
                     73:            syserr(MESS(1700, "Bigsize in Bottom or Crange"));
                     74:        }
                     75:        return(vsize);
                     76:     }
                     77:     return mk_integer(psize);
                     78: }
                     79: 
                     80: Visible value size(t) value t; { /* #t */
                     81:        int tsize;
                     82:        switch (Type(t)) {
                     83:        case ELT:
                     84:        case Lis:
                     85:        case Tex:
                     86:        case Tab:
                     87:                tsize = Tltsize(t);
                     88:                if (tsize EQ Bigsize) return treesize(Root(t));
                     89:                return mk_integer(tsize);
                     90:        default:
                     91:                reqerr(MESS(1701, "in #t, t is not a text, list or table"));
                     92:                return zero;
                     93:        }
                     94: }
                     95: 
                     96: Visible value th_of(num, v) value num, v; { /* num th'of v */
                     97:        value m= Vnil;
                     98:        if (!Is_tlt(v))
                     99:                error(MESS(1702, "in n th'of t, t is not a text, list or table"));
                    100:        else if (!Is_number(num))
                    101:                error(MESS(1703, "in n th'of t, n is not a number"));
                    102:        else if (empty(v))
                    103:                error(MESS(1704, "in n th'of t, t is empty"));
                    104:        else if (numcomp(num, one) < 0)
                    105:                error(MESS(1705, "in n th'of t, n is < 1"));
                    106:        else {
                    107:                /*RANGES?*/
                    108:                m= thof(intval(num), v);
                    109:                if (m == Vnil && still_ok)
                    110:                        error(MESS(1706, "in n th'of t, n exceeds #t"));
                    111:        }
                    112:        return m;
                    113: }
                    114: 
                    115: /*
                    116:  * 'Walktree' handles functions on texts and associates of tables.
                    117:  * The actual function performed is determined by the 'visit' function.
                    118:  * The tree is walked (possibly recursively) and all items are visited.
                    119:  * The return value of walktree() and visit() is used to determine whether
                    120:  * the walk should continue (Yes == continue, No == stop now).
                    121:  * Global variables are used to communicate the result, and the parameters
                    122:  * of the function. The naming convention is according to "e func t".
                    123:  */
                    124: 
                    125: Hidden intlet tt;              /* type of walked value t */
                    126: Hidden intlet wt;              /* width of items in walked value t */
                    127: Hidden value ve;               /* value of e, if func is dyadic */
                    128: Hidden char ce;                /* C char in e, if t is a text */
                    129: 
                    130: Hidden int count;              /* result of size2 */
                    131: Hidden bool found;             /* result for in */
                    132: Hidden intlet m_char;          /* result for min/max on texts */
                    133: Hidden value m_val;            /* result for min/max on tables */
                    134: 
                    135: #define Lowchar (-Maxintlet)   /* -infinity for characters */
                    136: #define Highchar (Maxintlet)   /* +infinity */
                    137: 
                    138: Hidden bool walktree(p, visit) btreeptr p; bool (*visit)(); {
                    139:        intlet l;
                    140:        
                    141:        if (p EQ Bnil) return Yes; /* i.e., not found (used by in() !) */
                    142:        for (l=0; l < Lim(p); l++) {
                    143:                switch (Flag(p)) {
                    144:                case Inner:
                    145:                        if (!walktree(Ptr(p, l), visit) || !still_ok)
                    146:                                return No;
                    147:                        if (!(*visit)(Piitm(p, l, wt)) || !still_ok)
                    148:                                return No;
                    149:                        break;
                    150:                case Bottom:
                    151:                        if (!(*visit)(Pbitm(p, l, wt)) || !still_ok)
                    152:                                return No;
                    153:                }
                    154:        }
                    155:        return Flag(p) EQ Bottom || walktree(Ptr(p, l), visit);
                    156: }
                    157: 
                    158: /* Common code for min/max-1/2, size2, in. */
                    159: 
                    160: Hidden Procedure tlt_func(e, t, where, li_func, te_visit, ta_visit)
                    161:        value e, t;                     /* [e] func t */
                    162:        string where;                   /* "in [e] func_name t" */
                    163:        value (*li_func)();             /* func for lists */
                    164:        bool (*te_visit)(), (*ta_visit)(); /* 'visit' for walktree */
                    165: {
                    166:        m_val = Vnil;
                    167:        if (empty(t)) {
                    168:                error3(MESSMAKE(where), Vnil, MESS(1707, ", t is empty"));
                    169:                return;
                    170:        }
                    171:        wt = Itemwidth(Itemtype(t));
                    172:        tt = Type(t);
                    173:        switch (tt) {
                    174:        case Lis:
                    175:                m_val = (*li_func)(e, t);
                    176:                break;
                    177:        case Tex:
                    178:                if (e NE Vnil) {
                    179:                        if (!Character(e)) {
                    180:                                error3(MESSMAKE(where), Vnil,
                    181:                        MESS(1708, ", t is a text, but e is not a character"));
                    182:                                return;
                    183:                        }
                    184:                        ce = Bchar(Root(e), 0);
                    185:                }
                    186:                found = !walktree(Root(t), te_visit);
                    187:                if (m_char NE Lowchar && m_char NE Highchar)
                    188:                        m_val = mkchar(m_char);
                    189:                break;
                    190:        case Tab:
                    191:                ve = e;
                    192:                found = !walktree(Root(t), ta_visit);
                    193:                break;
                    194:        default:
                    195:                error3(MESSMAKE(where), Vnil,
                    196:                        MESS(1709, ", t is not a text list or table"));
                    197:        }
                    198: }
                    199: 
                    200: Hidden value li2size(e, t) value e, t; {
                    201:        count = l2size(e, t);
                    202:        return Vnil;
                    203: }
                    204: 
                    205: Hidden bool te2size(pitm) itemptr pitm; {
                    206:        if (ce EQ Charval(pitm))
                    207:                count++;
                    208:        return Yes;
                    209: }
                    210: 
                    211: Hidden bool ta2size(pitm) itemptr pitm; {
                    212:        if (compare(ve, Ascval(pitm)) EQ 0)
                    213:                count++;
                    214:        return Yes;
                    215: }
                    216: 
                    217: Visible value size2(e, t) value e, t; { /* e#t */
                    218:        if (empty(t)) /* Must check here because tlt_func would complain */
                    219:                return copy(zero);
                    220:        m_char = Lowchar;
                    221:        count = 0;
                    222:        tlt_func(e, t, "in e#t", li2size, te2size, ta2size);
                    223:        return mk_integer(count);
                    224: }
                    225: 
                    226: Hidden value li_in(e, t) value e, t; {
                    227:        found = in_keys(e, t);
                    228:        return Vnil;
                    229: }
                    230:        
                    231: Hidden bool te_in(pitm) itemptr pitm; {
                    232:        return Charval(pitm) NE ce;
                    233: }
                    234: 
                    235: Hidden bool ta_in(pitm) itemptr pitm; {
                    236:        return compare(ve, Ascval(pitm)) NE 0;
                    237: }
                    238: 
                    239: Visible bool in(e, t) value e, t; {
                    240:        if (empty(t)) /* Must check here because tlt_func would complain */
                    241:                return No;
                    242:        m_char = Lowchar;
                    243:        found = No;
                    244:        tlt_func(e, t, "in the test e in t", li_in, te_in, ta_in);
                    245:        return found;
                    246: }
                    247: 
                    248: Hidden value li_min(e, t) value e, t; {
                    249:        return th_of(one, t);
                    250: }
                    251: 
                    252: Hidden bool te_min(pitm) itemptr pitm; {
                    253:        if (m_char > Charval(pitm))
                    254:                m_char = Charval(pitm);
                    255:        return Yes;
                    256: }
                    257: 
                    258: Hidden bool ta_min(pitm) itemptr pitm; {
                    259:        if (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0) {
                    260:                release(m_val);
                    261:                m_val = copy(Ascval(pitm));
                    262:        }
                    263:        return Yes;
                    264: }
                    265: 
                    266: Visible value min1(t) value t; {
                    267:        m_char = Highchar;
                    268:        tlt_func(Vnil, t, "in min t", li_min, te_min, ta_min);
                    269:        return m_val;
                    270: }
                    271: 
                    272: Hidden value li_max(e, t) value e, t; {
                    273:        value v= size(t);
                    274:        m_val = th_of(v, t);
                    275:        release(v);
                    276:        return m_val;
                    277: }
                    278: 
                    279: Hidden bool te_max(pitm) itemptr pitm; {
                    280:        if (m_char < Charval(pitm))
                    281:                m_char = Charval(pitm);
                    282:        return Yes;
                    283: }
                    284: 
                    285: Hidden bool ta_max(pitm) itemptr pitm; {
                    286:        if (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0) {
                    287:                release(m_val);
                    288:                m_val = copy(Ascval(pitm));
                    289:        }
                    290:        return Yes;
                    291: }
                    292: 
                    293: Visible value max1(t) value t; {
                    294:        m_char = Lowchar;
                    295:        tlt_func(Vnil, t, "in max t", li_max, te_max, ta_max);
                    296:        return m_val;
                    297: }
                    298: 
                    299: Hidden bool te2min(pitm) itemptr pitm; {
                    300:        if (m_char > Charval(pitm) && Charval(pitm) > ce) {
                    301:                m_char = Charval(pitm);
                    302:        }
                    303:        return Yes;
                    304: }
                    305: 
                    306: Hidden bool ta2min(pitm) itemptr pitm; {
                    307:        if (compare(Ascval(pitm), ve) > 0
                    308:            &&
                    309:            (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0)) {
                    310:                release(m_val);
                    311:                m_val = copy(Ascval(pitm));
                    312:        }
                    313:        return Yes;
                    314: }
                    315: 
                    316: Visible value min2(e, t) value e, t; {
                    317:        m_char = Highchar;
                    318:        tlt_func(e, t, "in e min t", l2min, te2min, ta2min);
                    319:        if (m_val EQ Vnil && still_ok)
                    320:                reqerr(MESS(1710, "in e min t, no element of t exceeds e"));
                    321:        return m_val;
                    322: }
                    323: 
                    324: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
                    325: 
                    326: Hidden bool te2max(pitm) itemptr pitm; {
                    327:        if (ce > Charval(pitm) && Charval(pitm) > m_char) {
                    328:                m_char = Charval(pitm);
                    329:        }
                    330:        return Yes;
                    331: }
                    332: 
                    333: Hidden bool ta2max(pitm) itemptr pitm; {
                    334:        if (compare(ve, Ascval(pitm)) > 0
                    335:            &&
                    336:            (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0)) {
                    337:                release(m_val);
                    338:                m_val = copy(Ascval(pitm));
                    339:        }
                    340:        return Yes;
                    341: }
                    342: 
                    343: Visible value max2(e, t) value e, t; {
                    344:        m_char = Lowchar;
                    345:        tlt_func(e, t, "in e max t", l2max, te2max, ta2max);
                    346:        if (m_val EQ Vnil && still_ok)
                    347:                reqerr(MESS(1711, "in e max t, no element of t is less than e"));
                    348:        return m_val;
                    349: }
                    350: 
                    351: #else INTEGRATION
                    352: 
                    353: Visible value mk_elt() { return grab_elt(); }
                    354: 
                    355: Visible value size(x) value x; { /* monadic # operator */
                    356:        if (!Is_tlt(x))
                    357:                error(MESS(1712, "in #t, t is not a text, list or table"));
                    358:        return mk_integer((int) Length(x));
                    359: }
                    360: 
                    361: #define Lisent(tp,k) (*(tp+(k)))
                    362: 
                    363: Visible value size2(v, t) value v, t; { /* Dyadic # operator */
                    364:        intlet len= Length(t), n= 0, k; value *tp= Ats(t);
                    365:        if (!Is_tlt(t)) {
                    366:                error(MESS(1713, "in e#t, t is not a text, list or table"));
                    367:                return mk_integer((int) n);
                    368:        }
                    369:        switch (Type(t)) {
                    370:        case Tex:
                    371:                {string cp= (string)tp; char c;
                    372:                        if (Type(v) != Tex)
                    373:                                error(MESS(1714, "in e#t, t is a text but e is not"));
                    374:                        if (Length(v) != 1)
                    375:                                error(MESS(1715, "in e#t, e is a text but not a character"));
                    376:                        c= *Str(v);
                    377:                        Overall if (*cp++ == c) n++;
                    378:                } break;
                    379:        case ELT:
                    380:                break;
                    381:        case Lis:
                    382:                {intlet lo= -1, mi, xx, mm, hi= len; relation c;
                    383:                bins:   if (hi-lo < 2) break;
                    384:                        mi= (lo+hi)/2;
                    385:                        if ((c= compare(v, Lisent(tp,mi))) == 0) goto some;
                    386:                        if (c < 0) hi= mi; else lo= mi;
                    387:                        goto bins;
                    388:                some:   xx= mi;
                    389:                        while (xx-lo > 1) {
                    390:                                mm= (lo+xx)/2;
                    391:                                if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
                    392:                                else lo= mm;
                    393:                        }
                    394:                        xx= mi;
                    395:                        while (hi-xx > 1) {
                    396:                                mm= (xx+hi)/2;
                    397:                                if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
                    398:                                else hi= mm;
                    399:                        }
                    400:                        n= hi-lo-1;
                    401:                } break;
                    402:        case Tab:
                    403:                Overall if (compare(v, Dts(*tp++)) == 0) n++;
                    404:                break;
                    405:        default:
                    406:                syserr(MESS(1716, "e#t with non text, list or table"));
                    407:                break;
                    408:        }
                    409:        return mk_integer((int) n);
                    410: }
                    411: 
                    412: Hidden bool less(r) relation r;    { return r<0; }
                    413: Hidden bool greater(r) relation r; { return r>0; }
                    414: 
                    415: Hidden value mm1(t, rel) value t; bool (*rel)(); {
                    416:        intlet len= Length(t), k; value m, *tp= Ats(t);
                    417:        switch (Type(t)) {
                    418:        case Tex:
                    419:                {string cp= (string) tp; char mc= '\0', mm[2];
                    420:                        Overall {
                    421:                                if (mc == '\0' || ((*rel)(*cp < mc ? -1 : (*cp > mc ? 1 : 0))))
                    422:                                        mc= *cp;
                    423:                                cp++;
                    424:                        }
                    425:                        mm[0]= mc; mm[1]= '\0';
                    426:                        m= mk_text(mm);
                    427:                } break;
                    428:        case Lis:
                    429:                if ((*rel)(-1)) /*min*/ m= copy(*Ats(t));
                    430:                else m= copy(*(Ats(t)+len-1));
                    431:                break;
                    432:        case Tab:
                    433:                {value dm= Vnil;
                    434:                        Overall {
                    435:                                if (dm == Vnil || (*rel)(compare(Dts(*tp), dm)))
                    436:                                        dm= Dts(*tp);
                    437:                                tp++;
                    438:                        }
                    439:                        m= copy(dm);
                    440:                } break;
                    441:        default:
                    442:                syserr(MESS(1717, "min or max t, with non text, list or table"));
                    443:        }
                    444:        return m;
                    445: }
                    446: 
                    447: #ifdef NO_ABS
                    448: 
                    449: Hidden int abs(i) int i; {
                    450:        return i >= 0 ? i : -i;
                    451: }
                    452: 
                    453: #endif
                    454: 
                    455: Hidden value mm2(v, t, rel) value v, t; bool (*rel)(); {
                    456:        intlet len= Length(t), k; value m= Vnil, *tp= Ats(t);
                    457:        switch (Type(t)) {
                    458:        case Tex:
                    459:                {string cp= (string) tp; char c, mc= '\0', mm[2];
                    460:                        c= *Str(v);
                    461:                        Overall {
                    462:                                if ((*rel)(c < *cp ? -1 : c > *cp ? 1 : 0)) {
                    463:                                        if (mc == '\0' || (*rel)(*cp < mc ? -1 : *cp>mc ? 1 : 0))
                    464:                                                mc= *cp;
                    465:                                }
                    466:                                cp++;
                    467:                        }
                    468:                        if (mc != '\0') {
                    469:                                mm[0]= mc; mm[1]= '\0';
                    470:                                m= mk_text(mm);
                    471:                        }
                    472:                } break;
                    473:        case Lis:
                    474:                {intlet lim1, mid, lim2;
                    475:                        if ((*rel)(-1)) { /*min*/
                    476:                                lim1= 1; lim2= len-1;
                    477:                        } else {
                    478:                                lim2= 1; lim1= len-1;
                    479:                        }
                    480:                        if (!(*rel)(compare(v, Lisent(tp,lim2)))) break;
                    481:                        if (len == 1 || (*rel)(compare(v, Lisent(tp,lim1)))) {
                    482:                                m= copy(Lisent(tp,lim1));
                    483:                                break;
                    484:                        }
                    485:                        /* v rel tp[lim2] && !(v rel tp[lim1]) */
                    486:                        while (abs(lim2-lim1) > 1) {
                    487:                                mid= (lim1+lim2)/2;
                    488:                                if ((*rel)(compare(v, Lisent(tp,mid)))) lim2= mid;
                    489:                                else lim1= mid;
                    490:                        }
                    491:                        m= copy(Lisent(tp,lim2));
                    492:                } break;
                    493:        case Tab:
                    494:                {value dm= Vnil;
                    495:                        Overall {
                    496:                                if ((*rel)(compare(v, Dts(*tp)))) {
                    497:                                        if (dm == Vnil ||
                    498:                                                (*rel)(compare(Dts(*tp), dm)))
                    499:                                                dm= Dts(*tp);
                    500:                                }
                    501:                                tp++;
                    502:                        }
                    503:                        if (dm != Vnil) m= copy(dm);
                    504:                } break;
                    505:        default:
                    506:                syserr(MESS(1718, "min2 or max2 with non text, list or table"));
                    507:                break;
                    508:        }
                    509:        return m;
                    510: }
                    511: 
                    512: Visible value min1(t) value t; { /* Monadic min */
                    513:        value m= Vnil;
                    514:        if (!Is_tlt(t))
                    515:                error(MESS(1719, "in min t, t is not a text, list or table"));
                    516:        else if (Length(t) == 0)
                    517:                error(MESS(1720, "in min t, t is empty"));
                    518:        else m= mm1(t, less);
                    519:        return m;
                    520: }
                    521: 
                    522: Visible value min2(v, t) value v, t; {
                    523:        value m= Vnil;
                    524:        if (!Is_tlt(t))
                    525:                error(MESS(1721, "in e min t, t is not a text, list or table"));
                    526:        else if (Length(t) == 0)
                    527:                error(MESS(1722, "in e min t, t is empty"));
                    528:        else if (Is_text(t)) {
                    529:                if (!Is_text(v))
                    530:                        error(MESS(1723, "in e min t, t is a text but e is not"));
                    531:                else if (Length(v) != 1)
                    532:                        error(MESS(1724, "in e min t, e is a text but not a character"));
                    533:        }
                    534:        if (still_ok) {
                    535:                m= mm2(v, t, less);
                    536:                if (m == Vnil)
                    537:                        error(MESS(1725, "in e min t, no element of t exceeds e"));
                    538:        }
                    539:        return m;
                    540: }
                    541: 
                    542: Visible value max1(t) value t; {
                    543:        value m= Vnil;
                    544:        if (!Is_tlt(t))
                    545:                error(MESS(1726, "in max t, t is not a text, list or table"));
                    546:        else if (Length(t) == 0)
                    547:                error(MESS(1727, "in max t, t is empty"));
                    548:        else m= mm1(t, greater);
                    549:        return m;
                    550: }
                    551: 
                    552: Visible value max2(v, t) value v, t; {
                    553:        value m= Vnil;
                    554:        if (!Is_tlt(t))
                    555:                error(MESS(1728, "in e max t, t is not a text, list or table"));
                    556:        else if (Length(t) == 0)
                    557:                error(MESS(1729, "in e max t, t is empty"));
                    558:        else if (Is_text(t)) {
                    559:                if (!Is_text(v))
                    560:                        error(MESS(1730, "in e max t, t is a text but e is not"));
                    561:                else if (Length(v) != 1)
                    562:                        error(MESS(1731, "in e max t, e is a text but not a character"));
                    563:        }
                    564:        if (still_ok) {
                    565:                m= mm2(v, t, greater);
                    566:                if (m == Vnil)
                    567:                        error(MESS(1732, "in e max t, no element of t is less than e"));
                    568:        }
                    569:        return m;
                    570: }
                    571: 
                    572: Visible value th_of(n, t) value n, t; {
                    573:        return thof(intval(n), t);
                    574: }
                    575: 
                    576: Visible value thof(n, t) int n; value t; {
                    577:        intlet len= Length(t); value w= Vnil;
                    578:        if (!Is_tlt(t))
                    579:                error(MESS(1733, "in n th'of t, t is not a text, list or table"));
                    580:        else if (n <= 0 || n > len)
                    581:                error(MESS(1734, "in n th'of t, n is out of bounds"));
                    582:        else {
                    583:                switch (Type(t)) {
                    584:                case Tex:
                    585:                        {char ww[2];
                    586:                                ww[0]= *(Str(t)+n-1); ww[1]= '\0';
                    587:                                w= mk_text(ww);
                    588:                        } break;
                    589:                case Lis:
                    590:                        w= copy(*(Ats(t)+n-1));
                    591:                        break;
                    592:                case Tab:
                    593:                        w= copy(Dts(*(Ats(t)+n-1)));
                    594:                        break;
                    595:                default:
                    596:                        syserr(MESS(1735, "th'of with non text, list or table"));
                    597:                }
                    598:        }
                    599:        return w;
                    600: }
                    601: 
                    602: Visible bool found(elem, v, probe, where)
                    603:        value (*elem)(), v, probe; intlet *where;
                    604:        /* think of elem(v,lo-1) as -Infinity and elem(v,hi+1) as +Infinity.
                    605:           found and where at the end satisfy:
                    606:           SELECT:
                    607:               SOME k IN {lo..hi} HAS probe = elem(v,k):
                    608:                   found = Yes AND where = k
                    609:               ELSE: found = No AND elem(v,where-1) < probe < elem(v,where).
                    610:        */
                    611: {relation c; intlet lo=0, hi= Length(v)-1;
                    612:        if (lo > hi) { *where= lo; return No; }
                    613:        if ((c= compare(probe, (*elem)(v, lo))) == 0) {*where= lo; return Yes; }
                    614:        if (c < 0) { *where=lo; return No; }
                    615:        if (lo == hi) { *where=hi+1; return No; }
                    616:        if ((c= compare(probe, (*elem)(v, hi))) == 0) { *where=hi; return Yes; }
                    617:        if (c > 0) { *where=hi+1; return No; }
                    618:        /* elem(lo) < probe < elem(hi) */
                    619:        while (hi-lo > 1) {
                    620:                if ((c= compare(probe, (*elem)(v, (lo+hi)/2))) == 0) {
                    621:                        *where= (lo+hi)/2; return Yes;
                    622:                }
                    623:                if (c < 0) hi= (lo+hi)/2; else lo= (lo+hi)/2;
                    624:        }
                    625:        *where= hi; return No;
                    626: }
                    627: 
                    628: Visible bool in(v, t) value v, t; {
                    629:        intlet where, k, len= Length(t); value *tp= Ats(t);
                    630:        if (!Is_tlt(t)) {
                    631:                error(MESS(1736, "in the test e in t, t is not a text, list or table"));
                    632:                return No;
                    633:        }
                    634:        switch (Type(t)) {
                    635:        case Tex:
                    636:                if (Type(v) != Tex)
                    637:                        error(MESS(1737, "in the test e in t, t is a text but e is not"));
                    638:                else if (Length(v) != 1)
                    639:                        error(MESS(1738, "in the test e in t, e is a text but not a character"));
                    640:                else return index((string) tp, *Str(v)) != 0;
                    641:                return No;
                    642:        case ELT:
                    643:                return No;
                    644:        case Lis:
                    645:                return found(list_elem, t, v, &where);
                    646:        case Tab:
                    647:                Overall if (compare(v, Dts(*tp++)) == 0) return Yes;
                    648:                return No;
                    649:        default:
                    650:                syserr(MESS(1739, "e in t with non text, list or table"));
                    651:                return No;
                    652:        }
                    653: }
                    654: 
                    655: Visible bool empty(v) value v; {
                    656:        switch (Type(v)) {
                    657:        case Tex:
                    658:        case Lis:
                    659:        case Tab:
                    660:        case ELT:
                    661:                return (Length(v) == 0);
                    662:        default:
                    663:                syserr(MESS(1740, "empty() on non tlt value"));
                    664:                return (No);
                    665:        }
                    666: }
                    667: 
                    668: #endif INTEGRATION

unix.superglobalmegacorp.com

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