Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zmath.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Mathematical operators */
18
#include "math_.h"
19
#include "ghost.h"
20
#include "gxfarith.h"
21
#include "oper.h"
22
#include "store.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
/*
30
 * Define the current state of random number generator for operators.  We
31
 * have to implement this ourselves because the Unix rand doesn't provide
32
 * anything equivalent to rrand.  Note that the value always lies in the
33
 * range [0..0x7ffffffe], even if longs are longer than 32 bits.
34
 *
35
 * The state must be public so that context switching can save and
36
 * restore it.  (Even though the Red Book doesn't mention this,
37
 * we verified with Adobe that this is the case.)
38
 */
39
3.95M
#define zrand_state (i_ctx_p->rand_state)
40
41
/* Initialize the random number generator. */
42
const long rand_state_initial = 1;
43
44
/****** NOTE: none of these operators currently ******/
45
/****** check for floating over- or underflow.  ******/
46
47
/* <num> sqrt <real> */
48
int
49
zsqrt(i_ctx_t *i_ctx_p)
50
621k
{
51
621k
    os_ptr op = osp;
52
621k
    double num;
53
621k
    int code = real_param(op, &num);
54
55
621k
    if (code < 0)
56
11
        return code;
57
621k
    if (num < 0.0)
58
7
        return_error(gs_error_rangecheck);
59
621k
    make_real(op, sqrt(num));
60
621k
    return 0;
61
621k
}
62
63
/* <num> arccos <real> */
64
static int
65
zarccos(i_ctx_t *i_ctx_p)
66
0
{
67
0
    os_ptr op = osp;
68
0
    double num, result;
69
0
    int code = real_param(op, &num);
70
71
0
    if (code < 0)
72
0
        return code;
73
0
    result = acos(num) * radians_to_degrees;
74
0
    make_real(op, result);
75
0
    return 0;
76
0
}
77
78
/* <num> arcsin <real> */
79
static int
80
zarcsin(i_ctx_t *i_ctx_p)
81
0
{
82
0
    os_ptr op = osp;
83
0
    double num, result;
84
0
    int code = real_param(op, &num);
85
86
0
    if (code < 0)
87
0
        return code;
88
0
    result = asin(num) * radians_to_degrees;
89
0
    make_real(op, result);
90
0
    return 0;
91
0
}
92
93
/* <num> <denom> atan <real> */
94
int
95
zatan(i_ctx_t *i_ctx_p)
96
1.55k
{
97
1.55k
    os_ptr op = osp;
98
1.55k
    double args[2];
99
1.55k
    double result;
100
1.55k
    int code = num_params(op, 2, args);
101
102
1.55k
    if (code < 0)
103
14
        return code;
104
1.54k
    code = gs_atan2_degrees(args[0], args[1], &result);
105
1.54k
    if (code < 0)
106
1
        return code;
107
1.54k
    make_real(op - 1, result);
108
1.54k
    pop(1);
109
1.54k
    return 0;
110
1.54k
}
111
112
/* <num> cos <real> */
113
int
114
zcos(i_ctx_t *i_ctx_p)
115
32.1M
{
116
32.1M
    os_ptr op = osp;
117
32.1M
    double angle;
118
32.1M
    int code = real_param(op, &angle);
119
120
32.1M
    if (code < 0)
121
7
        return code;
122
32.1M
    make_real(op, gs_cos_degrees(angle));
123
32.1M
    return 0;
124
32.1M
}
125
126
/* <num> sin <real> */
127
int
128
zsin(i_ctx_t *i_ctx_p)
129
55.1k
{
130
55.1k
    os_ptr op = osp;
131
55.1k
    double angle;
132
55.1k
    int code = real_param(op, &angle);
133
134
55.1k
    if (code < 0)
135
19
        return code;
136
55.1k
    make_real(op, gs_sin_degrees(angle));
137
55.1k
    return 0;
138
55.1k
}
139
140
/* <base> <exponent> exp <real> */
141
int
142
zexp(i_ctx_t *i_ctx_p)
143
6.79M
{
144
6.79M
    os_ptr op = osp;
145
6.79M
    double args[2];
146
6.79M
    double result;
147
6.79M
    double ipart;
148
6.79M
    int code = num_params(op, 2, args);
149
150
6.79M
    if (code < 0)
151
8
        return code;
152
6.79M
    if (args[0] == 0.0 && args[1] < 0)
153
0
        return_error(gs_error_undefinedresult);
154
6.79M
    if (args[0] < 0.0 && modf(args[1], &ipart) != 0.0)
155
0
        return_error(gs_error_undefinedresult);
156
6.79M
    if (args[0] == 0.0 && args[1] == 0.0)
157
2
        result = 1.0;    /* match Adobe; can't rely on C library */
158
6.79M
    else
159
6.79M
        result = pow(args[0], args[1]);
160
6.79M
#ifdef HAVE_ISINF
161
6.79M
    if (isinf((op - 1)->value.realval))
162
1
        return_error(gs_error_undefinedresult);
163
6.79M
#endif
164
6.79M
    make_real(op - 1, result);
165
6.79M
    pop(1);
166
6.79M
    return 0;
167
6.79M
}
168
169
/* <posnum> ln <real> */
170
int
171
zln(i_ctx_t *i_ctx_p)
172
53
{
173
53
    os_ptr op = osp;
174
53
    double num;
175
53
    int code = real_param(op, &num);
176
177
53
    if (code < 0)
178
13
        return code;
179
40
    if (num <= 0.0)
180
3
        return_error(gs_error_rangecheck);
181
37
    make_real(op, log(num));
182
37
    return 0;
183
40
}
184
185
/* <posnum> log <real> */
186
int
187
zlog(i_ctx_t *i_ctx_p)
188
19
{
189
19
    os_ptr op = osp;
190
19
    double num;
191
19
    int code = real_param(op, &num);
192
193
19
    if (code < 0)
194
11
        return code;
195
8
    if (num <= 0.0)
196
2
        return_error(gs_error_rangecheck);
197
6
    make_real(op, log10(num));
198
6
    return 0;
199
8
}
200
201
/* - rand <int> */
202
static int
203
zrand(i_ctx_t *i_ctx_p)
204
976k
{
205
976k
    os_ptr op = osp;
206
207
        /*
208
         * We use an algorithm from CACM 31 no. 10, pp. 1192-1201,
209
         * October 1988.  According to a posting by Ed Taft on
210
         * comp.lang.postscript, Level 2 (Adobe) PostScript interpreters
211
         * use this algorithm too:
212
         *      x[n+1] = (16807 * x[n]) mod (2^31 - 1)
213
         */
214
976k
#define A 16807
215
976k
#define M 0x7fffffff
216
1.95M
#define Q 127773    /* M / A */
217
976k
#define R 2836      /* M % A */
218
976k
    zrand_state = A * (zrand_state % Q) - R * (zrand_state / Q);
219
    /* Note that zrand_state cannot be 0 here. */
220
976k
    if (zrand_state <= 0)
221
12.5k
        zrand_state += M;
222
976k
#undef A
223
976k
#undef M
224
976k
#undef Q
225
976k
#undef R
226
976k
    push(1);
227
976k
    make_int(op, zrand_state);
228
976k
    return 0;
229
976k
}
230
231
/* <int> srand - */
232
static int
233
zsrand(i_ctx_t *i_ctx_p)
234
38.7k
{
235
38.7k
    os_ptr op = osp;
236
38.7k
    int state;
237
238
38.7k
    check_type(*op, t_integer);
239
38.7k
    state = op->value.intval;
240
    /*
241
     * The following somewhat bizarre adjustments are according to
242
     * public information from Adobe describing their implementation.
243
     */
244
38.7k
    if (state < 1)
245
2.73k
        state = -(state % 0x7ffffffe) + 1;
246
35.9k
    else if (state > 0x7ffffffe)
247
0
        state = 0x7ffffffe;
248
38.7k
    zrand_state = state;
249
38.7k
    pop(1);
250
38.7k
    return 0;
251
38.7k
}
252
253
/* - rrand <int> */
254
static int
255
zrrand(i_ctx_t *i_ctx_p)
256
22
{
257
22
    os_ptr op = osp;
258
259
22
    push(1);
260
22
    make_int(op, zrand_state);
261
22
    return 0;
262
22
}
263
264
/* ------ Initialization procedure ------ */
265
266
const op_def zmath_op_defs[] =
267
{
268
    {"1arccos", zarccos}, /* extension */
269
    {"1arcsin", zarcsin}, /* extension */
270
    {"2atan", zatan},
271
    {"1cos", zcos},
272
    {"2exp", zexp},
273
    {"1ln", zln},
274
    {"1log", zlog},
275
    {"0rand", zrand},
276
    {"0rrand", zrrand},
277
    {"1sin", zsin},
278
    {"1sqrt", zsqrt},
279
    {"1srand", zsrand},
280
    op_def_end(0)
281
};