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