|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2:
3: /*
4: $Header: b1obj.c,v 1.4 85/08/22 16:52:13 timo Exp $
5: */
6:
7: /* Generic routines for all values */
8:
9: #include "b.h"
10: #include "b1obj.h"
11: #ifndef INTEGRATION
12: #include "b1btr.h"
13: #include "b1val.h"
14: #endif
15: #include "b1tlt.h"
16: #include "b3err.h"
17: #include "b3typ.h"
18:
19: #ifndef INTEGRATION
20:
21: Visible bool comp_ok = Yes; /* Temporary, to catch type errors */
22:
23: relation comp_tlt(), comp_text(); /* From b1lta.c */
24:
25: Hidden Procedure incompatible(v, w) value v, w; {
26: value message, m1, m2, m3, m4, m5, m6;
27: message= concat(m1= convert(m2= (value) valtype(v), No, No),
28: m3= concat(m4= mk_text(" and "),
29: m5= convert(m6= (value) valtype(w), No, No)));
30: error2(MESS(1400, "incompatible types "), message);
31: release(message);
32: release(m1); release(m2); release(m3);
33: release(m4); release(m5); release(m6);
34: }
35:
36: Visible relation compare(v, w) value v, w; {
37: literal vt, wt;
38: int i;
39: relation rel;
40:
41: comp_ok = Yes;
42:
43: if (v EQ w) return(0);
44: if (IsSmallInt(v) && IsSmallInt(w))
45: return SmallIntVal(v) - SmallIntVal(w);
46: vt = Type(v);
47: wt = Type(w);
48: switch (vt) {
49: case Num:
50: if (wt != Num) {
51: incomp:
52: /*Temporary until static checks are implemented*/
53: incompatible(v, w);
54: comp_ok= No;
55: return -1;
56: }
57: return(numcomp(v, w));
58: case Com:
59: if (wt != Com || Nfields(v) != Nfields(w)) goto incomp;
60: for (i = 0; i < Nfields(v); i++) {
61: rel = compare(*Field(v, i), *Field(w, i));
62: if (rel NE 0) return(rel);
63: }
64: return(0);
65: case Tex:
66: if (wt != Tex) goto incomp;
67: return(comp_text(v, w));
68: case Lis:
69: if (wt != Lis && wt != ELT) goto incomp;
70: return(comp_tlt(v, w));
71: case Tab:
72: if (wt != Tab && wt != ELT) goto incomp;
73: return(comp_tlt(v, w));
74: case ELT:
75: if (wt != Tab && wt != Lis && wt != ELT) goto incomp;
76: return(Root(w) EQ Bnil ? 0 : -1);
77: default:
78: syserr(MESS(1401, "comparison of unknown types"));
79: /*NOTREACHED*/
80: }
81: }
82:
83: /* Used for set'random. Needs to be rewritten so that for small changes in v */
84: /* you get large changes in hash(v) */
85:
86: Visible double hash(v) value v; {
87: if (Is_number(v)) return numhash(v);
88: else if (Is_compound(v)) {
89: int len= Nfields(v), k; double d= .404*len;
90: k_Overfields {
91: d= .874*d+.310*hash(*Field(v, k));
92: }
93: return d;
94: } else {
95: int len= length(v), k; double d= .404*len;
96: if (len == 0) return .909;
97: else if (Is_text(v)) {
98: value ch;
99: k_Over_len {
100: ch= thof(k+1, v);
101: d= .987*d+.277*charval(ch);
102: release(ch);
103: }
104: return d;
105: } else if (Is_list(v)) {
106: value el;
107: k_Over_len {
108: d= .874*d+.310*hash(el= thof(k+1, v));
109: release(el);
110: }
111: return d;
112: } else if (Is_table(v)) {
113: k_Over_len {
114: d= .874*d+.310*hash(*key(v, k))
115: +.123*hash(*assoc(v, k));
116: }
117: return d;
118: } else {
119: syserr(MESS(1402, "hash called with unknown type"));
120: return (double) Dummy;
121: }
122: }
123: }
124:
125: Hidden Procedure concato(v, t) value* v; value t; {
126: value v1= *v;
127: *v= concat(*v, t);
128: release(v1);
129: }
130:
131: Visible value convert(v, coll, outer) value v; bool coll, outer; {
132: value t, quote, c, cv, sep, th, open, close; int k, len; char ch;
133: switch (Type(v)) {
134: case Num:
135: return mk_text(convnum(v));
136: case Tex:
137: if (outer) return copy(v);
138: quote= mk_text("\"");
139: len= length(v);
140: t= copy(quote);
141: for (k=1; k<=len; k++) {
142: c= thof(k, v);
143: ch= charval(c);
144: concato(&t, c);
145: if (ch == '"' || ch == '`') concato(&t, c);
146: release(c);
147: }
148: concato(&t, quote);
149: release(quote);
150: break;
151: case Com:
152: len= Nfields(v);
153: outer&= coll;
154: sep= mk_text(outer ? " " : ", ");
155: t= mk_text(coll ? "" : "(");
156: k_Over_len {
157: concato(&t, cv= convert(*Field(v, k), No, outer));
158: release(cv);
159: if (!Last(k)) concato(&t, sep);
160: }
161: release(sep);
162: if (!coll) {
163: concato(&t, cv= mk_text(")"));
164: release(cv);
165: }
166: break;
167: case Lis:
168: case ELT:
169: len= length(v);
170: t= mk_text("{");
171: sep= mk_text("; ");
172: for (k=1; k<=len; k++) {
173: concato(&t, cv= convert(th= thof(k, v), No, No));
174: release(cv); release(th);
175: if (k != len) concato(&t, sep);
176: }
177: release(sep);
178: concato(&t, cv= mk_text("}"));
179: release(cv);
180: break;
181: case Tab:
182: len= length(v);
183: open= mk_text("[");
184: close= mk_text("]: ");
185: sep= mk_text("; ");
186: t= mk_text("{");
187: k_Over_len {
188: concato(&t, open);
189: concato(&t, cv= convert(*key(v, k), Yes, No));
190: release(cv);
191: concato(&t, close);
192: concato(&t, cv= convert(*assoc(v, k), No, No));
193: release(cv);
194: if (!Last(k)) concato(&t, sep);
195: }
196: concato(&t, cv= mk_text("}")); release(cv);
197: release(open); release(close); release(sep);
198: break;
199: default:
200: if (bugs || testing) {
201: t= mk_text("?");
202: concato(&t, cv= mkchar(Type(v))); release(cv);
203: concato(&t, cv= mkchar('$')); release(cv);
204: break;
205: }
206: syserr(MESS(1403, "unknown type in convert"));
207: }
208: return t;
209: }
210:
211: Hidden value adj(v, w, side) value v, w; char side; {
212: value t, c, sp, r, i;
213: int len, wid, diff, left, right;
214: c= convert(v, Yes, Yes);
215: len= length(c);
216: wid= intval(w);
217: if (wid<=len) return c;
218: else {
219: diff= wid-len;
220: if (side == 'L') { left= 0; right= diff; }
221: else if (side == 'R') { left= diff; right= 0; }
222: else {left= diff/2; right= (diff+1)/2; }
223: sp= mk_text(" ");
224: if (left == 0) t= c;
225: else {
226: t= repeat(sp, i= mk_integer(left)); release(i);
227: concato(&t, c);
228: release(c);
229: }
230: if (right != 0) {
231: r= repeat(sp, i= mk_integer(right)); release(i);
232: concato(&t, r);
233: release(r);
234: }
235: release(sp);
236: return t;
237: }
238: }
239:
240: Visible value adjleft(v, w) value v, w; {
241: return adj(v, w, 'L');
242: }
243:
244: Visible value adjright(v, w) value v, w; {
245: return adj(v, w, 'R');
246: }
247:
248: Visible value centre(v, w) value v, w; {
249: return adj(v, w, 'C');
250: }
251:
252: #else INTEGRATION
253:
254: #define Sgn(d) (d)
255:
256: Visible relation compare(v, w) value v, w; {
257: literal vt= Type(v), wt= Type(w);
258: register intlet vlen, wlen, len, k;
259: value message;
260: vlen= IsSmallInt(v) ? 0 : Length(v);
261: wlen= IsSmallInt(w) ? 0 : Length(w);
262: if (v == w) return 0;
263: if (!(vt == wt && !(vt == Com && vlen != wlen) ||
264: vt == ELT && (wt == Lis || wt == Tab) ||
265: wt == ELT && (vt == Lis || vt == Tab))) {
266: message= concat(convert((value) valtype(v), No, No),
267: concat(mk_text(" and "),
268: convert((value) valtype(w), No, No)));
269: error2(MESS(1404, "incompatible types "), message);
270: /*doesn't return: so can't release message*/
271: }
272: if (vt != Num && (vlen == 0 || wlen == 0))
273: return Sgn(vlen-wlen);
274: switch (vt) {
275: case Num: return numcomp(v, w);
276: case Tex: return strcmp(Str(v), Str(w));
277:
278: case Com:
279: case Lis:
280: case Tab:
281: case ELT:
282: {value *vp= Ats(v), *wp= Ats(w);
283: relation c;
284: len= vlen < wlen ? vlen : wlen;
285: Overall if ((c= compare(*vp++, *wp++)) != 0) return c;
286: return Sgn(vlen-wlen);
287: }
288: default:
289: syserr(MESS(1405, "comparison of unknown types"));
290: /* NOTREACHED */
291: }
292: }
293:
294: Visible double hash(v) value v; {
295: literal t= Type(v); intlet len= Length(v), k; double d= t+.404*len;
296: switch (t) {
297: case Num: return numhash(v);
298: case Tex:
299: {string vp= Str(v);
300: Overall d= .987*d+.277*(*vp++);
301: return d;
302: }
303: case Com:
304: case Lis:
305: case Tab:
306: case ELT:
307: {value *vp= Ats(v);
308: if (len == 0) return .909;
309: Overall d= .874*d+.310*hash(*vp++);
310: return d;
311: }
312: default:
313: syserr(MESS(1406, "hash called with unknown type"));
314: /* NOTREACHED */
315: }
316: }
317:
318: #endif INTEGRATION
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.