|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: /* $Header: B1tlt.c,v 1.1 84/06/28 00:49:00 timo Exp $ */
3:
4: #include "b.h"
5: #include "b1obj.h"
6: #include "B1tlt.h"
7:
8: Visible value mk_elt() { return grab_elt(); }
9:
10: Visible value size(x) value x; { /* monadic # operator */
11: if (!Is_tlt(x)) error("in #t, t is not a text, list or table");
12: return mk_integer((int) Length(x));
13: }
14:
15: #define Lisent(tp,k) (*(tp+(k)))
16:
17: Visible value size2(v, t) value v, t; { /* Dyadic # operator */
18: intlet len= Length(t), n= 0, k; value *tp= Ats(t);
19: if (!Is_tlt(t)) error("in e#t, t is not a text, list or table");
20: switch (t->type) {
21: case Tex:
22: {string cp= (string)tp; char c;
23: if (v->type != Tex)
24: error("in e#t, t is a text but e is not");
25: if (Length(v) != 1) error(
26: "in e#t, e is a text but not a character");
27: c= *Str(v);
28: Overall if (*cp++ == c) n++;
29: } break;
30: case ELT:
31: break;
32: case Lis:
33: {intlet lo= -1, mi, xx, mm, hi= len; relation c;
34: bins: if (hi-lo < 2) break;
35: mi= (lo+hi)/2;
36: if ((c= compare(v, Lisent(tp,mi))) == 0) goto some;
37: if (c < 0) hi= mi; else lo= mi;
38: goto bins;
39: some: xx= mi;
40: while (xx-lo > 1) {
41: mm= (lo+xx)/2;
42: if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
43: else lo= mm;
44: }
45: xx= mi;
46: while (hi-xx > 1) {
47: mm= (xx+hi)/2;
48: if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
49: else hi= mm;
50: }
51: n= hi-lo-1;
52: } break;
53: case Tab:
54: Overall if (compare(v, Dts(*tp++)) == 0) n++;
55: break;
56: default:
57: syserr("e#t with non text, list or table");
58: break;
59: }
60: return mk_integer((int) n);
61: }
62:
63: Hidden bool less(r) relation r; { return r<0; }
64: Hidden bool greater(r) relation r; { return r>0; }
65:
66: Hidden value mm1(t, rel) value t; bool (*rel)(); {
67: intlet len= Length(t), k; value m, *tp= Ats(t);
68: switch (t->type) {
69: case Tex:
70: {string cp= (string) tp; char mc= '\0', mm[2];
71: Overall {
72: if (mc == '\0' || ((*rel)(*cp < mc ? -1 : (*cp > mc ? 1 : 0))))
73: mc= *cp;
74: cp++;
75: }
76: mm[0]= mc; mm[1]= '\0';
77: m= mk_text(mm);
78: } break;
79: case Lis:
80: if ((*rel)(-1)) /*min*/ m= copy(*Ats(t));
81: else m= copy(*(Ats(t)+len-1));
82: break;
83: case Tab:
84: {value dm= Vnil;
85: Overall {
86: if (dm == Vnil || (*rel)(compare(Dts(*tp), dm)))
87: dm= Dts(*tp);
88: tp++;
89: }
90: m= copy(dm);
91: } break;
92: default:
93: syserr("min or max t, with non text, list or table");
94: }
95: return m;
96: }
97:
98: Hidden value mm2(v, t, rel) value v, t; bool (*rel)(); {
99: intlet len= Length(t), k; value m= Vnil, *tp= Ats(t);
100: switch (t->type) {
101: case Tex:
102: {string cp= (string) tp; char c, mc= '\0', mm[2];
103: c= *Str(v);
104: Overall {
105: if ((*rel)(c < *cp ? -1 : c > *cp ? 1 : 0)) {
106: if (mc == '\0' || (*rel)(*cp < mc ? -1 : *cp>mc ? 1 : 0))
107: mc= *cp;
108: }
109: cp++;
110: }
111: if (mc != '\0') {
112: mm[0]= mc; mm[1]= '\0';
113: m= mk_text(mm);
114: }
115: } break;
116: case Lis:
117: {intlet lim1, mid, lim2;
118: if ((*rel)(-1)) { /*min*/
119: lim1= 1; lim2= len-1;
120: } else {
121: lim2= 1; lim1= len-1;
122: }
123: if (!(*rel)(compare(v, Lisent(tp,lim2)))) break;
124: if (len == 1 || (*rel)(compare(v, Lisent(tp,lim1)))) {
125: m= copy(Lisent(tp,lim1));
126: break;
127: }
128: /* v rel tp[lim2] && !(v rel tp[lim1]) */
129: while (abs(lim2-lim1) > 1) {
130: mid= (lim1+lim2)/2;
131: if ((*rel)(compare(v, Lisent(tp,mid)))) lim2= mid;
132: else lim1= mid;
133: }
134: m= copy(Lisent(tp,lim2));
135: } break;
136: case Tab:
137: {value dm= Vnil;
138: Overall {
139: if ((*rel)(compare(v, Dts(*tp)))) {
140: if (dm == Vnil ||
141: (*rel)(compare(Dts(*tp), dm)))
142: dm= Dts(*tp);
143: }
144: tp++;
145: }
146: if (dm != Vnil) m= copy(dm);
147: } break;
148: default:
149: syserr("min2 or max2 with non text, list or table");
150: break;
151: }
152: return m;
153: }
154:
155: Visible value min1(t) value t; { /* Monadic min */
156: if (!Is_tlt(t)) error("in min t, t is not a text, list or table");
157: if (Length(t) == 0) error("in min t, t is empty");
158: return mm1(t, less);
159: }
160:
161: Visible value min2(v, t) value v, t; {
162: value m;
163: if (!Is_tlt(t)) error("in e min t, t is not a text, list or table");
164: if (Length(t) == 0) error("in e min t, t is empty");
165: if (Is_text(t)) {
166: if (!Is_text(v)) error("in e min t, t is a text but e is not");
167: if (Length(v) != 1) error("in e min t, e is a text but not a character");
168: }
169: m= mm2(v, t, less);
170: if (m == Vnil) error("in e min t, no element of t exceeds e");
171: return m;
172: }
173:
174: Visible value max1(t) value t; {
175: if (!Is_tlt(t)) error("in max t, t is not a text, list or table");
176: if (Length(t) == 0) error("in max t, t is empty");
177: return mm1(t, greater);
178: }
179:
180: Visible value max2(v, t) value v, t; {
181: value m;
182: if (!Is_tlt(t)) error("in e max t, t is not a text, list or table");
183: if (Length(t) == 0) error("in e max t, t is empty");
184: if (Is_text(t)) {
185: if (!Is_text(v)) error("in e max t, t is a text but e is not");
186: if (Length(v) != 1) error("in e max t, e is a text but not a character");
187: }
188: m= mm2(v, t, greater);
189: if (m == Vnil) error("in e max t, no element of t is less than e");
190: return m;
191: }
192:
193: Visible value th_of(n, t) value n, t; {
194: return thof(intval(n), t);
195: }
196:
197: Visible value thof(n, t) int n; value t; {
198: intlet len= Length(t); value w;
199: if (!Is_tlt(t)) error("in n th'of t, t is not a text, list or table");
200: if (n <= 0 || n > len) error("in n th'of t, n is out of bounds");
201: switch (t->type) {
202: case Tex:
203: {char ww[2];
204: ww[0]= *(Str(t)+n-1); ww[1]= '\0';
205: w= mk_text(ww);
206: } break;
207: case Lis:
208: w= copy(*(Ats(t)+n-1));
209: break;
210: case Tab:
211: w= copy(Dts(*(Ats(t)+n-1)));
212: break;
213: default:
214: syserr("th'of with non text, list or table");
215: }
216: return w;
217: }
218:
219: Visible bool found(elem, v, probe, where)
220: value (*elem)(), v, probe; intlet *where;
221: /* think of elem(v,lo-1) as -Infinity and elem(v,hi+1) as +Infinity.
222: found and where at the end satisfy:
223: SELECT:
224: SOME k IN {lo..hi} HAS probe = elem(v,k):
225: found = Yes AND where = k
226: ELSE: found = No AND elem(v,where-1) < probe < elem(v,where).
227: */
228: {relation c; intlet lo=0, hi= Length(v)-1;
229: if (lo > hi) { *where= lo; return No; }
230: if ((c= compare(probe, (*elem)(v, lo))) == 0) {*where= lo; return Yes; }
231: if (c < 0) { *where=lo; return No; }
232: if (lo == hi) { *where=hi+1; return No; }
233: if ((c= compare(probe, (*elem)(v, hi))) == 0) { *where=hi; return Yes; }
234: if (c > 0) { *where=hi+1; return No; }
235: /* elem(lo) < probe < elem(hi) */
236: while (hi-lo > 1) {
237: if ((c= compare(probe, (*elem)(v, (lo+hi)/2))) == 0) {
238: *where= (lo+hi)/2; return Yes;
239: }
240: if (c < 0) hi= (lo+hi)/2; else lo= (lo+hi)/2;
241: }
242: *where= hi; return No;
243: }
244:
245: Visible bool in(v, t) value v, t; {
246: intlet where, k, len= Length(t); value *tp= Ats(t);
247: if (!Is_tlt(t)) error("in the test e in t, t is not a text, list or table");
248: switch (t->type) {
249: case Tex:
250: if (v->type != Tex)
251: error("in the test e in t, t is a text but e is not");
252: if (Length(v) != 1)
253: error("in the test e in t, e is a text but not a character");
254: return index((string) tp, *Str(v)) != 0;
255: case ELT:
256: return No;
257: case Lis:
258: return found(list_elem, t, v, &where);
259: case Tab:
260: Overall if (compare(v, Dts(*tp++)) == 0) return Yes;
261: return No;
262: default:
263: syserr("e in t with non text, list or table");
264: return No;
265: }
266: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.