|
|
1.1 root 1: /*
2: * File: rcomp.c
3: * Contents: anycmp, equiv, lexcmp, numcmp
4: */
5:
6: #include "../h/rt.h"
7:
8: /*
9: * anycmp - compare any two objects. The result of the comparison is
10: * an integer such that:
11: * d1 = d2 -> 0
12: * d1 > d2 -> >0 (1 if same type)
13: * d1 < d2 -> <0 (-1 if same type)
14: */
15:
16: anycmp(d1,d2)
17: struct descrip *d1, *d2;
18: {
19: register int o1, o2;
20: register long lresult;
21: double rres1, rres2, rresult;
22:
23: /*
24: * Get a collating number for d1 and d2.
25: */
26: o1 = order(d1);
27: o2 = order(d2);
28:
29: /*
30: * If d1 and d2 aren't of the same type, return the difference of
31: * their collating numbers.
32: */
33: if (o1 != o2)
34: return (o1 - o2);
35:
36: if (o1 == D_Null)
37: /*
38: * o1 0, (D_Null), return 0 because all null values are the same.
39: */
40: return 0;
41: if (o1 == 3)
42: /*
43: * d1 and d2 are strings, use lexcmp to compare them.
44: */
45: return lexcmp(d1,d2);
46:
47: switch (Type(*d1)) {
48: /*
49: * For numbers, return -1, 0, 1, depending on whether d1 <, =, > d2.
50: */
51: case T_Integer:
52: lresult = IntVal(*d1) - IntVal(*d2);
53: if (lresult == 0)
54: return 0;
55: return ((lresult > 0) ? 1 : -1);
56:
57: case T_Longint:
58: lresult = BlkLoc(*d1)->longint.intval - BlkLoc(*d2)->longint.intval;
59: if (lresult == 0)
60: return 0;
61: return ((lresult > 0) ? 1 : -1);
62:
63: case T_Real:
64: GetReal(d1,rres1);
65: GetReal(d2,rres2);
66: rresult = rres1 - rres2;
67: if (rresult == 0)
68: return 0;
69: return ((rresult > 0) ? 1 : -1);
70:
71: case T_Cset:
72: case T_File:
73: case T_Proc:
74: case T_List:
75: case T_Table:
76: case T_Set:
77: case T_Record:
78: case T_Coexpr:
79: /*
80: * Csets, files, procedures, lists, tables, records, co-expressions
81: * and sets have no specified collating sequence so any two of
82: * the same type are considered to be equal.
83: */
84: return 0;
85:
86: default:
87: syserr("anycmp: unknown datatype.");
88: }
89: }
90:
91: /*
92: * order(x) - return collating number for object x.
93: */
94:
95: order(d)
96: struct descrip *d;
97: {
98: if (Qual(*d))
99: return 3; /* string */
100: switch (Type(*d)) {
101: case T_Null:
102: return 0;
103: case T_Integer:
104: case T_Longint:
105: return 1;
106: case T_Real:
107: return 2;
108: case T_Cset:
109: return 4;
110: case T_Coexpr:
111: return 5;
112: case T_File:
113: return 6;
114: case T_Proc:
115: return 7;
116: case T_List:
117: return 8;
118: case T_Table:
119: return 9;
120: case T_Set:
121: return 10;
122: case T_Record:
123: return 11;
124: default:
125: syserr("order: unknown datatype.");
126: }
127: }
128:
129:
130: /*
131: * equiv - test equivalence of two objects.
132: */
133:
134: equiv(dp1, dp2)
135: struct descrip *dp1, *dp2;
136: {
137: register int result, i;
138: register char *s1, *s2;
139: double rres1, rres2;
140:
141: result = 0;
142:
143: /*
144: * If the descriptors are identical, the objects are equivalent.
145: */
146: if (EqlDesc(*dp1,*dp2))
147: result = 1;
148: else if (Qual(*dp1) && Qual(*dp2)) {
149:
150: /*
151: * If both are strings of equal length, compare their characters.
152: */
153:
154: if ((i = StrLen(*dp1)) == StrLen(*dp2)) {
155: s1 = StrLoc(*dp1);
156: s2 = StrLoc(*dp2);
157: result = 1;
158: while (i--)
159: if (*s1++ != *s2++) {
160: result = 0;
161: break;
162: }
163: }
164: }
165: else if (dp1->dword == dp2->dword)
166: switch (Type(*dp1)) {
167: /*
168: * For integers and reals, just compare the values.
169: */
170: case T_Integer:
171: result = (IntVal(*dp1) == IntVal(*dp2));
172: break;
173:
174: case T_Longint:
175: result =
176: (BlkLoc(*dp1)->longint.intval == BlkLoc(*dp2)->longint.intval);
177: break;
178:
179: case T_Real:
180: GetReal(dp1, rres1);
181: GetReal(dp2, rres2);
182: result = (rres1 == rres2);
183: break;
184:
185: case T_Cset:
186: /*
187: * Compare the bit arrays of the csets.
188: */
189: result = 1;
190: for (i = 0; i < CsetSize; i++)
191: if (BlkLoc(*dp1)->cset.bits[i] != BlkLoc(*dp2)->cset.bits[i]) {
192: result = 0;
193: break;
194: }
195: }
196: else
197: /*
198: * dp1 and dp2 are of different types, so they can't be
199: * equivalent.
200: */
201: result = 0;
202:
203: return result;
204: }
205:
206:
207: /*
208: * lexcmp - lexically compare two strings.
209: */
210:
211: lexcmp(d1, d2)
212: struct descrip *d1, *d2;
213: {
214: register char *s1, *s2;
215: register int minlen;
216: int l1, l2;
217:
218: /*
219: * Get length and starting address of both strings.
220: */
221: l1 = StrLen(*d1);
222: s1 = StrLoc(*d1);
223: l2 = StrLen(*d2);
224: s2 = StrLoc(*d2);
225:
226: /*
227: * Set minlen to length of the shorter string.
228: */
229: minlen = (l1 <= l2) ? l1 : l2;
230:
231: /*
232: * Compare as many bytes as are in the smaller string. If an
233: * inequality is found, return the difference of the differing
234: * bytes.
235: */
236: while (minlen--)
237: if (*s1++ != *s2++)
238: return (int)((*--s1 & 0377) - (*--s2 & 0377));
239:
240: /*
241: * The strings compared equal for the length of the shorter. Return
242: * the difference in their lengths. (Thus, the strings must be of
243: * the same length to be equal.)
244: */
245: return (l1 - l2);
246: }
247:
248:
249: /*
250: * numcmp - compare two numbers. Returns -1, 0, 1 for dp1 <, =, > dp2.
251: * dp3 is made into a descriptor for the return value.
252: */
253:
254: numcmp(dp1, dp2, dp3)
255: struct descrip *dp1, *dp2, *dp3;
256: {
257: register int result;
258: union numeric n1, n2;
259: int t1, t2;
260: /*
261: * Be sure that both dp1 and dp2 are numeric.
262: */
263:
264: if ((t1 = cvnum(dp1, &n1)) == NULL)
265: runerr(102, dp1);
266: if ((t2 = cvnum(dp2, &n2)) == NULL)
267: runerr(102, dp2);
268:
269: if (!(t1 == T_Real || t2 == T_Real)) {
270: /*
271: * dp1 and dp2 are both integers, compare them and
272: * create an integer descriptor in dp3
273: */
274:
275: result = 0;
276: if (n1.integer < n2.integer) result = -1;
277: else if (n1.integer != n2.integer) result = 1;
278: Mkint(n2.integer, dp3);
279: }
280: else {
281:
282: /*
283: * Either dp1 or dp2 is real. Convert the other to a real,
284: * compare them and create a real descriptor in dp3.
285: */
286:
287: if (!(t1 == T_Real))
288: n1.real = n1.integer;
289: if (!(t2 == T_Real))
290: n2.real = n2.integer;
291: result = 0;
292: if (n1.real < n2.real) result = -1;
293: else if (n1.real != n2.real) result = 1;
294: mkreal(n2.real, dp3);
295: }
296:
297: return result; /* return result in r0 */
298: }
299:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.