]> code.delx.au - gnu-emacs/blob - src/floatfns.c
Convert consecutive FSF copyright years to ranges.
[gnu-emacs] / src / floatfns.c
1 /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
2 Copyright (C) 1988, 1993-1994, 1999, 2001-2011 Free Software Foundation, Inc.
3
4 Author: Wolfgang Rupprecht
5 (according to ack.texi)
6
7 This file is part of GNU Emacs.
8
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21
22
23 /* ANSI C requires only these float functions:
24 acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
25 frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
26
27 Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
28 Define HAVE_CBRT if you have cbrt.
29 Define HAVE_RINT if you have a working rint.
30 If you don't define these, then the appropriate routines will be simulated.
31
32 Define HAVE_MATHERR if on a system supporting the SysV matherr callback.
33 (This should happen automatically.)
34
35 Define FLOAT_CHECK_ERRNO if the float library routines set errno.
36 This has no effect if HAVE_MATHERR is defined.
37
38 Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
39 (What systems actually do this? Please let us know.)
40
41 Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
42 either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and
43 range checking will happen before calling the float routines. This has
44 no effect if HAVE_MATHERR is defined (since matherr will be called when
45 a domain error occurs.)
46 */
47
48 #include <config.h>
49 #include <signal.h>
50 #include <setjmp.h>
51 #include "lisp.h"
52 #include "syssignal.h"
53
54 #if STDC_HEADERS
55 #include <float.h>
56 #endif
57
58 /* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
59 #ifndef IEEE_FLOATING_POINT
60 #if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
61 && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
62 #define IEEE_FLOATING_POINT 1
63 #else
64 #define IEEE_FLOATING_POINT 0
65 #endif
66 #endif
67
68 #include <math.h>
69
70 /* This declaration is omitted on some systems, like Ultrix. */
71 #if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
72 extern double logb (double);
73 #endif /* not HPUX and HAVE_LOGB and no logb macro */
74
75 #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
76 /* If those are defined, then this is probably a `matherr' machine. */
77 # ifndef HAVE_MATHERR
78 # define HAVE_MATHERR
79 # endif
80 #endif
81
82 #ifdef NO_MATHERR
83 #undef HAVE_MATHERR
84 #endif
85
86 #ifdef HAVE_MATHERR
87 # ifdef FLOAT_CHECK_ERRNO
88 # undef FLOAT_CHECK_ERRNO
89 # endif
90 # ifdef FLOAT_CHECK_DOMAIN
91 # undef FLOAT_CHECK_DOMAIN
92 # endif
93 #endif
94
95 #ifndef NO_FLOAT_CHECK_ERRNO
96 #define FLOAT_CHECK_ERRNO
97 #endif
98
99 #ifdef FLOAT_CHECK_ERRNO
100 # include <errno.h>
101 #endif
102
103 #ifdef FLOAT_CATCH_SIGILL
104 static SIGTYPE float_error ();
105 #endif
106
107 /* Nonzero while executing in floating point.
108 This tells float_error what to do. */
109
110 static int in_float;
111
112 /* If an argument is out of range for a mathematical function,
113 here is the actual argument value to use in the error message.
114 These variables are used only across the floating point library call
115 so there is no need to staticpro them. */
116
117 static Lisp_Object float_error_arg, float_error_arg2;
118
119 static const char *float_error_fn_name;
120
121 /* Evaluate the floating point expression D, recording NUM
122 as the original argument for error messages.
123 D is normally an assignment expression.
124 Handle errors which may result in signals or may set errno.
125
126 Note that float_error may be declared to return void, so you can't
127 just cast the zero after the colon to (SIGTYPE) to make the types
128 check properly. */
129
130 #ifdef FLOAT_CHECK_ERRNO
131 #define IN_FLOAT(d, name, num) \
132 do { \
133 float_error_arg = num; \
134 float_error_fn_name = name; \
135 in_float = 1; errno = 0; (d); in_float = 0; \
136 switch (errno) { \
137 case 0: break; \
138 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
139 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
140 default: arith_error (float_error_fn_name, float_error_arg); \
141 } \
142 } while (0)
143 #define IN_FLOAT2(d, name, num, num2) \
144 do { \
145 float_error_arg = num; \
146 float_error_arg2 = num2; \
147 float_error_fn_name = name; \
148 in_float = 1; errno = 0; (d); in_float = 0; \
149 switch (errno) { \
150 case 0: break; \
151 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
152 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
153 default: arith_error (float_error_fn_name, float_error_arg); \
154 } \
155 } while (0)
156 #else
157 #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
158 #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
159 #endif
160
161 /* Convert float to Lisp_Int if it fits, else signal a range error
162 using the given arguments. */
163 #define FLOAT_TO_INT(x, i, name, num) \
164 do \
165 { \
166 if (FIXNUM_OVERFLOW_P (x)) \
167 range_error (name, num); \
168 XSETINT (i, (EMACS_INT)(x)); \
169 } \
170 while (0)
171 #define FLOAT_TO_INT2(x, i, name, num1, num2) \
172 do \
173 { \
174 if (FIXNUM_OVERFLOW_P (x)) \
175 range_error2 (name, num1, num2); \
176 XSETINT (i, (EMACS_INT)(x)); \
177 } \
178 while (0)
179
180 #define arith_error(op,arg) \
181 xsignal2 (Qarith_error, build_string ((op)), (arg))
182 #define range_error(op,arg) \
183 xsignal2 (Qrange_error, build_string ((op)), (arg))
184 #define range_error2(op,a1,a2) \
185 xsignal3 (Qrange_error, build_string ((op)), (a1), (a2))
186 #define domain_error(op,arg) \
187 xsignal2 (Qdomain_error, build_string ((op)), (arg))
188 #define domain_error2(op,a1,a2) \
189 xsignal3 (Qdomain_error, build_string ((op)), (a1), (a2))
190
191 /* Extract a Lisp number as a `double', or signal an error. */
192
193 double
194 extract_float (Lisp_Object num)
195 {
196 CHECK_NUMBER_OR_FLOAT (num);
197
198 if (FLOATP (num))
199 return XFLOAT_DATA (num);
200 return (double) XINT (num);
201 }
202 \f
203 /* Trig functions. */
204
205 DEFUN ("acos", Facos, Sacos, 1, 1, 0,
206 doc: /* Return the inverse cosine of ARG. */)
207 (register Lisp_Object arg)
208 {
209 double d = extract_float (arg);
210 #ifdef FLOAT_CHECK_DOMAIN
211 if (d > 1.0 || d < -1.0)
212 domain_error ("acos", arg);
213 #endif
214 IN_FLOAT (d = acos (d), "acos", arg);
215 return make_float (d);
216 }
217
218 DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
219 doc: /* Return the inverse sine of ARG. */)
220 (register Lisp_Object arg)
221 {
222 double d = extract_float (arg);
223 #ifdef FLOAT_CHECK_DOMAIN
224 if (d > 1.0 || d < -1.0)
225 domain_error ("asin", arg);
226 #endif
227 IN_FLOAT (d = asin (d), "asin", arg);
228 return make_float (d);
229 }
230
231 DEFUN ("atan", Fatan, Satan, 1, 2, 0,
232 doc: /* Return the inverse tangent of the arguments.
233 If only one argument Y is given, return the inverse tangent of Y.
234 If two arguments Y and X are given, return the inverse tangent of Y
235 divided by X, i.e. the angle in radians between the vector (X, Y)
236 and the x-axis. */)
237 (register Lisp_Object y, Lisp_Object x)
238 {
239 double d = extract_float (y);
240
241 if (NILP (x))
242 IN_FLOAT (d = atan (d), "atan", y);
243 else
244 {
245 double d2 = extract_float (x);
246
247 IN_FLOAT2 (d = atan2 (d, d2), "atan", y, x);
248 }
249 return make_float (d);
250 }
251
252 DEFUN ("cos", Fcos, Scos, 1, 1, 0,
253 doc: /* Return the cosine of ARG. */)
254 (register Lisp_Object arg)
255 {
256 double d = extract_float (arg);
257 IN_FLOAT (d = cos (d), "cos", arg);
258 return make_float (d);
259 }
260
261 DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
262 doc: /* Return the sine of ARG. */)
263 (register Lisp_Object arg)
264 {
265 double d = extract_float (arg);
266 IN_FLOAT (d = sin (d), "sin", arg);
267 return make_float (d);
268 }
269
270 DEFUN ("tan", Ftan, Stan, 1, 1, 0,
271 doc: /* Return the tangent of ARG. */)
272 (register Lisp_Object arg)
273 {
274 double d = extract_float (arg);
275 double c = cos (d);
276 #ifdef FLOAT_CHECK_DOMAIN
277 if (c == 0.0)
278 domain_error ("tan", arg);
279 #endif
280 IN_FLOAT (d = sin (d) / c, "tan", arg);
281 return make_float (d);
282 }
283
284 #if defined HAVE_ISNAN && defined HAVE_COPYSIGN
285 DEFUN ("isnan", Fisnan, Sisnan, 1, 1, 0,
286 doc: /* Return non nil iff argument X is a NaN. */)
287 (Lisp_Object x)
288 {
289 CHECK_FLOAT (x);
290 return isnan (XFLOAT_DATA (x)) ? Qt : Qnil;
291 }
292
293 DEFUN ("copysign", Fcopysign, Scopysign, 1, 2, 0,
294 doc: /* Copy sign of X2 to value of X1, and return the result.
295 Cause an error if X1 or X2 is not a float. */)
296 (Lisp_Object x1, Lisp_Object x2)
297 {
298 double f1, f2;
299
300 CHECK_FLOAT (x1);
301 CHECK_FLOAT (x2);
302
303 f1 = XFLOAT_DATA (x1);
304 f2 = XFLOAT_DATA (x2);
305
306 return make_float (copysign (f1, f2));
307 }
308
309 DEFUN ("frexp", Ffrexp, Sfrexp, 1, 1, 0,
310 doc: /* Get significand and exponent of a floating point number.
311 Breaks the floating point number X into its binary significand SGNFCAND
312 \(a floating point value between 0.5 (included) and 1.0 (excluded))
313 and an integral exponent EXP for 2, such that:
314
315 X = SGNFCAND * 2^EXP
316
317 The function returns the cons cell (SGNFCAND . EXP).
318 If X is zero, both parts (SGNFCAND and EXP) are zero. */)
319 (Lisp_Object x)
320 {
321 double f = XFLOATINT (x);
322
323 if (f == 0.0)
324 return Fcons (make_float (0.0), make_number (0));
325 else
326 {
327 int exp;
328 double sgnfcand = frexp (f, &exp);
329 return Fcons (make_float (sgnfcand), make_number (exp));
330 }
331 }
332
333 DEFUN ("ldexp", Fldexp, Sldexp, 1, 2, 0,
334 doc: /* Construct number X from significand SGNFCAND and exponent EXP.
335 Returns the floating point value resulting from multiplying SGNFCAND
336 (the significand) by 2 raised to the power of EXP (the exponent). */)
337 (Lisp_Object sgnfcand, Lisp_Object exp)
338 {
339 CHECK_NUMBER (exp);
340 return make_float (ldexp (XFLOATINT (sgnfcand), XINT (exp)));
341 }
342 #endif
343 \f
344 #if 0 /* Leave these out unless we find there's a reason for them. */
345
346 DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
347 doc: /* Return the bessel function j0 of ARG. */)
348 (register Lisp_Object arg)
349 {
350 double d = extract_float (arg);
351 IN_FLOAT (d = j0 (d), "bessel-j0", arg);
352 return make_float (d);
353 }
354
355 DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
356 doc: /* Return the bessel function j1 of ARG. */)
357 (register Lisp_Object arg)
358 {
359 double d = extract_float (arg);
360 IN_FLOAT (d = j1 (d), "bessel-j1", arg);
361 return make_float (d);
362 }
363
364 DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
365 doc: /* Return the order N bessel function output jn of ARG.
366 The first arg (the order) is truncated to an integer. */)
367 (register Lisp_Object n, Lisp_Object arg)
368 {
369 int i1 = extract_float (n);
370 double f2 = extract_float (arg);
371
372 IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
373 return make_float (f2);
374 }
375
376 DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
377 doc: /* Return the bessel function y0 of ARG. */)
378 (register Lisp_Object arg)
379 {
380 double d = extract_float (arg);
381 IN_FLOAT (d = y0 (d), "bessel-y0", arg);
382 return make_float (d);
383 }
384
385 DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
386 doc: /* Return the bessel function y1 of ARG. */)
387 (register Lisp_Object arg)
388 {
389 double d = extract_float (arg);
390 IN_FLOAT (d = y1 (d), "bessel-y0", arg);
391 return make_float (d);
392 }
393
394 DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
395 doc: /* Return the order N bessel function output yn of ARG.
396 The first arg (the order) is truncated to an integer. */)
397 (register Lisp_Object n, Lisp_Object arg)
398 {
399 int i1 = extract_float (n);
400 double f2 = extract_float (arg);
401
402 IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
403 return make_float (f2);
404 }
405
406 #endif
407 \f
408 #if 0 /* Leave these out unless we see they are worth having. */
409
410 DEFUN ("erf", Ferf, Serf, 1, 1, 0,
411 doc: /* Return the mathematical error function of ARG. */)
412 (register Lisp_Object arg)
413 {
414 double d = extract_float (arg);
415 IN_FLOAT (d = erf (d), "erf", arg);
416 return make_float (d);
417 }
418
419 DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
420 doc: /* Return the complementary error function of ARG. */)
421 (register Lisp_Object arg)
422 {
423 double d = extract_float (arg);
424 IN_FLOAT (d = erfc (d), "erfc", arg);
425 return make_float (d);
426 }
427
428 DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
429 doc: /* Return the log gamma of ARG. */)
430 (register Lisp_Object arg)
431 {
432 double d = extract_float (arg);
433 IN_FLOAT (d = lgamma (d), "log-gamma", arg);
434 return make_float (d);
435 }
436
437 DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
438 doc: /* Return the cube root of ARG. */)
439 (register Lisp_Object arg)
440 {
441 double d = extract_float (arg);
442 #ifdef HAVE_CBRT
443 IN_FLOAT (d = cbrt (d), "cube-root", arg);
444 #else
445 if (d >= 0.0)
446 IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
447 else
448 IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
449 #endif
450 return make_float (d);
451 }
452
453 #endif
454 \f
455 DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
456 doc: /* Return the exponential base e of ARG. */)
457 (register Lisp_Object arg)
458 {
459 double d = extract_float (arg);
460 #ifdef FLOAT_CHECK_DOMAIN
461 if (d > 709.7827) /* Assume IEEE doubles here */
462 range_error ("exp", arg);
463 else if (d < -709.0)
464 return make_float (0.0);
465 else
466 #endif
467 IN_FLOAT (d = exp (d), "exp", arg);
468 return make_float (d);
469 }
470
471 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
472 doc: /* Return the exponential ARG1 ** ARG2. */)
473 (register Lisp_Object arg1, Lisp_Object arg2)
474 {
475 double f1, f2, f3;
476
477 CHECK_NUMBER_OR_FLOAT (arg1);
478 CHECK_NUMBER_OR_FLOAT (arg2);
479 if (INTEGERP (arg1) /* common lisp spec */
480 && INTEGERP (arg2) /* don't promote, if both are ints, and */
481 && 0 <= XINT (arg2)) /* we are sure the result is not fractional */
482 { /* this can be improved by pre-calculating */
483 EMACS_INT acc, x, y; /* some binary powers of x then accumulating */
484 Lisp_Object val;
485
486 x = XINT (arg1);
487 y = XINT (arg2);
488 acc = 1;
489
490 if (y < 0)
491 {
492 if (x == 1)
493 acc = 1;
494 else if (x == -1)
495 acc = (y & 1) ? -1 : 1;
496 else
497 acc = 0;
498 }
499 else
500 {
501 while (y > 0)
502 {
503 if (y & 1)
504 acc *= x;
505 x *= x;
506 y = (unsigned)y >> 1;
507 }
508 }
509 XSETINT (val, acc);
510 return val;
511 }
512 f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1);
513 f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2);
514 /* Really should check for overflow, too */
515 if (f1 == 0.0 && f2 == 0.0)
516 f1 = 1.0;
517 #ifdef FLOAT_CHECK_DOMAIN
518 else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
519 domain_error2 ("expt", arg1, arg2);
520 #endif
521 IN_FLOAT2 (f3 = pow (f1, f2), "expt", arg1, arg2);
522 /* Check for overflow in the result. */
523 if (f1 != 0.0 && f3 == 0.0)
524 range_error ("expt", arg1);
525 return make_float (f3);
526 }
527
528 DEFUN ("log", Flog, Slog, 1, 2, 0,
529 doc: /* Return the natural logarithm of ARG.
530 If the optional argument BASE is given, return log ARG using that base. */)
531 (register Lisp_Object arg, Lisp_Object base)
532 {
533 double d = extract_float (arg);
534
535 #ifdef FLOAT_CHECK_DOMAIN
536 if (d <= 0.0)
537 domain_error2 ("log", arg, base);
538 #endif
539 if (NILP (base))
540 IN_FLOAT (d = log (d), "log", arg);
541 else
542 {
543 double b = extract_float (base);
544
545 #ifdef FLOAT_CHECK_DOMAIN
546 if (b <= 0.0 || b == 1.0)
547 domain_error2 ("log", arg, base);
548 #endif
549 if (b == 10.0)
550 IN_FLOAT2 (d = log10 (d), "log", arg, base);
551 else
552 IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
553 }
554 return make_float (d);
555 }
556
557 DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
558 doc: /* Return the logarithm base 10 of ARG. */)
559 (register Lisp_Object arg)
560 {
561 double d = extract_float (arg);
562 #ifdef FLOAT_CHECK_DOMAIN
563 if (d <= 0.0)
564 domain_error ("log10", arg);
565 #endif
566 IN_FLOAT (d = log10 (d), "log10", arg);
567 return make_float (d);
568 }
569
570 DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
571 doc: /* Return the square root of ARG. */)
572 (register Lisp_Object arg)
573 {
574 double d = extract_float (arg);
575 #ifdef FLOAT_CHECK_DOMAIN
576 if (d < 0.0)
577 domain_error ("sqrt", arg);
578 #endif
579 IN_FLOAT (d = sqrt (d), "sqrt", arg);
580 return make_float (d);
581 }
582 \f
583 #if 0 /* Not clearly worth adding. */
584
585 DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
586 doc: /* Return the inverse hyperbolic cosine of ARG. */)
587 (register Lisp_Object arg)
588 {
589 double d = extract_float (arg);
590 #ifdef FLOAT_CHECK_DOMAIN
591 if (d < 1.0)
592 domain_error ("acosh", arg);
593 #endif
594 #ifdef HAVE_INVERSE_HYPERBOLIC
595 IN_FLOAT (d = acosh (d), "acosh", arg);
596 #else
597 IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg);
598 #endif
599 return make_float (d);
600 }
601
602 DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
603 doc: /* Return the inverse hyperbolic sine of ARG. */)
604 (register Lisp_Object arg)
605 {
606 double d = extract_float (arg);
607 #ifdef HAVE_INVERSE_HYPERBOLIC
608 IN_FLOAT (d = asinh (d), "asinh", arg);
609 #else
610 IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg);
611 #endif
612 return make_float (d);
613 }
614
615 DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
616 doc: /* Return the inverse hyperbolic tangent of ARG. */)
617 (register Lisp_Object arg)
618 {
619 double d = extract_float (arg);
620 #ifdef FLOAT_CHECK_DOMAIN
621 if (d >= 1.0 || d <= -1.0)
622 domain_error ("atanh", arg);
623 #endif
624 #ifdef HAVE_INVERSE_HYPERBOLIC
625 IN_FLOAT (d = atanh (d), "atanh", arg);
626 #else
627 IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg);
628 #endif
629 return make_float (d);
630 }
631
632 DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
633 doc: /* Return the hyperbolic cosine of ARG. */)
634 (register Lisp_Object arg)
635 {
636 double d = extract_float (arg);
637 #ifdef FLOAT_CHECK_DOMAIN
638 if (d > 710.0 || d < -710.0)
639 range_error ("cosh", arg);
640 #endif
641 IN_FLOAT (d = cosh (d), "cosh", arg);
642 return make_float (d);
643 }
644
645 DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
646 doc: /* Return the hyperbolic sine of ARG. */)
647 (register Lisp_Object arg)
648 {
649 double d = extract_float (arg);
650 #ifdef FLOAT_CHECK_DOMAIN
651 if (d > 710.0 || d < -710.0)
652 range_error ("sinh", arg);
653 #endif
654 IN_FLOAT (d = sinh (d), "sinh", arg);
655 return make_float (d);
656 }
657
658 DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
659 doc: /* Return the hyperbolic tangent of ARG. */)
660 (register Lisp_Object arg)
661 {
662 double d = extract_float (arg);
663 IN_FLOAT (d = tanh (d), "tanh", arg);
664 return make_float (d);
665 }
666 #endif
667 \f
668 DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
669 doc: /* Return the absolute value of ARG. */)
670 (register Lisp_Object arg)
671 {
672 CHECK_NUMBER_OR_FLOAT (arg);
673
674 if (FLOATP (arg))
675 IN_FLOAT (arg = make_float (fabs (XFLOAT_DATA (arg))), "abs", arg);
676 else if (XINT (arg) < 0)
677 XSETINT (arg, - XINT (arg));
678
679 return arg;
680 }
681
682 DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
683 doc: /* Return the floating point number equal to ARG. */)
684 (register Lisp_Object arg)
685 {
686 CHECK_NUMBER_OR_FLOAT (arg);
687
688 if (INTEGERP (arg))
689 return make_float ((double) XINT (arg));
690 else /* give 'em the same float back */
691 return arg;
692 }
693
694 DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
695 doc: /* Returns largest integer <= the base 2 log of the magnitude of ARG.
696 This is the same as the exponent of a float. */)
697 (Lisp_Object arg)
698 {
699 Lisp_Object val;
700 EMACS_INT value;
701 double f = extract_float (arg);
702
703 if (f == 0.0)
704 value = MOST_NEGATIVE_FIXNUM;
705 else
706 {
707 #ifdef HAVE_LOGB
708 IN_FLOAT (value = logb (f), "logb", arg);
709 #else
710 #ifdef HAVE_FREXP
711 int ivalue;
712 IN_FLOAT (frexp (f, &ivalue), "logb", arg);
713 value = ivalue - 1;
714 #else
715 int i;
716 double d;
717 if (f < 0.0)
718 f = -f;
719 value = -1;
720 while (f < 0.5)
721 {
722 for (i = 1, d = 0.5; d * d >= f; i += i)
723 d *= d;
724 f /= d;
725 value -= i;
726 }
727 while (f >= 1.0)
728 {
729 for (i = 1, d = 2.0; d * d <= f; i += i)
730 d *= d;
731 f /= d;
732 value += i;
733 }
734 #endif
735 #endif
736 }
737 XSETINT (val, value);
738 return val;
739 }
740
741
742 /* the rounding functions */
743
744 static Lisp_Object
745 rounding_driver (Lisp_Object arg, Lisp_Object divisor,
746 double (*double_round) (double),
747 EMACS_INT (*int_round2) (EMACS_INT, EMACS_INT),
748 const char *name)
749 {
750 CHECK_NUMBER_OR_FLOAT (arg);
751
752 if (! NILP (divisor))
753 {
754 EMACS_INT i1, i2;
755
756 CHECK_NUMBER_OR_FLOAT (divisor);
757
758 if (FLOATP (arg) || FLOATP (divisor))
759 {
760 double f1, f2;
761
762 f1 = FLOATP (arg) ? XFLOAT_DATA (arg) : XINT (arg);
763 f2 = (FLOATP (divisor) ? XFLOAT_DATA (divisor) : XINT (divisor));
764 if (! IEEE_FLOATING_POINT && f2 == 0)
765 xsignal0 (Qarith_error);
766
767 IN_FLOAT2 (f1 = (*double_round) (f1 / f2), name, arg, divisor);
768 FLOAT_TO_INT2 (f1, arg, name, arg, divisor);
769 return arg;
770 }
771
772 i1 = XINT (arg);
773 i2 = XINT (divisor);
774
775 if (i2 == 0)
776 xsignal0 (Qarith_error);
777
778 XSETINT (arg, (*int_round2) (i1, i2));
779 return arg;
780 }
781
782 if (FLOATP (arg))
783 {
784 double d;
785
786 IN_FLOAT (d = (*double_round) (XFLOAT_DATA (arg)), name, arg);
787 FLOAT_TO_INT (d, arg, name, arg);
788 }
789
790 return arg;
791 }
792
793 /* With C's /, the result is implementation-defined if either operand
794 is negative, so take care with negative operands in the following
795 integer functions. */
796
797 static EMACS_INT
798 ceiling2 (EMACS_INT i1, EMACS_INT i2)
799 {
800 return (i2 < 0
801 ? (i1 < 0 ? ((-1 - i1) / -i2) + 1 : - (i1 / -i2))
802 : (i1 <= 0 ? - (-i1 / i2) : ((i1 - 1) / i2) + 1));
803 }
804
805 static EMACS_INT
806 floor2 (EMACS_INT i1, EMACS_INT i2)
807 {
808 return (i2 < 0
809 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2))
810 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2));
811 }
812
813 static EMACS_INT
814 truncate2 (EMACS_INT i1, EMACS_INT i2)
815 {
816 return (i2 < 0
817 ? (i1 < 0 ? -i1 / -i2 : - (i1 / -i2))
818 : (i1 < 0 ? - (-i1 / i2) : i1 / i2));
819 }
820
821 static EMACS_INT
822 round2 (EMACS_INT i1, EMACS_INT i2)
823 {
824 /* The C language's division operator gives us one remainder R, but
825 we want the remainder R1 on the other side of 0 if R1 is closer
826 to 0 than R is; because we want to round to even, we also want R1
827 if R and R1 are the same distance from 0 and if C's quotient is
828 odd. */
829 EMACS_INT q = i1 / i2;
830 EMACS_INT r = i1 % i2;
831 EMACS_INT abs_r = r < 0 ? -r : r;
832 EMACS_INT abs_r1 = (i2 < 0 ? -i2 : i2) - abs_r;
833 return q + (abs_r + (q & 1) <= abs_r1 ? 0 : (i2 ^ r) < 0 ? -1 : 1);
834 }
835
836 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
837 if `rint' exists but does not work right. */
838 #ifdef HAVE_RINT
839 #define emacs_rint rint
840 #else
841 static double
842 emacs_rint (double d)
843 {
844 return floor (d + 0.5);
845 }
846 #endif
847
848 static double
849 double_identity (double d)
850 {
851 return d;
852 }
853
854 DEFUN ("ceiling", Fceiling, Sceiling, 1, 2, 0,
855 doc: /* Return the smallest integer no less than ARG.
856 This rounds the value towards +inf.
857 With optional DIVISOR, return the smallest integer no less than ARG/DIVISOR. */)
858 (Lisp_Object arg, Lisp_Object divisor)
859 {
860 return rounding_driver (arg, divisor, ceil, ceiling2, "ceiling");
861 }
862
863 DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
864 doc: /* Return the largest integer no greater than ARG.
865 This rounds the value towards -inf.
866 With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR. */)
867 (Lisp_Object arg, Lisp_Object divisor)
868 {
869 return rounding_driver (arg, divisor, floor, floor2, "floor");
870 }
871
872 DEFUN ("round", Fround, Sround, 1, 2, 0,
873 doc: /* Return the nearest integer to ARG.
874 With optional DIVISOR, return the nearest integer to ARG/DIVISOR.
875
876 Rounding a value equidistant between two integers may choose the
877 integer closer to zero, or it may prefer an even integer, depending on
878 your machine. For example, \(round 2.5\) can return 3 on some
879 systems, but 2 on others. */)
880 (Lisp_Object arg, Lisp_Object divisor)
881 {
882 return rounding_driver (arg, divisor, emacs_rint, round2, "round");
883 }
884
885 DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0,
886 doc: /* Truncate a floating point number to an int.
887 Rounds ARG toward zero.
888 With optional DIVISOR, truncate ARG/DIVISOR. */)
889 (Lisp_Object arg, Lisp_Object divisor)
890 {
891 return rounding_driver (arg, divisor, double_identity, truncate2,
892 "truncate");
893 }
894
895
896 Lisp_Object
897 fmod_float (Lisp_Object x, Lisp_Object y)
898 {
899 double f1, f2;
900
901 f1 = FLOATP (x) ? XFLOAT_DATA (x) : XINT (x);
902 f2 = FLOATP (y) ? XFLOAT_DATA (y) : XINT (y);
903
904 if (! IEEE_FLOATING_POINT && f2 == 0)
905 xsignal0 (Qarith_error);
906
907 /* If the "remainder" comes out with the wrong sign, fix it. */
908 IN_FLOAT2 ((f1 = fmod (f1, f2),
909 f1 = (f2 < 0 ? f1 > 0 : f1 < 0) ? f1 + f2 : f1),
910 "mod", x, y);
911 return make_float (f1);
912 }
913 \f
914 /* It's not clear these are worth adding. */
915
916 DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
917 doc: /* Return the smallest integer no less than ARG, as a float.
918 \(Round toward +inf.\) */)
919 (register Lisp_Object arg)
920 {
921 double d = extract_float (arg);
922 IN_FLOAT (d = ceil (d), "fceiling", arg);
923 return make_float (d);
924 }
925
926 DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
927 doc: /* Return the largest integer no greater than ARG, as a float.
928 \(Round towards -inf.\) */)
929 (register Lisp_Object arg)
930 {
931 double d = extract_float (arg);
932 IN_FLOAT (d = floor (d), "ffloor", arg);
933 return make_float (d);
934 }
935
936 DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
937 doc: /* Return the nearest integer to ARG, as a float. */)
938 (register Lisp_Object arg)
939 {
940 double d = extract_float (arg);
941 IN_FLOAT (d = emacs_rint (d), "fround", arg);
942 return make_float (d);
943 }
944
945 DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
946 doc: /* Truncate a floating point number to an integral float value.
947 Rounds the value toward zero. */)
948 (register Lisp_Object arg)
949 {
950 double d = extract_float (arg);
951 if (d >= 0.0)
952 IN_FLOAT (d = floor (d), "ftruncate", arg);
953 else
954 IN_FLOAT (d = ceil (d), "ftruncate", arg);
955 return make_float (d);
956 }
957 \f
958 #ifdef FLOAT_CATCH_SIGILL
959 static SIGTYPE
960 float_error (signo)
961 int signo;
962 {
963 if (! in_float)
964 fatal_error_signal (signo);
965
966 #ifdef BSD_SYSTEM
967 sigsetmask (SIGEMPTYMASK);
968 #else
969 /* Must reestablish handler each time it is called. */
970 signal (SIGILL, float_error);
971 #endif /* BSD_SYSTEM */
972
973 SIGNAL_THREAD_CHECK (signo);
974 in_float = 0;
975
976 xsignal1 (Qarith_error, float_error_arg);
977 }
978
979 /* Another idea was to replace the library function `infnan'
980 where SIGILL is signaled. */
981
982 #endif /* FLOAT_CATCH_SIGILL */
983
984 #ifdef HAVE_MATHERR
985 int
986 matherr (struct exception *x)
987 {
988 Lisp_Object args;
989 const char *name = x->name;
990
991 if (! in_float)
992 /* Not called from emacs-lisp float routines; do the default thing. */
993 return 0;
994 if (!strcmp (x->name, "pow"))
995 name = "expt";
996
997 args
998 = Fcons (build_string (name),
999 Fcons (make_float (x->arg1),
1000 ((!strcmp (name, "log") || !strcmp (name, "pow"))
1001 ? Fcons (make_float (x->arg2), Qnil)
1002 : Qnil)));
1003 switch (x->type)
1004 {
1005 case DOMAIN: xsignal (Qdomain_error, args); break;
1006 case SING: xsignal (Qsingularity_error, args); break;
1007 case OVERFLOW: xsignal (Qoverflow_error, args); break;
1008 case UNDERFLOW: xsignal (Qunderflow_error, args); break;
1009 default: xsignal (Qarith_error, args); break;
1010 }
1011 return (1); /* don't set errno or print a message */
1012 }
1013 #endif /* HAVE_MATHERR */
1014
1015 void
1016 init_floatfns (void)
1017 {
1018 #ifdef FLOAT_CATCH_SIGILL
1019 signal (SIGILL, float_error);
1020 #endif
1021 in_float = 0;
1022 }
1023
1024 void
1025 syms_of_floatfns (void)
1026 {
1027 defsubr (&Sacos);
1028 defsubr (&Sasin);
1029 defsubr (&Satan);
1030 defsubr (&Scos);
1031 defsubr (&Ssin);
1032 defsubr (&Stan);
1033 #if defined HAVE_ISNAN && defined HAVE_COPYSIGN
1034 defsubr (&Sisnan);
1035 defsubr (&Scopysign);
1036 defsubr (&Sfrexp);
1037 defsubr (&Sldexp);
1038 #endif
1039 #if 0
1040 defsubr (&Sacosh);
1041 defsubr (&Sasinh);
1042 defsubr (&Satanh);
1043 defsubr (&Scosh);
1044 defsubr (&Ssinh);
1045 defsubr (&Stanh);
1046 defsubr (&Sbessel_y0);
1047 defsubr (&Sbessel_y1);
1048 defsubr (&Sbessel_yn);
1049 defsubr (&Sbessel_j0);
1050 defsubr (&Sbessel_j1);
1051 defsubr (&Sbessel_jn);
1052 defsubr (&Serf);
1053 defsubr (&Serfc);
1054 defsubr (&Slog_gamma);
1055 defsubr (&Scube_root);
1056 #endif
1057 defsubr (&Sfceiling);
1058 defsubr (&Sffloor);
1059 defsubr (&Sfround);
1060 defsubr (&Sftruncate);
1061 defsubr (&Sexp);
1062 defsubr (&Sexpt);
1063 defsubr (&Slog);
1064 defsubr (&Slog10);
1065 defsubr (&Ssqrt);
1066
1067 defsubr (&Sabs);
1068 defsubr (&Sfloat);
1069 defsubr (&Slogb);
1070 defsubr (&Sceiling);
1071 defsubr (&Sfloor);
1072 defsubr (&Sround);
1073 defsubr (&Struncate);
1074 }
1075