|
|
1.1 root 1: /*
2: * File: oarith.c
3: * Contents: div, minus, mod, mult, neg, number, plus, power
4: */
5:
6: #include "../h/rt.h"
7: #ifdef SUN
8: #include <math.h>
9: #include <signal.h>
10: #endif SUN
11:
12: #ifdef NoOver
13: #define Add(x,y) (x + y)
14: #define Sub(x,y) (x - y)
15: #define Mpy(x,y) (x * y)
16: #else NoOver
17: #define Add(x,y) ckadd(x,y)
18: #define Sub(x,y) cksub(x,y)
19: #define Mpy(x,y) ckmul(x,y)
20: #endif NoOver
21:
22: /*
23: * x / y - divide y into x.
24: */
25:
26: OpDcl(div,2,"/")
27: {
28: register int t1, t2;
29: union numeric n1, n2;
30:
31: /*
32: * x and y must be numbers.
33: */
34: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
35: runerr(102, &Arg1);
36: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
37: runerr(102, &Arg2);
38:
39: if (!(t1 == T_Real || t2 == T_Real)) {
40: /*
41: * x and y are both integers, just divide them and return the result.
42: */
43: if (n2.integer == 0L)
44: runerr(201, &Arg2);
45: Mkint(n1.integer / n2.integer, &Arg0);
46: }
47: else {
48: /*
49: * Either x or y or both is real, convert the real values to integers,
50: * divide them, and return the result.
51: */
52: if (!(t1 == T_Real))
53: n1.real = n1.integer;
54: if (!(t2 == T_Real))
55: n2.real = n2.integer;
56: #ifdef ZeroDivide
57: if (n2.real == 0.0)
58: runerr(204,0);
59: #endif ZeroDivide
60: mkreal(n1.real / n2.real, &Arg0);
61: #ifdef SUN
62: if (((struct b_real *)BlkLoc(Arg0))->realval == HUGE)
63: kill(getpid(),SIGFPE);
64: #endif SUN
65: }
66: Return;
67: }
68:
69:
70: /*
71: * x - y - subtract y from x.
72: */
73:
74: OpDcl(minus,2,"-")
75: {
76: register int t1, t2;
77: union numeric n1, n2;
78: #ifndef NoOver
79: extern long cksub();
80: #endif NoOver
81:
82: /*
83: * x and y must be numeric. Save the cvnum return values for later use.
84: */
85: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
86: runerr(102, &Arg1);
87: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
88: runerr(102, &Arg2);
89:
90: if (!(t1 == T_Real || t2 == T_Real)) {
91: /*
92: * Both x and y are integers. Perform integer subtraction and place
93: * the result in Arg0 as the return value.
94: */
95: Mkint(Sub(n1.integer, n2.integer), &Arg0);
96: }
97: else {
98: /*
99: * Either x or y is real, convert the other to a real, perform
100: * the subtraction and place the result in Arg0 as the return value.
101: */
102: if (!(t1 == T_Real))
103: n1.real = n1.integer;
104: if (!(t2 == T_Real))
105: n2.real = n2.integer;
106: mkreal(n1.real - n2.real, &Arg0);
107: }
108: Return;
109: }
110:
111:
112: /*
113: * x % y - take remainder of x / y.
114: */
115:
116: OpDcl(mod,2,"%")
117: {
118: register int t1, t2;
119: union numeric n1, n2;
120:
121: /*
122: * x and y must be numeric. Save the cvnum return values for later use.
123: */
124: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
125: runerr(102, &Arg1);
126: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
127: runerr(102, &Arg2);
128:
129: if (!(t1 == T_Real || t2 == T_Real)) {
130: /*
131: * Both x and y are integers. If y is 0, generate an error because
132: * it's divide by 0. Otherwise, just return the modulus of the
133: * two arguments.
134: */
135: if (n2.integer == 0L)
136: runerr(202, &Arg2);
137: Mkint(n1.integer % n2.integer, &Arg0);
138: }
139: else {
140: /*
141: * Either x or y is real, convert the other to a real, perform
142: * the modulation, convert the result to an integer and place it
143: * in Arg0 as the return value.
144: */
145: if (!(t1 == T_Real))
146: n1.real = n1.integer;
147: if (!(t2 == T_Real))
148: n2.real = n2.integer;
149: mkreal(n1.real - n2.real * (int)(n1.real / n2.real), &Arg0);
150: }
151: Return;
152: }
153:
154:
155: /*
156: * x * y - multiply x and y.
157: */
158:
159: OpDcl(mult,2,"*")
160: {
161: register int t1, t2;
162: union numeric n1, n2;
163: #ifndef NoOver
164: extern long ckmul();
165: #endif NoOver
166:
167: /*
168: * x and y must be numeric. Save the cvnum return values for later use.
169: */
170: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
171: runerr(102, &Arg1);
172: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
173: runerr(102, &Arg2);
174:
175: if (!(t1 == T_Real || t2 == T_Real)) {
176: /*
177: * Both x and y are integers. Perform the multiplication and
178: * and place the result in Arg0 as the return value.
179: */
180: Mkint(Mpy(n1.integer,n2.integer), &Arg0);
181: }
182: else {
183: /*
184: * Either x or y is real, convert the other to a real, perform
185: * the subtraction and place the result in Arg0 as the return value.
186: */
187: if (!(t1 == T_Real))
188: n1.real = n1.integer;
189: if (!(t2 == T_Real))
190: n2.real = n2.integer;
191: mkreal(n1.real * n2.real, &Arg0);
192: }
193: Return;
194: }
195:
196:
197: /*
198: * -x - negate x.
199: */
200:
201: OpDcl(neg,1,"-")
202: {
203: union numeric n;
204: long l;
205:
206: /*
207: * x must be numeric.
208: */
209: switch (cvnum(&Arg1, &n)) {
210:
211: case T_Integer:
212: case T_Longint:
213: /*
214: * If it's an integer, check for overflow by negating it and
215: * seeing if the negation didn't "work". Use Mkint to
216: * construct the return value.
217: */
218: l = -n.integer;
219: if (n.integer < 0 && l < 0)
220: runerr(203, &Arg1);
221: Mkint(l, &Arg0);
222: break;
223:
224: case T_Real:
225: /*
226: * x is real, just negate it and use mkreal to construct the
227: * return value.
228: */
229: mkreal(-n.real, &Arg0);
230: break;
231:
232: default:
233: /*
234: * x isn't numeric.
235: */
236: runerr(102, &Arg1);
237: }
238: Return;
239: }
240:
241:
242: /*
243: * +x - convert x to numeric type.
244: * Operational definition: generate runerr if x is not numeric.
245: */
246:
247: OpDcl(number,1,"+")
248: {
249: union numeric n;
250:
251: switch (cvnum(&Arg1, &n)) {
252:
253: case T_Integer:
254: case T_Longint:
255: Mkint(n.integer, &Arg0);
256: break;
257:
258: case T_Real:
259: mkreal(n.real, &Arg0);
260: break;
261:
262: default:
263: runerr(102, &Arg1);
264: }
265: Return;
266: }
267:
268:
269: /*
270: * x + y - add x and y.
271: */
272:
273: OpDcl(plus,2,"+")
274: {
275: register int t1, t2;
276: union numeric n1, n2;
277: #ifndef NoOver
278: extern long ckadd();
279: #endif NoOver
280:
281: /*
282: * x and y must be numeric. Save the cvnum return values for later use.
283: */
284: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
285: runerr(102, &Arg1);
286: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
287: runerr(102, &Arg2);
288:
289: if (!(t1 == T_Real || t2 == T_Real)) {
290: /*
291: * Both x and y are integers. Perform integer addition and plcae the
292: * result in Arg0 as the return value.
293: */
294: Mkint(Add(n1.integer, n2.integer), &Arg0);
295: }
296: else {
297: /*
298: * Either x or y is real, convert the other to a real, perform
299: * the addition and place the result in Arg0 as the return value.
300: */
301: if (!(t1 == T_Real))
302: n1.real = n1.integer;
303: if (!(t2 == T_Real))
304: n2.real = n2.integer;
305: mkreal(n1.real + n2.real, &Arg0);
306: }
307: Return;
308: }
309:
310:
311:
312:
313: /*
314: * x ^ y - raise x to the y power.
315: */
316:
317: OpDcl(power,2,"^")
318: {
319: register int t1, t2;
320: union numeric n1, n2;
321: extern double pow();
322: extern long ipow();
323:
324: /*
325: * x and y must be numeric. Save the cvnum return values for later use.
326: */
327: if ((t1 = cvnum(&Arg1, &n1)) == NULL)
328: runerr(102, &Arg1);
329: if ((t2 = cvnum(&Arg2, &n2)) == NULL)
330: runerr(102, &Arg2);
331:
332: if (!(t1 == T_Real || t2 == T_Real)) {
333: /*
334: * Both x and y are integers. Perform integer exponentiation
335: * and place the result in Arg0 as the return value.
336: */
337: Mkint(ipow(n1.integer, n2.integer), &Arg0);
338: }
339: else {
340: /*
341: * Either x or y is real, convert the other to a real, perform
342: * real exponentiation and place the result in Arg0 as the
343: * return value.
344: */
345: if (!(t1 == T_Real))
346: n1.real = n1.integer;
347: if (!(t2 == T_Real))
348: n2.real = n2.integer;
349: if (n1.real == 0.0 && n2.real <= 0.0)
350: /*
351: * Tried to raise zero to a negative power.
352: */
353: runerr(204, NULL);
354: if (n1.real < 0.0 && t2 == T_Real)
355: /*
356: * Tried to raise a negative number to a real power.
357: */
358: runerr(206, NULL);
359: mkreal(pow(n1.real,n2.real), &Arg0);
360: }
361: Return;
362: }
363:
364: long ipow(n1, n2)
365: long n1, n2;
366: {
367: long result;
368:
369: if (n1 == 0 && n2 <= 0)
370: runerr(204, NULL);
371: if (n2 < 0)
372: return 0.0;
373: result = 1L;
374: while (n2 > 0) {
375: if (n2 & 01L)
376: result *= n1;
377: n1 *= n1;
378: n2 >>= 1;
379: }
380: return result;
381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.