1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Arithmetic operators */
18 #include "math_.h"
19 #include "ghost.h"
20 #include "oper.h"
21 #include "store.h"
22 
23 /****** NOTE: none of the arithmetic operators  ******/
24 /****** currently check for floating exceptions ******/
25 
26 /*
27  * Many of the procedures in this file are public only so they can be
28  * called from the FunctionType 4 interpreter (zfunc4.c).
29  */
30 
31 /* Define max and min values for what will fit in value.intval. */
32 #define MIN_INTVAL 0x80000000
33 #define MAX_INTVAL 0x7fffffff
34 
35 /* <num1> <num2> add <sum> */
36 /* We make this into a separate procedure because */
37 /* the interpreter will almost always call it directly. */
38 int
zop_add(register os_ptr op)39 zop_add(register os_ptr op)
40 {
41     switch (r_type(op)) {
42     default:
43         return_op_typecheck(op);
44     case t_real:
45         switch (r_type(op - 1)) {
46         default:
47             return_op_typecheck(op - 1);
48         case t_real:
49             op[-1].value.realval += op->value.realval;
50             break;
51         case t_integer:
52             make_real(op - 1, (double)op[-1].value.intval + op->value.realval);
53         }
54         break;
55     case t_integer:
56         switch (r_type(op - 1)) {
57         default:
58             return_op_typecheck(op - 1);
59         case t_real:
60             op[-1].value.realval += (double)op->value.intval;
61             break;
62         case t_integer: {
63             int int2 = op->value.intval;
64 
65             if (((op[-1].value.intval += int2) ^ int2) < 0 &&
66                 ((op[-1].value.intval - int2) ^ int2) >= 0
67                 ) {			/* Overflow, convert to real */
68                 make_real(op - 1, (double)(op[-1].value.intval - int2) + int2);
69             }
70         }
71         }
72     }
73     return 0;
74 }
75 int
zadd(i_ctx_t * i_ctx_p)76 zadd(i_ctx_t *i_ctx_p)
77 {
78     os_ptr op = osp;
79     int code = zop_add(op);
80 
81     if (code == 0) {
82         pop(1);
83     }
84     return code;
85 }
86 
87 /* <num1> <num2> div <real_quotient> */
88 int
zdiv(i_ctx_t * i_ctx_p)89 zdiv(i_ctx_t *i_ctx_p)
90 {
91     os_ptr op = osp;
92     os_ptr op1 = op - 1;
93 
94     /* We can't use the non_int_cases macro, */
95     /* because we have to check explicitly for op == 0. */
96     switch (r_type(op)) {
97         default:
98             return_op_typecheck(op);
99         case t_real:
100             if (op->value.realval == 0)
101                 return_error(e_undefinedresult);
102             switch (r_type(op1)) {
103                 default:
104                     return_op_typecheck(op1);
105                 case t_real:
106                     op1->value.realval /= op->value.realval;
107                     break;
108                 case t_integer:
109                     make_real(op1, (double)op1->value.intval / op->value.realval);
110             }
111             break;
112         case t_integer:
113             if (op->value.intval == 0)
114                 return_error(e_undefinedresult);
115             switch (r_type(op1)) {
116                 default:
117                     return_op_typecheck(op1);
118                 case t_real:
119                     op1->value.realval /= (double)op->value.intval;
120                     break;
121                 case t_integer:
122                     make_real(op1, (double)op1->value.intval / (double)op->value.intval);
123             }
124     }
125     pop(1);
126     return 0;
127 }
128 
129 /* <num1> <num2> mul <product> */
130 int
zmul(i_ctx_t * i_ctx_p)131 zmul(i_ctx_t *i_ctx_p)
132 {
133     os_ptr op = osp;
134 
135     switch (r_type(op)) {
136     default:
137         return_op_typecheck(op);
138     case t_real:
139         switch (r_type(op - 1)) {
140         default:
141             return_op_typecheck(op - 1);
142         case t_real:
143             op[-1].value.realval *= op->value.realval;
144             break;
145         case t_integer:
146             make_real(op - 1, (double)op[-1].value.intval * op->value.realval);
147         }
148         break;
149     case t_integer:
150         switch (r_type(op - 1)) {
151         default:
152             return_op_typecheck(op - 1);
153         case t_real:
154             op[-1].value.realval *= (double)op->value.intval;
155             break;
156         case t_integer: {
157             double ab = (double)op[-1].value.intval * op->value.intval;
158             if (ab > 2147483647.)       /* (double)0x7fffffff */
159                 make_real(op - 1, ab);
160             else if (ab < -2147483648.) /* (double)(int)0x80000000 */
161                 make_real(op - 1, ab);
162             else
163                 op[-1].value.intval = (int)ab;
164         }
165         }
166     }
167     pop(1);
168     return 0;
169 }
170 
171 /* <num1> <num2> sub <difference> */
172 /* We make this into a separate procedure because */
173 /* the interpreter will almost always call it directly. */
174 int
zop_sub(register os_ptr op)175 zop_sub(register os_ptr op)
176 {
177     switch (r_type(op)) {
178     default:
179         return_op_typecheck(op);
180     case t_real:
181         switch (r_type(op - 1)) {
182         default:
183             return_op_typecheck(op - 1);
184         case t_real:
185             op[-1].value.realval -= op->value.realval;
186             break;
187         case t_integer:
188             make_real(op - 1, (double)op[-1].value.intval - op->value.realval);
189         }
190         break;
191     case t_integer:
192         switch (r_type(op - 1)) {
193         default:
194             return_op_typecheck(op - 1);
195         case t_real:
196             op[-1].value.realval -= (double)op->value.intval;
197             break;
198         case t_integer: {
199             int int1 = op[-1].value.intval;
200 
201             if ((int1 ^ (op[-1].value.intval = int1 - op->value.intval)) < 0 &&
202                 (int1 ^ op->value.intval) < 0
203                 ) {			/* Overflow, convert to real */
204                 make_real(op - 1, (float)int1 - op->value.intval);
205             }
206         }
207         }
208     }
209     return 0;
210 }
211 int
zsub(i_ctx_t * i_ctx_p)212 zsub(i_ctx_t *i_ctx_p)
213 {
214     os_ptr op = osp;
215     int code = zop_sub(op);
216 
217     if (code == 0) {
218         pop(1);
219     }
220     return code;
221 }
222 
223 /* <num1> <num2> idiv <int_quotient> */
224 int
zidiv(i_ctx_t * i_ctx_p)225 zidiv(i_ctx_t *i_ctx_p)
226 {
227     os_ptr op = osp;
228 
229     check_type(*op, t_integer);
230     check_type(op[-1], t_integer);
231     if ((op->value.intval == 0) || (op[-1].value.intval == MIN_INTVAL && op->value.intval == -1)) {
232         /* Anomalous boundary case: -MININT / -1, fail. */
233         return_error(e_undefinedresult);
234     }
235     op[-1].value.intval /= op->value.intval;
236     pop(1);
237     return 0;
238 }
239 
240 /* <int1> <int2> mod <remainder> */
241 int
zmod(i_ctx_t * i_ctx_p)242 zmod(i_ctx_t *i_ctx_p)
243 {
244     os_ptr op = osp;
245 
246     check_type(*op, t_integer);
247     check_type(op[-1], t_integer);
248     if (op->value.intval == 0)
249         return_error(e_undefinedresult);
250     op[-1].value.intval %= op->value.intval;
251     pop(1);
252     return 0;
253 }
254 
255 /* <num1> neg <num2> */
256 int
zneg(i_ctx_t * i_ctx_p)257 zneg(i_ctx_t *i_ctx_p)
258 {
259     os_ptr op = osp;
260 
261     switch (r_type(op)) {
262         default:
263             return_op_typecheck(op);
264         case t_real:
265             op->value.realval = -op->value.realval;
266             break;
267         case t_integer:
268             if (op->value.intval == MIN_INTVAL)
269                 make_real(op, -(float)MIN_INTVAL);
270             else
271                 op->value.intval = -op->value.intval;
272     }
273     return 0;
274 }
275 
276 /* <num1> abs <num2> */
277 int
zabs(i_ctx_t * i_ctx_p)278 zabs(i_ctx_t *i_ctx_p)
279 {
280     os_ptr op = osp;
281 
282     switch (r_type(op)) {
283         default:
284             return_op_typecheck(op);
285         case t_real:
286             if (op->value.realval >= 0)
287                 return 0;
288             break;
289         case t_integer:
290             if (op->value.intval >= 0)
291                 return 0;
292             break;
293     }
294     return zneg(i_ctx_p);
295 }
296 
297 /* <num1> ceiling <num2> */
298 int
zceiling(i_ctx_t * i_ctx_p)299 zceiling(i_ctx_t *i_ctx_p)
300 {
301     os_ptr op = osp;
302 
303     switch (r_type(op)) {
304         default:
305             return_op_typecheck(op);
306         case t_real:
307             op->value.realval = ceil(op->value.realval);
308         case t_integer:;
309     }
310     return 0;
311 }
312 
313 /* <num1> floor <num2> */
314 int
zfloor(i_ctx_t * i_ctx_p)315 zfloor(i_ctx_t *i_ctx_p)
316 {
317     os_ptr op = osp;
318 
319     switch (r_type(op)) {
320         default:
321             return_op_typecheck(op);
322         case t_real:
323             op->value.realval = floor(op->value.realval);
324         case t_integer:;
325     }
326     return 0;
327 }
328 
329 /* <num1> round <num2> */
330 int
zround(i_ctx_t * i_ctx_p)331 zround(i_ctx_t *i_ctx_p)
332 {
333     os_ptr op = osp;
334 
335     switch (r_type(op)) {
336         default:
337             return_op_typecheck(op);
338         case t_real:
339             op->value.realval = floor(op->value.realval + 0.5);
340         case t_integer:;
341     }
342     return 0;
343 }
344 
345 /* <num1> truncate <num2> */
346 int
ztruncate(i_ctx_t * i_ctx_p)347 ztruncate(i_ctx_t *i_ctx_p)
348 {
349     os_ptr op = osp;
350 
351     switch (r_type(op)) {
352         default:
353             return_op_typecheck(op);
354         case t_real:
355             op->value.realval =
356                 (op->value.realval < 0.0 ?
357                  ceil(op->value.realval) :
358                  floor(op->value.realval));
359         case t_integer:;
360     }
361     return 0;
362 }
363 
364 /* Non-standard operators */
365 
366 /* <int1> <int2> .bitadd <sum> */
367 static int
zbitadd(i_ctx_t * i_ctx_p)368 zbitadd(i_ctx_t *i_ctx_p)
369 {
370     os_ptr op = osp;
371 
372     check_type(*op, t_integer);
373     check_type(op[-1], t_integer);
374     op[-1].value.intval += op->value.intval;
375     pop(1);
376     return 0;
377 }
378 
379 /* ------ Initialization table ------ */
380 
381 const op_def zarith_op_defs[] =
382 {
383     {"1abs", zabs},
384     {"2add", zadd},
385     {"2.bitadd", zbitadd},
386     {"1ceiling", zceiling},
387     {"2div", zdiv},
388     {"2idiv", zidiv},
389     {"1floor", zfloor},
390     {"2mod", zmod},
391     {"2mul", zmul},
392     {"1neg", zneg},
393     {"1round", zround},
394     {"2sub", zsub},
395     {"1truncate", ztruncate},
396     op_def_end(0)
397 };
398