comparison src/floatfns.c @ 2094:c77607f8e32d

(FLOAT_CHECK_ERRNO): Define unless NO_FLOAT_CHECK_ERRNO. Changes from Lucid: (HAVE_MATHERR, FLOAT_CHECK_ERRNO, FLOAT_CATCH_SIGILL): New parm macros. (FLOAT_CHECK_DOMAIN, HAVE_RINT): New parm macros. (HAVE_INVERSE_HYPERBOLIC, HAVE_CBRT): New parm macros. [!HAVE_RINT]: Define rint as macro. (IN_FLOAT): Major rewrite; several alternate versions. (IN_FLOAT2): New macro. (arith_error, range_error, domain_error, domain_error2): New macros. (Facos, Fasin, Fatan, Fcos, Fsin, Ftan, Fexp, Fexpt, Flog): Changed. (Flog10, Fsqrt, Fabs, Ffloat, Flogb): Changed. (Ffloor, Fceiling, Fround, Ftruncate): Changed. (Fcube_root): Renamed from Fcbrt. (matherr): New function. (float_error): Only if FLOAT_CATCH_SIGILL.
author Richard M. Stallman <rms@gnu.org>
date Wed, 10 Mar 1993 05:33:40 +0000
parents 699ae3079c09
children 4077ef8ad483
comparison
equal deleted inserted replaced
2093:ce8bad247b1a 2094:c77607f8e32d
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to 17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19 19
20 20
21 /* ANSI C requires only these float functions:
22 acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
23 frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
24
25 Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
26 Define HAVE_CBRT if you have cbrt.
27 Define HAVE_RINT if you have rint.
28 If you don't define these, then the appropriate routines will be simulated.
29
30 Define HAVE_MATHERR if on a system supporting the SysV matherr callback.
31 (This should happen automatically.)
32
33 Define FLOAT_CHECK_ERRNO if the float library routines set errno.
34 This has no effect if HAVE_MATHERR is defined.
35
36 Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
37 (What systems actually do this? Please let us know.)
38
39 Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
40 either setting errno, or signalling SIGFPE/SIGILL. Otherwise, domain and
41 range checking will happen before calling the float routines. This has
42 no effect if HAVE_MATHERR is defined (since matherr will be called when
43 a domain error occurs.)
44 */
45
21 #include <signal.h> 46 #include <signal.h>
22 47
23 #include "config.h" 48 #include "config.h"
24 #include "lisp.h" 49 #include "lisp.h"
25 #include "syssignal.h" 50 #include "syssignal.h"
27 Lisp_Object Qarith_error; 52 Lisp_Object Qarith_error;
28 53
29 #ifdef LISP_FLOAT_TYPE 54 #ifdef LISP_FLOAT_TYPE
30 55
31 #include <math.h> 56 #include <math.h>
32 #include <errno.h> 57
58 #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
59 /* If those are defined, then this is probably a `matherr' machine. */
60 # ifndef HAVE_MATHERR
61 # define HAVE_MATHERR
62 # endif
63 #endif
64
65 #ifdef HAVE_MATHERR
66 # ifdef FLOAT_CHECK_ERRNO
67 # undef FLOAT_CHECK_ERRNO
68 # endif
69 # ifdef FLOAT_CHECK_DOMAIN
70 # undef FLOAT_CHECK_DOMAIN
71 # endif
72 #endif
73
74 #ifndef NO_FLOAT_CHECK_ERRNO
75 #define FLOAT_CHECK_ERRNO
76 #endif
77
78 #ifdef FLOAT_CHECK_ERRNO
79 # include <errno.h>
33 80
34 extern int errno; 81 extern int errno;
82 #endif
35 83
36 /* Avoid traps on VMS from sinh and cosh. 84 /* Avoid traps on VMS from sinh and cosh.
37 All the other functions set errno instead. */ 85 All the other functions set errno instead. */
38 86
39 #ifdef VMS 87 #ifdef VMS
41 #undef sinh 89 #undef sinh
42 #define cosh(x) ((exp(x)+exp(-x))*0.5) 90 #define cosh(x) ((exp(x)+exp(-x))*0.5)
43 #define sinh(x) ((exp(x)-exp(-x))*0.5) 91 #define sinh(x) ((exp(x)-exp(-x))*0.5)
44 #endif /* VMS */ 92 #endif /* VMS */
45 93
94 #ifndef HAVE_RINT
95 #define rint(x) (floor((x)+0.5))
96 #endif
97
46 static SIGTYPE float_error (); 98 static SIGTYPE float_error ();
47 99
48 /* Nonzero while executing in floating point. 100 /* Nonzero while executing in floating point.
49 This tells float_error what to do. */ 101 This tells float_error what to do. */
50 102
51 static int in_float; 103 static int in_float;
52 104
53 /* If an argument is out of range for a mathematical function, 105 /* If an argument is out of range for a mathematical function,
54 here is the actual argument value to use in the error message. */ 106 here is the actual argument value to use in the error message. */
55 107
56 static Lisp_Object float_error_arg; 108 static Lisp_Object float_error_arg, float_error_arg2;
109
110 static char *float_error_fn_name;
57 111
58 /* Evaluate the floating point expression D, recording NUM 112 /* Evaluate the floating point expression D, recording NUM
59 as the original argument for error messages. 113 as the original argument for error messages.
60 D is normally an assignment expression. 114 D is normally an assignment expression.
61 Handle errors which may result in signals or may set errno. 115 Handle errors which may result in signals or may set errno.
62 116
63 Note that float_error may be declared to return void, so you can't 117 Note that float_error may be declared to return void, so you can't
64 just cast the zero after the colon to (SIGTYPE) to make the types 118 just cast the zero after the colon to (SIGTYPE) to make the types
65 check properly. */ 119 check properly. */
66 120
67 #define IN_FLOAT(D, NUM) \ 121 #ifdef FLOAT_CHECK_ERRNO
68 (in_float = 1, errno = 0, float_error_arg = NUM, (D), \ 122 #define IN_FLOAT(d, name, num) \
69 (errno == ERANGE || errno == EDOM ? (float_error (),0) : 0), \ 123 do { \
70 in_float = 0) 124 float_error_arg = num; \
125 float_error_fn_name = name; \
126 in_float = 1; errno = 0; (d); in_float = 0; \
127 switch (errno) { \
128 case 0: break; \
129 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
130 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
131 default: arith_error (float_error_fn_name, float_error_arg); \
132 } \
133 } while (0)
134 #define IN_FLOAT2(d, name, num, num2) \
135 do { \
136 float_error_arg = num; \
137 float_error_arg2 = num2; \
138 float_error_fn_name = name; \
139 in_float = 1; errno = 0; (d); in_float = 0; \
140 switch (errno) { \
141 case 0: break; \
142 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
143 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
144 default: arith_error (float_error_fn_name, float_error_arg); \
145 } \
146 } while (0)
147 #else
148 #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
149 #endif
150
151 #define arith_error(op,arg) \
152 Fsignal (Qarith_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
153 #define range_error(op,arg) \
154 Fsignal (Qrange_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
155 #define domain_error(op,arg) \
156 Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
157 #define domain_error2(op,a1,a2) \
158 Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((a1), Fcons ((a2), Qnil))))
71 159
72 /* Extract a Lisp number as a `double', or signal an error. */ 160 /* Extract a Lisp number as a `double', or signal an error. */
73 161
74 double 162 double
75 extract_float (num) 163 extract_float (num)
84 172
85 /* Trig functions. */ 173 /* Trig functions. */
86 174
87 DEFUN ("acos", Facos, Sacos, 1, 1, 0, 175 DEFUN ("acos", Facos, Sacos, 1, 1, 0,
88 "Return the inverse cosine of ARG.") 176 "Return the inverse cosine of ARG.")
89 (num) 177 (arg)
90 register Lisp_Object num; 178 register Lisp_Object arg;
91 { 179 {
92 double d = extract_float (num); 180 double d = extract_float (arg);
93 IN_FLOAT (d = acos (d), num); 181 #ifdef FLOAT_CHECK_DOMAIN
182 if (d > 1.0 || d < -1.0)
183 domain_error ("acos", arg);
184 #endif
185 IN_FLOAT (d = acos (d), "acos", arg);
94 return make_float (d); 186 return make_float (d);
95 } 187 }
96 188
97 DEFUN ("asin", Fasin, Sasin, 1, 1, 0, 189 DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
98 "Return the inverse sine of ARG.") 190 "Return the inverse sine of ARG.")
99 (num) 191 (arg)
100 register Lisp_Object num; 192 register Lisp_Object arg;
101 { 193 {
102 double d = extract_float (num); 194 double d = extract_float (arg);
103 IN_FLOAT (d = asin (d), num); 195 #ifdef FLOAT_CHECK_DOMAIN
196 if (d > 1.0 || d < -1.0)
197 domain_error ("asin", arg);
198 #endif
199 IN_FLOAT (d = asin (d), "asin", arg);
104 return make_float (d); 200 return make_float (d);
105 } 201 }
106 202
107 DEFUN ("atan", Fatan, Satan, 1, 1, 0, 203 DEFUN ("atan", Fatan, Satan, 1, 1, 0,
108 "Return the inverse tangent of ARG.") 204 "Return the inverse tangent of ARG.")
109 (num) 205 (arg)
110 register Lisp_Object num; 206 register Lisp_Object arg;
111 { 207 {
112 double d = extract_float (num); 208 double d = extract_float (arg);
113 IN_FLOAT (d = atan (d), num); 209 IN_FLOAT (d = atan (d), "atan", arg);
114 return make_float (d); 210 return make_float (d);
115 } 211 }
116 212
117 DEFUN ("cos", Fcos, Scos, 1, 1, 0, 213 DEFUN ("cos", Fcos, Scos, 1, 1, 0,
118 "Return the cosine of ARG.") 214 "Return the cosine of ARG.")
119 (num) 215 (arg)
120 register Lisp_Object num; 216 register Lisp_Object arg;
121 { 217 {
122 double d = extract_float (num); 218 double d = extract_float (arg);
123 IN_FLOAT (d = cos (d), num); 219 IN_FLOAT (d = cos (d), "cos", arg);
124 return make_float (d); 220 return make_float (d);
125 } 221 }
126 222
127 DEFUN ("sin", Fsin, Ssin, 1, 1, 0, 223 DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
128 "Return the sine of ARG.") 224 "Return the sine of ARG.")
129 (num) 225 (arg)
130 register Lisp_Object num; 226 register Lisp_Object arg;
131 { 227 {
132 double d = extract_float (num); 228 double d = extract_float (arg);
133 IN_FLOAT (d = sin (d), num); 229 IN_FLOAT (d = sin (d), "sin", arg);
134 return make_float (d); 230 return make_float (d);
135 } 231 }
136 232
137 DEFUN ("tan", Ftan, Stan, 1, 1, 0, 233 DEFUN ("tan", Ftan, Stan, 1, 1, 0,
138 "Return the tangent of ARG.") 234 "Return the tangent of ARG.")
139 (num) 235 (arg)
140 register Lisp_Object num; 236 register Lisp_Object arg;
141 { 237 {
142 double d = extract_float (num); 238 double d = extract_float (arg);
143 IN_FLOAT (d = tan (d), num); 239 double c = cos (d);
240 #ifdef FLOAT_CHECK_DOMAIN
241 if (c == 0.0)
242 domain_error ("tan", arg);
243 #endif
244 IN_FLOAT (d = sin (d) / c, "tan", arg);
144 return make_float (d); 245 return make_float (d);
145 } 246 }
146 247
147 #if 0 /* Leave these out unless we find there's a reason for them. */ 248 #if 0 /* Leave these out unless we find there's a reason for them. */
148 249
149 DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0, 250 DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
150 "Return the bessel function j0 of ARG.") 251 "Return the bessel function j0 of ARG.")
151 (num) 252 (arg)
152 register Lisp_Object num; 253 register Lisp_Object arg;
153 { 254 {
154 double d = extract_float (num); 255 double d = extract_float (arg);
155 IN_FLOAT (d = j0 (d), num); 256 IN_FLOAT (d = j0 (d), "bessel-j0", arg);
156 return make_float (d); 257 return make_float (d);
157 } 258 }
158 259
159 DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0, 260 DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
160 "Return the bessel function j1 of ARG.") 261 "Return the bessel function j1 of ARG.")
161 (num) 262 (arg)
162 register Lisp_Object num; 263 register Lisp_Object arg;
163 { 264 {
164 double d = extract_float (num); 265 double d = extract_float (arg);
165 IN_FLOAT (d = j1 (d), num); 266 IN_FLOAT (d = j1 (d), "bessel-j1", arg);
166 return make_float (d); 267 return make_float (d);
167 } 268 }
168 269
169 DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0, 270 DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
170 "Return the order N bessel function output jn of ARG.\n\ 271 "Return the order N bessel function output jn of ARG.\n\
171 The first arg (the order) is truncated to an integer.") 272 The first arg (the order) is truncated to an integer.")
172 (num1, num2) 273 (arg1, arg2)
173 register Lisp_Object num1, num2; 274 register Lisp_Object arg1, arg2;
174 { 275 {
175 int i1 = extract_float (num1); 276 int i1 = extract_float (arg1);
176 double f2 = extract_float (num2); 277 double f2 = extract_float (arg2);
177 278
178 IN_FLOAT (f2 = jn (i1, f2), num1); 279 IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", arg1);
179 return make_float (f2); 280 return make_float (f2);
180 } 281 }
181 282
182 DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0, 283 DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
183 "Return the bessel function y0 of ARG.") 284 "Return the bessel function y0 of ARG.")
184 (num) 285 (arg)
185 register Lisp_Object num; 286 register Lisp_Object arg;
186 { 287 {
187 double d = extract_float (num); 288 double d = extract_float (arg);
188 IN_FLOAT (d = y0 (d), num); 289 IN_FLOAT (d = y0 (d), "bessel-y0", arg);
189 return make_float (d); 290 return make_float (d);
190 } 291 }
191 292
192 DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0, 293 DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
193 "Return the bessel function y1 of ARG.") 294 "Return the bessel function y1 of ARG.")
194 (num) 295 (arg)
195 register Lisp_Object num; 296 register Lisp_Object arg;
196 { 297 {
197 double d = extract_float (num); 298 double d = extract_float (arg);
198 IN_FLOAT (d = y1 (d), num); 299 IN_FLOAT (d = y1 (d), "bessel-y0", arg);
199 return make_float (d); 300 return make_float (d);
200 } 301 }
201 302
202 DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0, 303 DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
203 "Return the order N bessel function output yn of ARG.\n\ 304 "Return the order N bessel function output yn of ARG.\n\
204 The first arg (the order) is truncated to an integer.") 305 The first arg (the order) is truncated to an integer.")
205 (num1, num2) 306 (arg1, arg2)
206 register Lisp_Object num1, num2; 307 register Lisp_Object arg1, arg2;
207 { 308 {
208 int i1 = extract_float (num1); 309 int i1 = extract_float (arg1);
209 double f2 = extract_float (num2); 310 double f2 = extract_float (arg2);
210 311
211 IN_FLOAT (f2 = yn (i1, f2), num1); 312 IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", arg1);
212 return make_float (f2); 313 return make_float (f2);
213 } 314 }
214 315
215 #endif 316 #endif
216 317
217 #if 0 /* Leave these out unless we see they are worth having. */ 318 #if 0 /* Leave these out unless we see they are worth having. */
218 319
219 DEFUN ("erf", Ferf, Serf, 1, 1, 0, 320 DEFUN ("erf", Ferf, Serf, 1, 1, 0,
220 "Return the mathematical error function of ARG.") 321 "Return the mathematical error function of ARG.")
221 (num) 322 (arg)
222 register Lisp_Object num; 323 register Lisp_Object arg;
223 { 324 {
224 double d = extract_float (num); 325 double d = extract_float (arg);
225 IN_FLOAT (d = erf (d), num); 326 IN_FLOAT (d = erf (d), "erf", arg);
226 return make_float (d); 327 return make_float (d);
227 } 328 }
228 329
229 DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0, 330 DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
230 "Return the complementary error function of ARG.") 331 "Return the complementary error function of ARG.")
231 (num) 332 (arg)
232 register Lisp_Object num; 333 register Lisp_Object arg;
233 { 334 {
234 double d = extract_float (num); 335 double d = extract_float (arg);
235 IN_FLOAT (d = erfc (d), num); 336 IN_FLOAT (d = erfc (d), "erfc", arg);
236 return make_float (d); 337 return make_float (d);
237 } 338 }
238 339
239 DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0, 340 DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
240 "Return the log gamma of ARG.") 341 "Return the log gamma of ARG.")
241 (num) 342 (arg)
242 register Lisp_Object num; 343 register Lisp_Object arg;
243 { 344 {
244 double d = extract_float (num); 345 double d = extract_float (arg);
245 IN_FLOAT (d = lgamma (d), num); 346 IN_FLOAT (d = lgamma (d), "log-gamma", arg);
246 return make_float (d); 347 return make_float (d);
247 } 348 }
248 349
249 DEFUN ("cbrt", Fcbrt, Scbrt, 1, 1, 0, 350 DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
250 "Return the cube root of ARG.") 351 "Return the cube root of ARG.")
251 (num) 352 (arg)
252 register Lisp_Object num; 353 register Lisp_Object arg;
253 { 354 {
254 double d = extract_float (num); 355 double d = extract_float (arg);
255 IN_FLOAT (d = cbrt (d), num); 356 #ifdef HAVE_CBRT
357 IN_FLOAT (d = cbrt (d), "cube-root", arg);
358 #else
359 if (d >= 0.0)
360 IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
361 else
362 IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
363 #endif
256 return make_float (d); 364 return make_float (d);
257 } 365 }
258 366
259 #endif 367 #endif
260 368
261 DEFUN ("exp", Fexp, Sexp, 1, 1, 0, 369 DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
262 "Return the exponential base e of ARG.") 370 "Return the exponential base e of ARG.")
263 (num) 371 (arg)
264 register Lisp_Object num; 372 register Lisp_Object arg;
265 { 373 {
266 double d = extract_float (num); 374 double d = extract_float (arg);
267 IN_FLOAT (d = exp (d), num); 375 #ifdef FLOAT_CHECK_DOMAIN
376 if (d > 709.7827) /* Assume IEEE doubles here */
377 range_error ("exp", arg);
378 else if (d < -709.0)
379 return make_float (0.0);
380 else
381 #endif
382 IN_FLOAT (d = exp (d), "exp", arg);
268 return make_float (d); 383 return make_float (d);
269 } 384 }
270 385
271 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, 386 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
272 "Return the exponential X ** Y.") 387 "Return the exponential X ** Y.")
273 (num1, num2) 388 (arg1, arg2)
274 register Lisp_Object num1, num2; 389 register Lisp_Object arg1, arg2;
275 { 390 {
276 double f1, f2; 391 double f1, f2;
277 392
278 CHECK_NUMBER_OR_FLOAT (num1, 0); 393 CHECK_NUMBER_OR_FLOAT (arg1, 0);
279 CHECK_NUMBER_OR_FLOAT (num2, 0); 394 CHECK_NUMBER_OR_FLOAT (arg2, 0);
280 if ((XTYPE (num1) == Lisp_Int) && /* common lisp spec */ 395 if ((XTYPE (arg1) == Lisp_Int) && /* common lisp spec */
281 (XTYPE (num2) == Lisp_Int)) /* don't promote, if both are ints */ 396 (XTYPE (arg2) == Lisp_Int)) /* don't promote, if both are ints */
282 { /* this can be improved by pre-calculating */ 397 { /* this can be improved by pre-calculating */
283 int acc, x, y; /* some binary powers of x then acumulating */ 398 int acc, x, y; /* some binary powers of x then acumulating */
284 /* these, therby saving some time. -wsr */ 399 /* these, therby saving some time. -wsr */
285 x = XINT (num1); 400 x = XINT (arg1);
286 y = XINT (num2); 401 y = XINT (arg2);
287 acc = 1; 402 acc = 1;
288 403
289 if (y < 0) 404 if (y < 0)
290 { 405 {
291 for (; y < 0; y++) 406 if (x == 1)
292 acc /= x; 407 acc = 1;
408 else if (x == -1)
409 acc = (y & 1) ? -1 : 1;
410 else
411 acc = 0;
293 } 412 }
294 else 413 else
295 { 414 {
296 for (; y > 0; y--) 415 for (; y > 0; y--)
297 acc *= x; 416 while (y > 0)
417 {
418 if (y & 1)
419 acc *= x;
420 x *= x;
421 y = (unsigned)y >> 1;
422 }
298 } 423 }
299 XFASTINT (x) = acc; 424 XSET (x, Lisp_Int, acc);
300 return x; 425 return x;
301 } 426 }
302 f1 = (XTYPE (num1) == Lisp_Float) ? XFLOAT (num1)->data : XINT (num1); 427 f1 = (XTYPE (arg1) == Lisp_Float) ? XFLOAT (arg1)->data : XINT (arg1);
303 f2 = (XTYPE (num2) == Lisp_Float) ? XFLOAT (num2)->data : XINT (num2); 428 f2 = (XTYPE (arg2) == Lisp_Float) ? XFLOAT (arg2)->data : XINT (arg2);
304 IN_FLOAT (f1 = pow (f1, f2), num1); 429 /* Really should check for overflow, too */
430 if (f1 == 0.0 && f2 == 0.0)
431 f1 = 1.0;
432 #ifdef FLOAT_CHECK_DOMAIN
433 else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
434 domain_error2 ("expt", arg1, arg2);
435 #endif
436 IN_FLOAT (f1 = pow (f1, f2), "expt", arg1);
305 return make_float (f1); 437 return make_float (f1);
306 } 438 }
307 439
308 DEFUN ("log", Flog, Slog, 1, 2, 0, 440 DEFUN ("log", Flog, Slog, 1, 2, 0,
309 "Return the natural logarithm of NUM.\n\ 441 "Return the natural logarithm of ARG.\n\
310 If second optional argument BASE is given, return log NUM using that base.") 442 If second optional argument BASE is given, return log ARG using that base.")
311 (num, base) 443 (arg, base)
312 register Lisp_Object num, base; 444 register Lisp_Object arg, base;
313 { 445 {
314 double d = extract_float (num); 446 double d = extract_float (arg);
315 447
448 #ifdef FLOAT_CHECK_DOMAIN
449 if (d <= 0.0)
450 domain_error2 ("log", arg, base);
451 #endif
316 if (NILP (base)) 452 if (NILP (base))
317 IN_FLOAT (d = log (d), num); 453 IN_FLOAT (d = log (d), "log", arg);
318 else 454 else
319 { 455 {
320 double b = extract_float (base); 456 double b = extract_float (base);
321 457
322 IN_FLOAT (d = log (num) / log (b), num); 458 #ifdef FLOAT_CHECK_DOMAIN
459 if (b <= 0.0 || b == 1.0)
460 domain_error2 ("log", arg, base);
461 #endif
462 if (b == 10.0)
463 IN_FLOAT2 (d = log10 (d), "log", arg, base);
464 else
465 IN_FLOAT2 (d = log (arg) / log (b), "log", arg, base);
323 } 466 }
324 return make_float (d); 467 return make_float (d);
325 } 468 }
326 469
327 DEFUN ("log10", Flog10, Slog10, 1, 1, 0, 470 DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
328 "Return the logarithm base 10 of ARG.") 471 "Return the logarithm base 10 of ARG.")
329 (num) 472 (arg)
330 register Lisp_Object num; 473 register Lisp_Object arg;
331 { 474 {
332 double d = extract_float (num); 475 double d = extract_float (arg);
333 IN_FLOAT (d = log10 (d), num); 476 #ifdef FLOAT_CHECK_DOMAIN
477 if (d <= 0.0)
478 domain_error ("log10", arg);
479 #endif
480 IN_FLOAT (d = log10 (d), "log10", arg);
334 return make_float (d); 481 return make_float (d);
335 } 482 }
336 483
337 DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0, 484 DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
338 "Return the square root of ARG.") 485 "Return the square root of ARG.")
339 (num) 486 (arg)
340 register Lisp_Object num; 487 register Lisp_Object arg;
341 { 488 {
342 double d = extract_float (num); 489 double d = extract_float (arg);
343 IN_FLOAT (d = sqrt (d), num); 490 #ifdef FLOAT_CHECK_DOMAIN
491 if (d < 0.0)
492 domain_error ("sqrt", arg);
493 #endif
494 IN_FLOAT (d = sqrt (d), "sqrt", arg);
344 return make_float (d); 495 return make_float (d);
345 } 496 }
346 497
347 #if 0 /* Not clearly worth adding. */ 498 #if 0 /* Not clearly worth adding. */
348 499
349 DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0, 500 DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
350 "Return the inverse hyperbolic cosine of ARG.") 501 "Return the inverse hyperbolic cosine of ARG.")
351 (num) 502 (arg)
352 register Lisp_Object num; 503 register Lisp_Object arg;
353 { 504 {
354 double d = extract_float (num); 505 double d = extract_float (arg);
355 IN_FLOAT (d = acosh (d), num); 506 #ifdef FLOAT_CHECK_DOMAIN
507 if (d < 1.0)
508 domain_error ("acosh", arg);
509 #endif
510 #ifdef HAVE_INVERSE_HYPERBOLIC
511 IN_FLOAT (d = acosh (d), "acosh", arg);
512 #else
513 IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg);
514 #endif
356 return make_float (d); 515 return make_float (d);
357 } 516 }
358 517
359 DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0, 518 DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
360 "Return the inverse hyperbolic sine of ARG.") 519 "Return the inverse hyperbolic sine of ARG.")
361 (num) 520 (arg)
362 register Lisp_Object num; 521 register Lisp_Object arg;
363 { 522 {
364 double d = extract_float (num); 523 double d = extract_float (arg);
365 IN_FLOAT (d = asinh (d), num); 524 #ifdef HAVE_INVERSE_HYPERBOLIC
525 IN_FLOAT (d = asinh (d), "asinh", arg);
526 #else
527 IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg);
528 #endif
366 return make_float (d); 529 return make_float (d);
367 } 530 }
368 531
369 DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0, 532 DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
370 "Return the inverse hyperbolic tangent of ARG.") 533 "Return the inverse hyperbolic tangent of ARG.")
371 (num) 534 (arg)
372 register Lisp_Object num; 535 register Lisp_Object arg;
373 { 536 {
374 double d = extract_float (num); 537 double d = extract_float (arg);
375 IN_FLOAT (d = atanh (d), num); 538 #ifdef FLOAT_CHECK_DOMAIN
539 if (d >= 1.0 || d <= -1.0)
540 domain_error ("atanh", arg);
541 #endif
542 #ifdef HAVE_INVERSE_HYPERBOLIC
543 IN_FLOAT (d = atanh (d), "atanh", arg);
544 #else
545 IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg);
546 #endif
376 return make_float (d); 547 return make_float (d);
377 } 548 }
378 549
379 DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0, 550 DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
380 "Return the hyperbolic cosine of ARG.") 551 "Return the hyperbolic cosine of ARG.")
381 (num) 552 (arg)
382 register Lisp_Object num; 553 register Lisp_Object arg;
383 { 554 {
384 double d = extract_float (num); 555 double d = extract_float (arg);
385 IN_FLOAT (d = cosh (d), num); 556 #ifdef FLOAT_CHECK_DOMAIN
557 if (d > 710.0 || d < -710.0)
558 range_error ("cosh", arg);
559 #endif
560 IN_FLOAT (d = cosh (d), "cosh", arg);
386 return make_float (d); 561 return make_float (d);
387 } 562 }
388 563
389 DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0, 564 DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
390 "Return the hyperbolic sine of ARG.") 565 "Return the hyperbolic sine of ARG.")
391 (num) 566 (arg)
392 register Lisp_Object num; 567 register Lisp_Object arg;
393 { 568 {
394 double d = extract_float (num); 569 double d = extract_float (arg);
395 IN_FLOAT (d = sinh (d), num); 570 #ifdef FLOAT_CHECK_DOMAIN
571 if (d > 710.0 || d < -710.0)
572 range_error ("sinh", arg);
573 #endif
574 IN_FLOAT (d = sinh (d), "sinh", arg);
396 return make_float (d); 575 return make_float (d);
397 } 576 }
398 577
399 DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0, 578 DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
400 "Return the hyperbolic tangent of ARG.") 579 "Return the hyperbolic tangent of ARG.")
401 (num) 580 (arg)
402 register Lisp_Object num; 581 register Lisp_Object arg;
403 { 582 {
404 double d = extract_float (num); 583 double d = extract_float (arg);
405 IN_FLOAT (d = tanh (d), num); 584 IN_FLOAT (d = tanh (d), "tanh", arg);
406 return make_float (d); 585 return make_float (d);
407 } 586 }
408 #endif 587 #endif
409 588
410 DEFUN ("abs", Fabs, Sabs, 1, 1, 0, 589 DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
411 "Return the absolute value of ARG.") 590 "Return the absolute value of ARG.")
412 (num) 591 (arg)
413 register Lisp_Object num; 592 register Lisp_Object arg;
414 { 593 {
415 CHECK_NUMBER_OR_FLOAT (num, 0); 594 CHECK_NUMBER_OR_FLOAT (arg, 0);
416 595
417 if (XTYPE (num) == Lisp_Float) 596 if (XTYPE (arg) == Lisp_Float)
418 IN_FLOAT (num = make_float (fabs (XFLOAT (num)->data)), num); 597 IN_FLOAT (arg = make_float (fabs (XFLOAT (arg)->data)), "abs", arg);
419 else if (XINT (num) < 0) 598 else if (XINT (arg) < 0)
420 XSETINT (num, - XFASTINT (num)); 599 XSETINT (arg, - XFASTINT (arg));
421 600
422 return num; 601 return arg;
423 } 602 }
424 603
425 DEFUN ("float", Ffloat, Sfloat, 1, 1, 0, 604 DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
426 "Return the floating point number equal to ARG.") 605 "Return the floating point number equal to ARG.")
427 (num) 606 (arg)
428 register Lisp_Object num; 607 register Lisp_Object arg;
429 { 608 {
430 CHECK_NUMBER_OR_FLOAT (num, 0); 609 CHECK_NUMBER_OR_FLOAT (arg, 0);
431 610
432 if (XTYPE (num) == Lisp_Int) 611 if (XTYPE (arg) == Lisp_Int)
433 return make_float ((double) XINT (num)); 612 return make_float ((double) XINT (arg));
434 else /* give 'em the same float back */ 613 else /* give 'em the same float back */
435 return num; 614 return arg;
436 } 615 }
437 616
438 DEFUN ("logb", Flogb, Slogb, 1, 1, 0, 617 DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
439 "Returns the integer that is the base 2 log of ARG.\n\ 618 "Returns the integer that is the base 2 log of ARG.\n\
440 This is the same as the exponent of a float.") 619 This is the same as the exponent of a float.")
441 (num) 620 (arg)
442 Lisp_Object num; 621 Lisp_Object arg;
443 { 622 {
444 /* System V apparently doesn't have a `logb' function. It might be 623 /* System V apparently doesn't have a `logb' function. It might be
445 better to use it on systems that have it, but Ultrix (at least) 624 better to use it on systems that have it, but Ultrix (at least)
446 doesn't declare it properly in <math.h>; does anyone really care? */ 625 doesn't declare it properly in <math.h>; does anyone really care? */
447 return Flog (num, make_number (2)); 626 return Flog (arg, make_number (2));
448 } 627 }
449 628
450 /* the rounding functions */ 629 /* the rounding functions */
451 630
452 DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0, 631 DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
453 "Return the smallest integer no less than ARG. (Round toward +inf.)") 632 "Return the smallest integer no less than ARG. (Round toward +inf.)")
454 (num) 633 (arg)
455 register Lisp_Object num; 634 register Lisp_Object arg;
456 { 635 {
457 CHECK_NUMBER_OR_FLOAT (num, 0); 636 CHECK_NUMBER_OR_FLOAT (arg, 0);
458 637
459 if (XTYPE (num) == Lisp_Float) 638 if (XTYPE (arg) == Lisp_Float)
460 IN_FLOAT (XSET (num, Lisp_Int, ceil (XFLOAT (num)->data)), num); 639 IN_FLOAT (XSET (arg, Lisp_Int, ceil (XFLOAT (arg)->data)), "celing", arg);
461 640
462 return num; 641 return arg;
463 } 642 }
464 643
465 DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0, 644 DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0,
466 "Return the largest integer no greater than ARG. (Round towards -inf.)") 645 "Return the largest integer no greater than ARG. (Round towards -inf.)")
467 (num) 646 (arg)
468 register Lisp_Object num; 647 register Lisp_Object arg;
469 { 648 {
470 CHECK_NUMBER_OR_FLOAT (num, 0); 649 CHECK_NUMBER_OR_FLOAT (arg, 0);
471 650
472 if (XTYPE (num) == Lisp_Float) 651 if (XTYPE (arg) == Lisp_Float)
473 IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data)), num); 652 IN_FLOAT (XSET (arg, Lisp_Int, floor (XFLOAT (arg)->data)), "floor", arg);
474 653
475 return num; 654 return arg;
476 } 655 }
477 656
478 DEFUN ("round", Fround, Sround, 1, 1, 0, 657 DEFUN ("round", Fround, Sround, 1, 1, 0,
479 "Return the nearest integer to ARG.") 658 "Return the nearest integer to ARG.")
480 (num) 659 (arg)
481 register Lisp_Object num; 660 register Lisp_Object arg;
482 { 661 {
483 CHECK_NUMBER_OR_FLOAT (num, 0); 662 CHECK_NUMBER_OR_FLOAT (arg, 0);
484 663
485 if (XTYPE (num) == Lisp_Float) 664 if (XTYPE (arg) == Lisp_Float)
486 { 665 /* Screw the prevailing rounding mode. */
487 /* Screw the prevailing rounding mode. */ 666 IN_FLOAT (XSET (arg, Lisp_Int, rint (XFLOAT (arg)->data)), "round", arg);
488 IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data + 0.5)), num); 667
489 668 return arg;
490 /* It used to be that on non-USG systems we'd use the `rint'
491 function. But that seems not to be declared properly in
492 <math.h> on Ultrix, I don't want to declare it myself because
493 that might conflict with <math.h> on other systems, and I
494 don't see what's wrong with the code above anyway. */
495 }
496
497 return num;
498 } 669 }
499 670
500 DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0, 671 DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0,
501 "Truncate a floating point number to an int.\n\ 672 "Truncate a floating point number to an int.\n\
502 Rounds the value toward zero.") 673 Rounds the value toward zero.")
503 (num) 674 (arg)
504 register Lisp_Object num; 675 register Lisp_Object arg;
505 { 676 {
506 CHECK_NUMBER_OR_FLOAT (num, 0); 677 CHECK_NUMBER_OR_FLOAT (arg, 0);
507 678
508 if (XTYPE (num) == Lisp_Float) 679 if (XTYPE (arg) == Lisp_Float)
509 XSET (num, Lisp_Int, (int) XFLOAT (num)->data); 680 XSET (arg, Lisp_Int, (int) XFLOAT (arg)->data);
510 681
511 return num; 682 return arg;
512 } 683 }
513 684
685 #if 0
686 /* It's not clear these are worth adding. */
687
688 DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
689 "Return the smallest integer no less than ARG, as a float.\n\
690 \(Round toward +inf.\)")
691 (arg)
692 register Lisp_Object arg;
693 {
694 double d = extract_float (arg);
695 IN_FLOAT (d = ceil (d), "fceiling", arg);
696 return make_float (d);
697 }
698
699 DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
700 "Return the largest integer no greater than ARG, as a float.\n\
701 \(Round towards -inf.\)")
702 (arg)
703 register Lisp_Object arg;
704 {
705 double d = extract_float (arg);
706 IN_FLOAT (d = floor (d), "ffloor", arg);
707 return make_float (d);
708 }
709
710 DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
711 "Return the nearest integer to ARG, as a float.")
712 (arg)
713 register Lisp_Object arg;
714 {
715 double d = extract_float (arg);
716 IN_FLOAT (d = rint (XFLOAT (arg)->data), "fround", arg);
717 return make_float (d);
718 }
719
720 DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
721 "Truncate a floating point number to an integral float value.\n\
722 Rounds the value toward zero.")
723 (arg)
724 register Lisp_Object arg;
725 {
726 double d = extract_float (arg);
727 if (d >= 0.0)
728 IN_FLOAT (d = floor (d), "ftruncate", arg);
729 else
730 IN_FLOAT (d = ceil (d), arg);
731 return make_float (d);
732 }
733 #endif
734
735 #ifdef FLOAT_CATCH_SIGILL
514 static SIGTYPE 736 static SIGTYPE
515 float_error (signo) 737 float_error (signo)
516 int signo; 738 int signo;
517 { 739 {
518 if (! in_float) 740 if (! in_float)
532 in_float = 0; 754 in_float = 0;
533 755
534 Fsignal (Qarith_error, Fcons (float_error_arg, Qnil)); 756 Fsignal (Qarith_error, Fcons (float_error_arg, Qnil));
535 } 757 }
536 758
759 /* Another idea was to replace the library function `infnan'
760 where SIGILL is signaled. */
761
762 #endif /* FLOAT_CATCH_SIGILL */
763
764 #ifdef HAVE_MATHERR
765 int
766 matherr (x)
767 struct exception *x;
768 {
769 Lisp_Object args;
770 if (! in_float)
771 /* Not called from emacs-lisp float routines; do the default thing. */
772 return 0;
773 if (!strcmp (x->name, "pow"))
774 x->name = "expt";
775
776 args
777 = Fcons (build_string (x->name),
778 Fcons (make_float (x->arg1),
779 ((!strcmp (x->name, "log") || !strcmp (x->name, "pow"))
780 ? Fcons (make_float (x->arg2), Qnil)
781 : Qnil)));
782 switch (x->type)
783 {
784 case DOMAIN: Fsignal (Qdomain_error, args); break;
785 case SING: Fsignal (Qsingularity_error, args); break;
786 case OVERFLOW: Fsignal (Qoverflow_error, args); break;
787 case UNDERFLOW: Fsignal (Qunderflow_error, args); break;
788 default: Fsignal (Qarith_error, args); break;
789 }
790 return (1); /* don't set errno or print a message */
791 }
792 #endif /* HAVE_MATHERR */
793
537 init_floatfns () 794 init_floatfns ()
538 { 795 {
796 #ifdef FLOAT_CATCH_SIGILL
539 signal (SIGILL, float_error); 797 signal (SIGILL, float_error);
798 #endif
540 in_float = 0; 799 in_float = 0;
541 } 800 }
542 801
543 syms_of_floatfns () 802 syms_of_floatfns ()
544 { 803 {
562 defsubr (&Sbessel_j1); 821 defsubr (&Sbessel_j1);
563 defsubr (&Sbessel_jn); 822 defsubr (&Sbessel_jn);
564 defsubr (&Serf); 823 defsubr (&Serf);
565 defsubr (&Serfc); 824 defsubr (&Serfc);
566 defsubr (&Slog_gamma); 825 defsubr (&Slog_gamma);
567 defsubr (&Scbrt); 826 defsubr (&Scube_root);
827 defsubr (&Sfceiling);
828 defsubr (&Sffloor);
829 defsubr (&Sfround);
830 defsubr (&Sftruncate);
568 #endif 831 #endif
569 defsubr (&Sexp); 832 defsubr (&Sexp);
570 defsubr (&Sexpt); 833 defsubr (&Sexpt);
571 defsubr (&Slog); 834 defsubr (&Slog);
572 defsubr (&Slog10); 835 defsubr (&Slog10);