Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};