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