/src/ghostpdl/psi/zarith.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, 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 | | #include "gsstate.h" |
23 | | |
24 | | /* |
25 | | * Many of the procedures in this file are public only so they can be |
26 | | * called from the FunctionType 4 interpreter (zfunc4.c). |
27 | | */ |
28 | | |
29 | | static int mul_64_64_overflowcheck(int64_t abc, int64_t def, int64_t *res); |
30 | | |
31 | | /* <num1> <num2> add <sum> */ |
32 | | /* We make this into a separate procedure because */ |
33 | | /* the interpreter will almost always call it directly. */ |
34 | | int |
35 | | zop_add(i_ctx_t *i_ctx_p) |
36 | 573M | { |
37 | 573M | register os_ptr op = osp; |
38 | 573M | float result; |
39 | | |
40 | 573M | check_op(2); |
41 | 573M | switch (r_type(op)) { |
42 | 8 | default: |
43 | 8 | return_op_typecheck(op); |
44 | 54.0M | case t_real: |
45 | 54.0M | switch (r_type(op - 1)) { |
46 | 12 | default: |
47 | 12 | return_op_typecheck(op - 1); |
48 | 30.1M | case t_real: |
49 | 30.1M | result = op[-1].value.realval + op->value.realval; |
50 | 30.1M | #ifdef HAVE_ISINF |
51 | 30.1M | if (isinf(result)) |
52 | 4 | return_error(gs_error_undefinedresult); |
53 | 30.1M | #endif |
54 | 30.1M | #ifdef HAVE_ISNAN |
55 | 30.1M | if (isnan(result)) |
56 | 0 | return_error(gs_error_undefinedresult); |
57 | 30.1M | #endif |
58 | 30.1M | op[-1].value.realval = result; |
59 | 30.1M | break; |
60 | 23.8M | case t_integer: |
61 | 23.8M | make_real(op - 1, (double)op[-1].value.intval + op->value.realval); |
62 | 54.0M | } |
63 | 54.0M | break; |
64 | 519M | case t_integer: |
65 | 519M | switch (r_type(op - 1)) { |
66 | 7 | default: |
67 | 7 | return_op_typecheck(op - 1); |
68 | 60.8M | case t_real: |
69 | 60.8M | result = op[-1].value.realval + (double)op->value.intval; |
70 | 60.8M | #ifdef HAVE_ISINF |
71 | 60.8M | if (isinf(result)) |
72 | 2 | return_error(gs_error_undefinedresult); |
73 | 60.8M | #endif |
74 | 60.8M | #ifdef HAVE_ISNAN |
75 | 60.8M | if (isnan(result)) |
76 | 0 | return_error(gs_error_undefinedresult); |
77 | 60.8M | #endif |
78 | 60.8M | op[-1].value.realval = result; |
79 | 60.8M | break; |
80 | 458M | case t_integer: { |
81 | 458M | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
82 | 0 | ps_int32 int1 = (ps_int32)op[-1].value.intval; |
83 | 0 | ps_int32 int2 = (ps_int32)op->value.intval; |
84 | | |
85 | | /* Test the signs first, if they are different then integer addition can't overflow */ |
86 | 0 | if ((int1 ^ int2) < 0) { |
87 | 0 | op[-1].value.intval = (ps_int32)int1 + int2; |
88 | 0 | } else { |
89 | 0 | ps_uint32 u1, u2; |
90 | 0 | if (int1 < 0) { |
91 | | /* minimum signed int converted to unsigned, doubled, can overflow */ |
92 | 0 | u1 = (ps_uint32)(~int1) + 1; |
93 | 0 | u2 = u1 + (ps_uint32)(~int2) + 1; |
94 | |
|
95 | 0 | if (u2 < u1 || u2 > ((ps_uint32)MAX_PS_INT32 + 1)) |
96 | 0 | make_real(op - 1, (double)int1 + int2); |
97 | 0 | else |
98 | 0 | op[-1].value.intval = (ps_int32)int1 + int2; |
99 | 0 | } else { |
100 | | /* maximum signed int + maximum signed int fits into an unsigned int, so no overflow */ |
101 | 0 | u1 = int1 + int2; |
102 | |
|
103 | 0 | if (u1 > (ps_uint32)MAX_PS_INT32) |
104 | 0 | make_real(op - 1, (double)int1 + int2); |
105 | 0 | else |
106 | 0 | op[-1].value.intval = (ps_int32)int1 + int2; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | } |
110 | 458M | else { |
111 | 458M | ps_int int1 = op[-1].value.intval; |
112 | 458M | ps_int int2 = op->value.intval; |
113 | | |
114 | | /* Test the signs first, if they are different then integer addition can't overflow */ |
115 | 458M | if ((int1 ^ int2) < 0) { |
116 | 2.37k | op[-1].value.intval = int1 + int2; |
117 | 458M | } else { |
118 | 458M | ps_uint u1, u2; |
119 | 458M | if (int1 < 0) { |
120 | | /* minimum signed int converted to unsigned, doubled, can overflow */ |
121 | 109 | u1 = (ps_uint)(~int1) + 1; |
122 | 109 | u2 = u1 + (ps_uint)(~int2) + 1; |
123 | | |
124 | 109 | if (u2 < u1 || u2 > ((ps_uint)MAX_PS_INT + 1)) |
125 | 109 | make_real(op - 1, (double)int1 + int2); |
126 | 109 | else |
127 | 109 | op[-1].value.intval = (ps_int)int1 + int2; |
128 | 458M | } else { |
129 | | /* maximum signed int + maximum signed int fits into an unsigned int, so no overflow */ |
130 | 458M | u1 = int1 + int2; |
131 | | |
132 | 458M | if (u1 > (ps_uint)MAX_PS_INT) |
133 | 458M | make_real(op - 1, (double)int1 + int2); |
134 | 458M | else |
135 | 458M | op[-1].value.intval = (ps_int)int1 + int2; |
136 | 458M | } |
137 | 458M | } |
138 | 458M | } |
139 | 458M | } |
140 | 519M | } |
141 | 573M | } |
142 | 573M | return 0; |
143 | 573M | } |
144 | | int |
145 | | zadd(i_ctx_t *i_ctx_p) |
146 | 0 | { |
147 | 0 | int code = zop_add(i_ctx_p); |
148 | |
|
149 | 0 | if (code == 0) { |
150 | 0 | pop(1); |
151 | 0 | } |
152 | 0 | return code; |
153 | 0 | } |
154 | | |
155 | | /* <num1> <num2> div <real_quotient> */ |
156 | | int |
157 | | zdiv(i_ctx_t *i_ctx_p) |
158 | 37.4M | { |
159 | 37.4M | os_ptr op = osp; |
160 | 37.4M | os_ptr op1 = op - 1; |
161 | 37.4M | float result; |
162 | | |
163 | 37.4M | check_op(2); |
164 | | /* We can't use the non_int_cases macro, */ |
165 | | /* because we have to check explicitly for op == 0. */ |
166 | 37.4M | switch (r_type(op)) { |
167 | 8 | default: |
168 | 8 | return_op_typecheck(op); |
169 | 2.15M | case t_real: |
170 | 2.15M | if (op->value.realval == 0) |
171 | 7 | return_error(gs_error_undefinedresult); |
172 | 2.15M | switch (r_type(op1)) { |
173 | 7 | default: |
174 | 7 | return_op_typecheck(op1); |
175 | 2.08M | case t_real: |
176 | 2.08M | result = op1->value.realval / op->value.realval; |
177 | 2.08M | #ifdef HAVE_ISINF |
178 | 2.08M | if (isinf(result)) |
179 | 3 | return_error(gs_error_undefinedresult); |
180 | 2.08M | #endif |
181 | 2.08M | #ifdef HAVE_ISNAN |
182 | 2.08M | if (isnan(result)) |
183 | 1 | return_error(gs_error_undefinedresult); |
184 | 2.08M | #endif |
185 | 2.08M | op1->value.realval = result; |
186 | 2.08M | break; |
187 | 78.0k | case t_integer: |
188 | 78.0k | result = (double)op1->value.intval / op->value.realval; |
189 | 78.0k | #ifdef HAVE_ISINF |
190 | 78.0k | if (isinf(result)) |
191 | 0 | return_error(gs_error_undefinedresult); |
192 | 78.0k | #endif |
193 | 78.0k | #ifdef HAVE_ISNAN |
194 | 78.0k | if (isnan(result)) |
195 | 0 | return_error(gs_error_undefinedresult); |
196 | 78.0k | #endif |
197 | 2.15M | make_real(op1, result); |
198 | 2.15M | } |
199 | 2.15M | break; |
200 | 35.3M | case t_integer: |
201 | 35.3M | if (op->value.intval == 0) |
202 | 9 | return_error(gs_error_undefinedresult); |
203 | 35.3M | switch (r_type(op1)) { |
204 | 6 | default: |
205 | 6 | return_op_typecheck(op1); |
206 | 26.7M | case t_real: |
207 | 26.7M | result = op1->value.realval / (double)op->value.intval; |
208 | 26.7M | #ifdef HAVE_ISINF |
209 | 26.7M | if (isinf(result)) |
210 | 0 | return_error(gs_error_undefinedresult); |
211 | 26.7M | #endif |
212 | 26.7M | #ifdef HAVE_ISNAN |
213 | 26.7M | if (isnan(result)) |
214 | 0 | return_error(gs_error_undefinedresult); |
215 | 26.7M | #endif |
216 | 26.7M | op1->value.realval = result; |
217 | 26.7M | break; |
218 | 8.53M | case t_integer: |
219 | 8.53M | result = (double)op1->value.intval / (double)op->value.intval; |
220 | 8.53M | #ifdef HAVE_ISINF |
221 | 8.53M | if (isinf(result)) |
222 | 0 | return_error(gs_error_undefinedresult); |
223 | 8.53M | #endif |
224 | 8.53M | #ifdef HAVE_ISNAN |
225 | 8.53M | if (isnan(result)) |
226 | 0 | return_error(gs_error_undefinedresult); |
227 | 8.53M | #endif |
228 | 35.3M | make_real(op1, result); |
229 | 35.3M | } |
230 | 37.4M | } |
231 | 37.4M | pop(1); |
232 | 37.4M | return 0; |
233 | 37.4M | } |
234 | | |
235 | | /* |
236 | | To detect 64bit x 64bit multiplication overflowing, consider |
237 | | breaking the numbers down into 32bit chunks. |
238 | | |
239 | | abc = (a<<64) + (b<<32) + c |
240 | | (where a is 0 or -1, and b and c are 32bit unsigned. |
241 | | |
242 | | Similarly: |
243 | | |
244 | | def = (d<<64) + (b<<32) + f |
245 | | |
246 | | Then: |
247 | | |
248 | | abc.def = ((a<<64) + (b<<32) + c) * ((d<<64) + (e<<32) + f) |
249 | | = (a<<64).def + (d<<64).abc + (b<<32).(e<<32) + |
250 | | (b<<32).f + (e<<32).c + cf |
251 | | = (a.def + d.abc + b.e)<<64 + (b.f + e.c)<<32 + cf |
252 | | |
253 | | */ |
254 | | |
255 | | static int mul_64_64_overflowcheck(int64_t abc, int64_t def, int64_t *res) |
256 | 17.4M | { |
257 | 17.4M | uint32_t b = (abc>>32); |
258 | 17.4M | uint32_t c = (uint32_t)abc; |
259 | 17.4M | uint32_t e = (def>>32); |
260 | 17.4M | uint32_t f = (uint32_t)def; |
261 | 17.4M | uint64_t low, mid, high, bf, ec; |
262 | | |
263 | | /* Low contribution */ |
264 | 17.4M | low = (uint64_t)c * (uint64_t)f; |
265 | | /* Mid contributions */ |
266 | 17.4M | bf = (uint64_t)b * (uint64_t)f; |
267 | 17.4M | ec = (uint64_t)e * (uint64_t)c; |
268 | | /* Top contribution */ |
269 | 17.4M | high = (uint64_t)b * (uint64_t)e; |
270 | 17.4M | if (abc < 0) |
271 | 383 | high -= def; |
272 | 17.4M | if (def < 0) |
273 | 35 | high -= abc; |
274 | | /* How do we check for carries from 64bit unsigned adds? |
275 | | * x + y >= (1<<64) == x >= (1<<64) - y |
276 | | * == x > (1<<64) - y - 1 |
277 | | * if we consider just 64bits, this is: |
278 | | * x > NOT y |
279 | | */ |
280 | 17.4M | if (bf > ~ec) |
281 | 10 | high += ((uint64_t)1)<<32; |
282 | 17.4M | mid = bf + ec; |
283 | 17.4M | if (low > ~(mid<<32)) |
284 | 10 | high += 1; |
285 | 17.4M | high += (mid>>32); |
286 | 17.4M | low += (mid<<32); |
287 | | |
288 | 17.4M | *res = low; |
289 | | |
290 | 17.4M | return (int64_t)low < 0 ? high != -1 : high != 0; |
291 | 17.4M | } |
292 | | |
293 | | /* <num1> <num2> mul <product> */ |
294 | | int |
295 | | zmul(i_ctx_t *i_ctx_p) |
296 | 135M | { |
297 | 135M | os_ptr op = osp; |
298 | 135M | float result; |
299 | | |
300 | 135M | switch (r_type(op)) { |
301 | 17 | default: |
302 | 17 | return_op_typecheck(op); |
303 | 67.7M | case t_real: |
304 | 67.7M | switch (r_type(op - 1)) { |
305 | 11 | default: |
306 | 11 | return_op_typecheck(op - 1); |
307 | 66.9M | case t_real: |
308 | 66.9M | result = op[-1].value.realval * op->value.realval; |
309 | 66.9M | #ifdef HAVE_ISINF |
310 | 66.9M | if (isinf(result)) |
311 | 27 | return_error(gs_error_undefinedresult); |
312 | 66.9M | #endif |
313 | 66.9M | #ifdef HAVE_ISNAN |
314 | 66.9M | if (isnan(result)) |
315 | 0 | return_error(gs_error_undefinedresult); |
316 | 66.9M | #endif |
317 | 66.9M | op[-1].value.realval = result; |
318 | 66.9M | break; |
319 | 854k | case t_integer: |
320 | 854k | result = (double)op[-1].value.intval * op->value.realval; |
321 | 854k | make_real(op - 1, result); |
322 | 67.7M | } |
323 | 67.7M | break; |
324 | 67.7M | case t_integer: |
325 | 67.3M | switch (r_type(op - 1)) { |
326 | 9 | default: |
327 | 9 | return_op_typecheck(op - 1); |
328 | 49.8M | case t_real: |
329 | 49.8M | result = op[-1].value.realval * (double)op->value.intval; |
330 | 49.8M | #ifdef HAVE_ISINF |
331 | 49.8M | if (isinf(result)) |
332 | 3 | return_error(gs_error_undefinedresult); |
333 | 49.8M | #endif |
334 | 49.8M | #ifdef HAVE_ISNAN |
335 | 49.8M | if (isnan(result)) |
336 | 0 | return_error(gs_error_undefinedresult); |
337 | 49.8M | #endif |
338 | 49.8M | op[-1].value.realval = result; |
339 | 49.8M | break; |
340 | 17.4M | case t_integer: { |
341 | 17.4M | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
342 | 0 | double ab = (double)op[-1].value.intval * op->value.intval; |
343 | 0 | if (ab > (double)MAX_PS_INT32) /* (double)0x7fffffff */ |
344 | 0 | make_real(op - 1, ab); |
345 | 0 | else if (ab < (double)MIN_PS_INT32) /* (double)(int)0x80000000 */ |
346 | 0 | make_real(op - 1, ab); |
347 | 0 | else |
348 | 0 | op[-1].value.intval = (ps_int)ab; |
349 | 0 | } |
350 | 17.4M | else { |
351 | 17.4M | int64_t result; |
352 | 17.4M | if (mul_64_64_overflowcheck(op[-1].value.intval, op->value.intval, &result)) { |
353 | 1 | double ab = (double)op[-1].value.intval * op->value.intval; |
354 | 1 | make_real(op - 1, ab); |
355 | 17.4M | } else { |
356 | 17.4M | op[-1].value.intval = result; |
357 | 17.4M | } |
358 | 17.4M | } |
359 | 17.4M | } |
360 | 67.3M | } |
361 | 135M | } |
362 | 135M | pop(1); |
363 | 135M | return 0; |
364 | 135M | } |
365 | | |
366 | | /* <num1> <num2> sub <difference> */ |
367 | | /* We make this into a separate procedure because */ |
368 | | /* the interpreter will almost always call it directly. */ |
369 | | int |
370 | | zop_sub(i_ctx_t *i_ctx_p) |
371 | 96.6M | { |
372 | 96.6M | register os_ptr op = osp; |
373 | | |
374 | 96.6M | check_op(2); |
375 | 96.6M | switch (r_type(op)) { |
376 | 72 | default: |
377 | 72 | return_op_typecheck(op); |
378 | 26.3M | case t_real: |
379 | 26.3M | switch (r_type(op - 1)) { |
380 | 14 | default: |
381 | 14 | return_op_typecheck(op - 1); |
382 | 378k | case t_real: |
383 | 378k | op[-1].value.realval -= op->value.realval; |
384 | 378k | break; |
385 | 25.9M | case t_integer: |
386 | 25.9M | make_real(op - 1, (double)op[-1].value.intval - op->value.realval); |
387 | 26.3M | } |
388 | 26.3M | break; |
389 | 70.3M | case t_integer: |
390 | 70.3M | switch (r_type(op - 1)) { |
391 | 6 | default: |
392 | 6 | return_op_typecheck(op - 1); |
393 | 67.4k | case t_real: |
394 | 67.4k | op[-1].value.realval -= (double)op->value.intval; |
395 | 67.4k | break; |
396 | 70.2M | case t_integer: { |
397 | 70.2M | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
398 | 0 | ps_int32 int1 = (ps_int32)op[-1].value.intval; |
399 | 0 | ps_int32 int2 = (ps_int32)op->value.intval; |
400 | | |
401 | | /* Test the signs first, if they are the same then integer subtraction can't overflow */ |
402 | 0 | if ((int1 ^ int2) >= 0) { |
403 | 0 | op[-1].value.intval = int1 - int2; |
404 | 0 | } else { |
405 | 0 | ps_uint32 u1, u2; |
406 | |
|
407 | 0 | if (int1 < 0) { |
408 | | /* -ve minus +ve, convert -ve to +ve and add as unsigned, defined behaviour if overflow (wraps round) */ |
409 | 0 | u1 = (ps_uint32)(~int1) + 1; |
410 | 0 | u2 = u1 + int2; |
411 | | /* If adding 2 positive values produced a smaller value, then the addition overflowed. |
412 | | * If the result is larger than the max signed int (+1 for -ve) then subtraction will overflow |
413 | | */ |
414 | 0 | if (u2 < u1 || u2 > ((ps_uint32)MAX_PS_INT32 + 1)) |
415 | 0 | make_real(op - 1, (float)int1 - op->value.intval); |
416 | 0 | else |
417 | 0 | op[-1].value.intval = int1 - int2; |
418 | 0 | } else { |
419 | | /* +ve minus -ve = +ve plus +ve, can overflow a *signed* int, but not an unsigned int */ |
420 | 0 | u1 = int1 + ((ps_uint32)(~int2) + 1); |
421 | 0 | if (u1 > (ps_uint)MAX_PS_INT32) |
422 | 0 | make_real(op - 1, (float)int1 - op->value.intval); |
423 | 0 | else |
424 | 0 | op[-1].value.intval = int1 - int2; |
425 | 0 | } |
426 | 0 | } |
427 | 0 | } |
428 | 70.2M | else { |
429 | 70.2M | ps_int int1 = op[-1].value.intval; |
430 | 70.2M | ps_int int2 = op->value.intval; |
431 | | |
432 | | /* Test the signs first, if they are the same then integer subtraction can't overflow */ |
433 | 70.2M | if ((int1 ^ int2) >= 0) { |
434 | 70.2M | op[-1].value.intval = int1 - int2; |
435 | 70.2M | } else { |
436 | 9.13k | ps_uint u1, u2; |
437 | | |
438 | 9.13k | if (int1 < 0) { |
439 | | /* -ve minus +ve, convert -ve to +ve and add as unsigned, defined behaviour if overflow (wraps round) */ |
440 | 7.40k | u1 = (ps_uint)(~int1) + 1; |
441 | 7.40k | u2 = u1 + int2; |
442 | | /* If adding 2 positive values produced a smaller value, then the addition overflowed. |
443 | | * If the result is larger than the max signed int (+1 for -ve) then subtraction will overflow |
444 | | */ |
445 | 7.40k | if (u2 < u1 || u2 > ((ps_uint)MAX_PS_INT + 1)) |
446 | 7.40k | make_real(op - 1, (float)int1 - op->value.intval); |
447 | 7.40k | else |
448 | 7.40k | op[-1].value.intval = int1 - int2; |
449 | 7.40k | } else { |
450 | | /* +ve minus -ve = +ve plus +ve, can overflow a *signed* int, but not an unsigned int */ |
451 | 1.73k | u1 = int1 + ((ps_uint)(~int2) + 1); |
452 | 1.73k | if (u1 > (ps_uint)MAX_PS_INT) |
453 | 1.73k | make_real(op - 1, (float)int1 - op->value.intval); |
454 | 1.73k | else |
455 | 1.73k | op[-1].value.intval = int1 - int2; |
456 | 1.73k | } |
457 | 9.13k | } |
458 | 70.2M | } |
459 | 70.2M | } |
460 | 70.3M | } |
461 | 96.6M | } |
462 | 96.6M | return 0; |
463 | 96.6M | } |
464 | | int |
465 | | zsub(i_ctx_t *i_ctx_p) |
466 | 0 | { |
467 | 0 | int code = zop_sub(i_ctx_p); |
468 | |
|
469 | 0 | if (code == 0) { |
470 | 0 | pop(1); |
471 | 0 | } |
472 | 0 | return code; |
473 | 0 | } |
474 | | |
475 | | /* <num1> <num2> idiv <int_quotient> */ |
476 | | int |
477 | | zidiv(i_ctx_t *i_ctx_p) |
478 | 42.2M | { |
479 | 42.2M | os_ptr op = osp; |
480 | | |
481 | 42.2M | check_op(2); |
482 | 42.2M | check_type(*op, t_integer); |
483 | 42.2M | check_type(op[-1], t_integer); |
484 | 42.2M | if (sizeof(ps_int) && gs_currentcpsimode(imemory)) { |
485 | 0 | int tmpval; |
486 | 0 | if ((op->value.intval == 0) || (op[-1].value.intval == (ps_int)MIN_PS_INT32 && op->value.intval == -1)) { |
487 | | /* Anomalous boundary case: -MININT / -1, fail. */ |
488 | 0 | return_error(gs_error_undefinedresult); |
489 | 0 | } |
490 | 0 | tmpval = (int)op[-1].value.intval / op->value.intval; |
491 | 0 | op[-1].value.intval = (int64_t)tmpval; |
492 | 0 | } |
493 | 42.2M | else { |
494 | 42.2M | if ((op->value.intval == 0) || (op[-1].value.intval == MIN_PS_INT && op->value.intval == -1)) { |
495 | | /* Anomalous boundary case: -MININT / -1, fail. */ |
496 | 3 | return_error(gs_error_undefinedresult); |
497 | 3 | } |
498 | 42.2M | op[-1].value.intval /= op->value.intval; |
499 | 42.2M | } |
500 | 42.2M | pop(1); |
501 | 42.2M | return 0; |
502 | 42.2M | } |
503 | | |
504 | | /* <int1> <int2> mod <remainder> */ |
505 | | int |
506 | | zmod(i_ctx_t *i_ctx_p) |
507 | 8.09M | { |
508 | 8.09M | os_ptr op = osp; |
509 | | |
510 | 8.09M | check_op(2); |
511 | 8.09M | check_type(*op, t_integer); |
512 | 8.09M | check_type(op[-1], t_integer); |
513 | 8.09M | if (op->value.intval == 0 || op[-1].value.intval == MIN_PS_INT) |
514 | 8 | return_error(gs_error_undefinedresult); |
515 | 8.09M | op[-1].value.intval %= op->value.intval; |
516 | 8.09M | pop(1); |
517 | 8.09M | return 0; |
518 | 8.09M | } |
519 | | |
520 | | /* <num1> neg <num2> */ |
521 | | int |
522 | | zneg(i_ctx_t *i_ctx_p) |
523 | 5.67M | { |
524 | 5.67M | os_ptr op = osp; |
525 | | |
526 | 5.67M | check_op(1); |
527 | 5.67M | switch (r_type(op)) { |
528 | 6 | default: |
529 | 6 | return_op_typecheck(op); |
530 | 2.24M | case t_real: |
531 | 2.24M | op->value.realval = -op->value.realval; |
532 | 2.24M | break; |
533 | 3.43M | case t_integer: |
534 | 3.43M | if (sizeof(ps_int) != 32 && gs_currentcpsimode(imemory)) { |
535 | 0 | if (((unsigned int)op->value.intval) == MIN_PS_INT32) |
536 | 0 | make_real(op, -(float)(ps_uint32)MIN_PS_INT32); |
537 | 0 | else |
538 | 0 | op->value.intval = -op->value.intval; |
539 | 0 | } |
540 | 3.43M | else { |
541 | 3.43M | if (op->value.intval == MIN_PS_INT) |
542 | 3.43M | make_real(op, -(float)MIN_PS_INT); |
543 | 3.43M | else |
544 | 3.43M | op->value.intval = -op->value.intval; |
545 | 3.43M | } |
546 | 5.67M | } |
547 | 5.67M | return 0; |
548 | 5.67M | } |
549 | | |
550 | | /* <num1> abs <num2> */ |
551 | | int |
552 | | zabs(i_ctx_t *i_ctx_p) |
553 | 11.1M | { |
554 | 11.1M | os_ptr op = osp; |
555 | | |
556 | 11.1M | check_op(1); |
557 | 11.1M | switch (r_type(op)) { |
558 | 56 | default: |
559 | 56 | return_op_typecheck(op); |
560 | 3.18M | case t_real: |
561 | 3.18M | if (op->value.realval >= 0) |
562 | 1.75M | return 0; |
563 | 1.43M | break; |
564 | 7.93M | case t_integer: |
565 | 7.93M | if (op->value.intval >= 0) |
566 | 7.93M | return 0; |
567 | 103 | break; |
568 | 11.1M | } |
569 | 1.43M | return zneg(i_ctx_p); |
570 | 11.1M | } |
571 | | |
572 | | /* <num1> ceiling <num2> */ |
573 | | int |
574 | | zceiling(i_ctx_t *i_ctx_p) |
575 | 185 | { |
576 | 185 | os_ptr op = osp; |
577 | | |
578 | 185 | check_op(1); |
579 | 174 | switch (r_type(op)) { |
580 | 9 | default: |
581 | 9 | return_op_typecheck(op); |
582 | 100 | case t_real: |
583 | 100 | op->value.realval = ceil(op->value.realval); |
584 | 165 | case t_integer:; |
585 | 174 | } |
586 | 165 | return 0; |
587 | 174 | } |
588 | | |
589 | | /* <num1> floor <num2> */ |
590 | | int |
591 | | zfloor(i_ctx_t *i_ctx_p) |
592 | 228 | { |
593 | 228 | os_ptr op = osp; |
594 | | |
595 | 228 | check_op(1); |
596 | 220 | switch (r_type(op)) { |
597 | 6 | default: |
598 | 6 | return_op_typecheck(op); |
599 | 103 | case t_real: |
600 | 103 | op->value.realval = floor(op->value.realval); |
601 | 214 | case t_integer:; |
602 | 220 | } |
603 | 214 | return 0; |
604 | 220 | } |
605 | | |
606 | | /* <num1> round <num2> */ |
607 | | int |
608 | | zround(i_ctx_t *i_ctx_p) |
609 | 4.14k | { |
610 | 4.14k | os_ptr op = osp; |
611 | | |
612 | 4.14k | check_op(1); |
613 | 4.13k | switch (r_type(op)) { |
614 | 7 | default: |
615 | 7 | return_op_typecheck(op); |
616 | 755 | case t_real: |
617 | 755 | op->value.realval = floor(op->value.realval + 0.5); |
618 | 4.12k | case t_integer:; |
619 | 4.13k | } |
620 | 4.12k | return 0; |
621 | 4.13k | } |
622 | | |
623 | | /* <num1> truncate <num2> */ |
624 | | int |
625 | | ztruncate(i_ctx_t *i_ctx_p) |
626 | 37.8k | { |
627 | 37.8k | os_ptr op = osp; |
628 | | |
629 | 37.8k | check_op(1); |
630 | 37.8k | switch (r_type(op)) { |
631 | 8 | default: |
632 | 8 | return_op_typecheck(op); |
633 | 1.48k | case t_real: |
634 | 1.48k | op->value.realval = |
635 | 1.48k | (op->value.realval < 0.0 ? |
636 | 15 | ceil(op->value.realval) : |
637 | 1.48k | floor(op->value.realval)); |
638 | 37.8k | case t_integer:; |
639 | 37.8k | } |
640 | 37.8k | return 0; |
641 | 37.8k | } |
642 | | |
643 | | /* Non-standard operators */ |
644 | | |
645 | | /* <int1> <int2> .bitadd <sum> */ |
646 | | static int |
647 | | zbitadd(i_ctx_t *i_ctx_p) |
648 | 0 | { |
649 | 0 | os_ptr op = osp; |
650 | |
|
651 | 0 | check_op(2); |
652 | 0 | check_type(*op, t_integer); |
653 | 0 | check_type(op[-1], t_integer); |
654 | 0 | op[-1].value.intval += op->value.intval; |
655 | 0 | pop(1); |
656 | 0 | return 0; |
657 | 0 | } |
658 | | |
659 | | /* ------ Initialization table ------ */ |
660 | | |
661 | | const op_def zarith_op_defs[] = |
662 | | { |
663 | | {"1abs", zabs}, |
664 | | {"2add", zadd}, |
665 | | {"2.bitadd", zbitadd}, |
666 | | {"1ceiling", zceiling}, |
667 | | {"2div", zdiv}, |
668 | | {"2idiv", zidiv}, |
669 | | {"1floor", zfloor}, |
670 | | {"2mod", zmod}, |
671 | | {"2mul", zmul}, |
672 | | {"1neg", zneg}, |
673 | | {"1round", zround}, |
674 | | {"2sub", zsub}, |
675 | | {"1truncate", ztruncate}, |
676 | | op_def_end(0) |
677 | | }; |