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