1 /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
2 Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
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
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* ANSI C requires only these float functions:
23 acos, asin, atan, atan2, ceil, cos, cosh, exp, fabs, floor, fmod,
24 frexp, ldexp, log, log10, modf, pow, sin, sinh, sqrt, tan, tanh.
26 Define HAVE_INVERSE_HYPERBOLIC if you have acosh, asinh, and atanh.
27 Define HAVE_CBRT if you have cbrt.
28 Define HAVE_RINT if you have a working rint.
29 If you don't define these, then the appropriate routines will be simulated.
31 Define HAVE_MATHERR if on a system supporting the SysV matherr callback.
32 (This should happen automatically.)
34 Define FLOAT_CHECK_ERRNO if the float library routines set errno.
35 This has no effect if HAVE_MATHERR is defined.
37 Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL.
38 (What systems actually do this? Please let us know.)
40 Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
41 either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and
42 range checking will happen before calling the float routines. This has
43 no effect if HAVE_MATHERR is defined (since matherr will be called when
44 a domain error occurs.)
51 #include "syssignal.h"
53 #ifdef LISP_FLOAT_TYPE
59 /* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
60 #ifndef IEEE_FLOATING_POINT
61 #if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
62 && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
63 #define IEEE_FLOATING_POINT 1
65 #define IEEE_FLOATING_POINT 0
69 /* Work around a problem that happens because math.h on hpux 7
70 defines two static variables--which, in Emacs, are not really static,
71 because `static' is defined as nothing. The problem is that they are
72 defined both here and in lread.c.
73 These macros prevent the name conflict. */
74 #if defined (HPUX) && !defined (HPUX8)
75 #define _MAXLDBL floatfns_maxldbl
76 #define _NMAXLDBL floatfns_nmaxldbl
81 /* This declaration is omitted on some systems, like Ultrix. */
82 #if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
83 extern double logb ();
84 #endif /* not HPUX and HAVE_LOGB and no logb macro */
86 #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
87 /* If those are defined, then this is probably a `matherr' machine. */
98 # ifdef FLOAT_CHECK_ERRNO
99 # undef FLOAT_CHECK_ERRNO
101 # ifdef FLOAT_CHECK_DOMAIN
102 # undef FLOAT_CHECK_DOMAIN
106 #ifndef NO_FLOAT_CHECK_ERRNO
107 #define FLOAT_CHECK_ERRNO
110 #ifdef FLOAT_CHECK_ERRNO
116 /* Avoid traps on VMS from sinh and cosh.
117 All the other functions set errno instead. */
122 #define cosh(x) ((exp(x)+exp(-x))*0.5)
123 #define sinh(x) ((exp(x)-exp(-x))*0.5)
126 static SIGTYPE
float_error ();
128 /* Nonzero while executing in floating point.
129 This tells float_error what to do. */
133 /* If an argument is out of range for a mathematical function,
134 here is the actual argument value to use in the error message.
135 These variables are used only across the floating point library call
136 so there is no need to staticpro them. */
138 static Lisp_Object float_error_arg
, float_error_arg2
;
140 static char *float_error_fn_name
;
142 /* Evaluate the floating point expression D, recording NUM
143 as the original argument for error messages.
144 D is normally an assignment expression.
145 Handle errors which may result in signals or may set errno.
147 Note that float_error may be declared to return void, so you can't
148 just cast the zero after the colon to (SIGTYPE) to make the types
151 #ifdef FLOAT_CHECK_ERRNO
152 #define IN_FLOAT(d, name, num) \
154 float_error_arg = num; \
155 float_error_fn_name = name; \
156 in_float = 1; errno = 0; (d); in_float = 0; \
159 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
160 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
161 default: arith_error (float_error_fn_name, float_error_arg); \
164 #define IN_FLOAT2(d, name, num, num2) \
166 float_error_arg = num; \
167 float_error_arg2 = num2; \
168 float_error_fn_name = name; \
169 in_float = 1; errno = 0; (d); in_float = 0; \
172 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
173 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
174 default: arith_error (float_error_fn_name, float_error_arg); \
178 #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
179 #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
182 /* Convert float to Lisp_Int if it fits, else signal a range error
183 using the given arguments. */
184 #define FLOAT_TO_INT(x, i, name, num) \
187 if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
188 (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
189 range_error (name, num); \
190 XSETINT (i, (EMACS_INT)(x)); \
193 #define FLOAT_TO_INT2(x, i, name, num1, num2) \
196 if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
197 (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
198 range_error2 (name, num1, num2); \
199 XSETINT (i, (EMACS_INT)(x)); \
203 #define arith_error(op,arg) \
204 Fsignal (Qarith_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
205 #define range_error(op,arg) \
206 Fsignal (Qrange_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
207 #define range_error2(op,a1,a2) \
208 Fsignal (Qrange_error, Fcons (build_string ((op)), \
209 Fcons ((a1), Fcons ((a2), Qnil))))
210 #define domain_error(op,arg) \
211 Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
212 #define domain_error2(op,a1,a2) \
213 Fsignal (Qdomain_error, Fcons (build_string ((op)), \
214 Fcons ((a1), Fcons ((a2), Qnil))))
216 /* Extract a Lisp number as a `double', or signal an error. */
222 CHECK_NUMBER_OR_FLOAT (num
, 0);
225 return XFLOAT (num
)->data
;
226 return (double) XINT (num
);
229 /* Trig functions. */
231 DEFUN ("acos", Facos
, Sacos
, 1, 1, 0,
232 "Return the inverse cosine of ARG.")
234 register Lisp_Object arg
;
236 double d
= extract_float (arg
);
237 #ifdef FLOAT_CHECK_DOMAIN
238 if (d
> 1.0 || d
< -1.0)
239 domain_error ("acos", arg
);
241 IN_FLOAT (d
= acos (d
), "acos", arg
);
242 return make_float (d
);
245 DEFUN ("asin", Fasin
, Sasin
, 1, 1, 0,
246 "Return the inverse sine of ARG.")
248 register Lisp_Object arg
;
250 double d
= extract_float (arg
);
251 #ifdef FLOAT_CHECK_DOMAIN
252 if (d
> 1.0 || d
< -1.0)
253 domain_error ("asin", arg
);
255 IN_FLOAT (d
= asin (d
), "asin", arg
);
256 return make_float (d
);
259 DEFUN ("atan", Fatan
, Satan
, 1, 1, 0,
260 "Return the inverse tangent of ARG.")
262 register Lisp_Object arg
;
264 double d
= extract_float (arg
);
265 IN_FLOAT (d
= atan (d
), "atan", arg
);
266 return make_float (d
);
269 DEFUN ("cos", Fcos
, Scos
, 1, 1, 0,
270 "Return the cosine of ARG.")
272 register Lisp_Object arg
;
274 double d
= extract_float (arg
);
275 IN_FLOAT (d
= cos (d
), "cos", arg
);
276 return make_float (d
);
279 DEFUN ("sin", Fsin
, Ssin
, 1, 1, 0,
280 "Return the sine of ARG.")
282 register Lisp_Object arg
;
284 double d
= extract_float (arg
);
285 IN_FLOAT (d
= sin (d
), "sin", arg
);
286 return make_float (d
);
289 DEFUN ("tan", Ftan
, Stan
, 1, 1, 0,
290 "Return the tangent of ARG.")
292 register Lisp_Object arg
;
294 double d
= extract_float (arg
);
296 #ifdef FLOAT_CHECK_DOMAIN
298 domain_error ("tan", arg
);
300 IN_FLOAT (d
= sin (d
) / c
, "tan", arg
);
301 return make_float (d
);
304 #if 0 /* Leave these out unless we find there's a reason for them. */
306 DEFUN ("bessel-j0", Fbessel_j0
, Sbessel_j0
, 1, 1, 0,
307 "Return the bessel function j0 of ARG.")
309 register Lisp_Object arg
;
311 double d
= extract_float (arg
);
312 IN_FLOAT (d
= j0 (d
), "bessel-j0", arg
);
313 return make_float (d
);
316 DEFUN ("bessel-j1", Fbessel_j1
, Sbessel_j1
, 1, 1, 0,
317 "Return the bessel function j1 of ARG.")
319 register Lisp_Object arg
;
321 double d
= extract_float (arg
);
322 IN_FLOAT (d
= j1 (d
), "bessel-j1", arg
);
323 return make_float (d
);
326 DEFUN ("bessel-jn", Fbessel_jn
, Sbessel_jn
, 2, 2, 0,
327 "Return the order N bessel function output jn of ARG.\n\
328 The first arg (the order) is truncated to an integer.")
330 register Lisp_Object n
, arg
;
332 int i1
= extract_float (n
);
333 double f2
= extract_float (arg
);
335 IN_FLOAT (f2
= jn (i1
, f2
), "bessel-jn", n
);
336 return make_float (f2
);
339 DEFUN ("bessel-y0", Fbessel_y0
, Sbessel_y0
, 1, 1, 0,
340 "Return the bessel function y0 of ARG.")
342 register Lisp_Object arg
;
344 double d
= extract_float (arg
);
345 IN_FLOAT (d
= y0 (d
), "bessel-y0", arg
);
346 return make_float (d
);
349 DEFUN ("bessel-y1", Fbessel_y1
, Sbessel_y1
, 1, 1, 0,
350 "Return the bessel function y1 of ARG.")
352 register Lisp_Object arg
;
354 double d
= extract_float (arg
);
355 IN_FLOAT (d
= y1 (d
), "bessel-y0", arg
);
356 return make_float (d
);
359 DEFUN ("bessel-yn", Fbessel_yn
, Sbessel_yn
, 2, 2, 0,
360 "Return the order N bessel function output yn of ARG.\n\
361 The first arg (the order) is truncated to an integer.")
363 register Lisp_Object n
, arg
;
365 int i1
= extract_float (n
);
366 double f2
= extract_float (arg
);
368 IN_FLOAT (f2
= yn (i1
, f2
), "bessel-yn", n
);
369 return make_float (f2
);
374 #if 0 /* Leave these out unless we see they are worth having. */
376 DEFUN ("erf", Ferf
, Serf
, 1, 1, 0,
377 "Return the mathematical error function of ARG.")
379 register Lisp_Object arg
;
381 double d
= extract_float (arg
);
382 IN_FLOAT (d
= erf (d
), "erf", arg
);
383 return make_float (d
);
386 DEFUN ("erfc", Ferfc
, Serfc
, 1, 1, 0,
387 "Return the complementary error function of ARG.")
389 register Lisp_Object arg
;
391 double d
= extract_float (arg
);
392 IN_FLOAT (d
= erfc (d
), "erfc", arg
);
393 return make_float (d
);
396 DEFUN ("log-gamma", Flog_gamma
, Slog_gamma
, 1, 1, 0,
397 "Return the log gamma of ARG.")
399 register Lisp_Object arg
;
401 double d
= extract_float (arg
);
402 IN_FLOAT (d
= lgamma (d
), "log-gamma", arg
);
403 return make_float (d
);
406 DEFUN ("cube-root", Fcube_root
, Scube_root
, 1, 1, 0,
407 "Return the cube root of ARG.")
409 register Lisp_Object arg
;
411 double d
= extract_float (arg
);
413 IN_FLOAT (d
= cbrt (d
), "cube-root", arg
);
416 IN_FLOAT (d
= pow (d
, 1.0/3.0), "cube-root", arg
);
418 IN_FLOAT (d
= -pow (-d
, 1.0/3.0), "cube-root", arg
);
420 return make_float (d
);
425 DEFUN ("exp", Fexp
, Sexp
, 1, 1, 0,
426 "Return the exponential base e of ARG.")
428 register Lisp_Object arg
;
430 double d
= extract_float (arg
);
431 #ifdef FLOAT_CHECK_DOMAIN
432 if (d
> 709.7827) /* Assume IEEE doubles here */
433 range_error ("exp", arg
);
435 return make_float (0.0);
438 IN_FLOAT (d
= exp (d
), "exp", arg
);
439 return make_float (d
);
442 DEFUN ("expt", Fexpt
, Sexpt
, 2, 2, 0,
443 "Return the exponential ARG1 ** ARG2.")
445 register Lisp_Object arg1
, arg2
;
449 CHECK_NUMBER_OR_FLOAT (arg1
, 0);
450 CHECK_NUMBER_OR_FLOAT (arg2
, 0);
451 if (INTEGERP (arg1
) /* common lisp spec */
452 && INTEGERP (arg2
)) /* don't promote, if both are ints */
453 { /* this can be improved by pre-calculating */
454 EMACS_INT acc
, x
, y
; /* some binary powers of x then accumulating */
466 acc
= (y
& 1) ? -1 : 1;
477 y
= (unsigned)y
>> 1;
483 f1
= FLOATP (arg1
) ? XFLOAT (arg1
)->data
: XINT (arg1
);
484 f2
= FLOATP (arg2
) ? XFLOAT (arg2
)->data
: XINT (arg2
);
485 /* Really should check for overflow, too */
486 if (f1
== 0.0 && f2
== 0.0)
488 #ifdef FLOAT_CHECK_DOMAIN
489 else if ((f1
== 0.0 && f2
< 0.0) || (f1
< 0 && f2
!= floor(f2
)))
490 domain_error2 ("expt", arg1
, arg2
);
492 IN_FLOAT2 (f1
= pow (f1
, f2
), "expt", arg1
, arg2
);
493 return make_float (f1
);
496 DEFUN ("log", Flog
, Slog
, 1, 2, 0,
497 "Return the natural logarithm of ARG.\n\
498 If second optional argument BASE is given, return log ARG using that base.")
500 register Lisp_Object arg
, base
;
502 double d
= extract_float (arg
);
504 #ifdef FLOAT_CHECK_DOMAIN
506 domain_error2 ("log", arg
, base
);
509 IN_FLOAT (d
= log (d
), "log", arg
);
512 double b
= extract_float (base
);
514 #ifdef FLOAT_CHECK_DOMAIN
515 if (b
<= 0.0 || b
== 1.0)
516 domain_error2 ("log", arg
, base
);
519 IN_FLOAT2 (d
= log10 (d
), "log", arg
, base
);
521 IN_FLOAT2 (d
= log (d
) / log (b
), "log", arg
, base
);
523 return make_float (d
);
526 DEFUN ("log10", Flog10
, Slog10
, 1, 1, 0,
527 "Return the logarithm base 10 of ARG.")
529 register Lisp_Object arg
;
531 double d
= extract_float (arg
);
532 #ifdef FLOAT_CHECK_DOMAIN
534 domain_error ("log10", arg
);
536 IN_FLOAT (d
= log10 (d
), "log10", arg
);
537 return make_float (d
);
540 DEFUN ("sqrt", Fsqrt
, Ssqrt
, 1, 1, 0,
541 "Return the square root of ARG.")
543 register Lisp_Object arg
;
545 double d
= extract_float (arg
);
546 #ifdef FLOAT_CHECK_DOMAIN
548 domain_error ("sqrt", arg
);
550 IN_FLOAT (d
= sqrt (d
), "sqrt", arg
);
551 return make_float (d
);
554 #if 0 /* Not clearly worth adding. */
556 DEFUN ("acosh", Facosh
, Sacosh
, 1, 1, 0,
557 "Return the inverse hyperbolic cosine of ARG.")
559 register Lisp_Object arg
;
561 double d
= extract_float (arg
);
562 #ifdef FLOAT_CHECK_DOMAIN
564 domain_error ("acosh", arg
);
566 #ifdef HAVE_INVERSE_HYPERBOLIC
567 IN_FLOAT (d
= acosh (d
), "acosh", arg
);
569 IN_FLOAT (d
= log (d
+ sqrt (d
*d
- 1.0)), "acosh", arg
);
571 return make_float (d
);
574 DEFUN ("asinh", Fasinh
, Sasinh
, 1, 1, 0,
575 "Return the inverse hyperbolic sine of ARG.")
577 register Lisp_Object arg
;
579 double d
= extract_float (arg
);
580 #ifdef HAVE_INVERSE_HYPERBOLIC
581 IN_FLOAT (d
= asinh (d
), "asinh", arg
);
583 IN_FLOAT (d
= log (d
+ sqrt (d
*d
+ 1.0)), "asinh", arg
);
585 return make_float (d
);
588 DEFUN ("atanh", Fatanh
, Satanh
, 1, 1, 0,
589 "Return the inverse hyperbolic tangent of ARG.")
591 register Lisp_Object arg
;
593 double d
= extract_float (arg
);
594 #ifdef FLOAT_CHECK_DOMAIN
595 if (d
>= 1.0 || d
<= -1.0)
596 domain_error ("atanh", arg
);
598 #ifdef HAVE_INVERSE_HYPERBOLIC
599 IN_FLOAT (d
= atanh (d
), "atanh", arg
);
601 IN_FLOAT (d
= 0.5 * log ((1.0 + d
) / (1.0 - d
)), "atanh", arg
);
603 return make_float (d
);
606 DEFUN ("cosh", Fcosh
, Scosh
, 1, 1, 0,
607 "Return the hyperbolic cosine of ARG.")
609 register Lisp_Object arg
;
611 double d
= extract_float (arg
);
612 #ifdef FLOAT_CHECK_DOMAIN
613 if (d
> 710.0 || d
< -710.0)
614 range_error ("cosh", arg
);
616 IN_FLOAT (d
= cosh (d
), "cosh", arg
);
617 return make_float (d
);
620 DEFUN ("sinh", Fsinh
, Ssinh
, 1, 1, 0,
621 "Return the hyperbolic sine of ARG.")
623 register Lisp_Object arg
;
625 double d
= extract_float (arg
);
626 #ifdef FLOAT_CHECK_DOMAIN
627 if (d
> 710.0 || d
< -710.0)
628 range_error ("sinh", arg
);
630 IN_FLOAT (d
= sinh (d
), "sinh", arg
);
631 return make_float (d
);
634 DEFUN ("tanh", Ftanh
, Stanh
, 1, 1, 0,
635 "Return the hyperbolic tangent of ARG.")
637 register Lisp_Object arg
;
639 double d
= extract_float (arg
);
640 IN_FLOAT (d
= tanh (d
), "tanh", arg
);
641 return make_float (d
);
645 DEFUN ("abs", Fabs
, Sabs
, 1, 1, 0,
646 "Return the absolute value of ARG.")
648 register Lisp_Object arg
;
650 CHECK_NUMBER_OR_FLOAT (arg
, 0);
653 IN_FLOAT (arg
= make_float (fabs (XFLOAT (arg
)->data
)), "abs", arg
);
654 else if (XINT (arg
) < 0)
655 XSETINT (arg
, - XINT (arg
));
660 DEFUN ("float", Ffloat
, Sfloat
, 1, 1, 0,
661 "Return the floating point number equal to ARG.")
663 register Lisp_Object arg
;
665 CHECK_NUMBER_OR_FLOAT (arg
, 0);
668 return make_float ((double) XINT (arg
));
669 else /* give 'em the same float back */
673 DEFUN ("logb", Flogb
, Slogb
, 1, 1, 0,
674 "Returns largest integer <= the base 2 log of the magnitude of ARG.\n\
675 This is the same as the exponent of a float.")
681 double f
= extract_float (arg
);
684 value
= -(VALMASK
>> 1);
688 IN_FLOAT (value
= logb (f
), "logb", arg
);
692 IN_FLOAT (frexp (f
, &ivalue
), "logb", arg
);
702 for (i
= 1, d
= 0.5; d
* d
>= f
; i
+= i
)
709 for (i
= 1, d
= 2.0; d
* d
<= f
; i
+= i
)
717 XSETINT (val
, value
);
721 #endif /* LISP_FLOAT_TYPE */
724 /* the rounding functions */
727 rounding_driver (arg
, divisor
, double_round
, int_round2
, name
)
728 register Lisp_Object arg
, divisor
;
729 double (*double_round
) ();
730 EMACS_INT (*int_round2
) ();
733 CHECK_NUMBER_OR_FLOAT (arg
, 0);
735 if (! NILP (divisor
))
739 CHECK_NUMBER_OR_FLOAT (divisor
, 1);
741 #ifdef LISP_FLOAT_TYPE
742 if (FLOATP (arg
) || FLOATP (divisor
))
746 f1
= FLOATP (arg
) ? XFLOAT (arg
)->data
: XINT (arg
);
747 f2
= (FLOATP (divisor
) ? XFLOAT (divisor
)->data
: XINT (divisor
));
748 if (! IEEE_FLOATING_POINT
&& f2
== 0)
749 Fsignal (Qarith_error
, Qnil
);
751 IN_FLOAT2 (f1
= (*double_round
) (f1
/ f2
), name
, arg
, divisor
);
752 FLOAT_TO_INT2 (f1
, arg
, name
, arg
, divisor
);
761 Fsignal (Qarith_error
, Qnil
);
763 XSETINT (arg
, (*int_round2
) (i1
, i2
));
767 #ifdef LISP_FLOAT_TYPE
772 IN_FLOAT (d
= (*double_round
) (XFLOAT (arg
)->data
), name
, arg
);
773 FLOAT_TO_INT (d
, arg
, name
, arg
);
780 /* With C's /, the result is implementation-defined if either operand
781 is negative, so take care with negative operands in the following
782 integer functions. */
789 ? (i1
< 0 ? ((-1 - i1
) / -i2
) + 1 : - (i1
/ -i2
))
790 : (i1
<= 0 ? - (-i1
/ i2
) : ((i1
- 1) / i2
) + 1));
798 ? (i1
<= 0 ? -i1
/ -i2
: -1 - ((i1
- 1) / -i2
))
799 : (i1
< 0 ? -1 - ((-1 - i1
) / i2
) : i1
/ i2
));
807 ? (i1
< 0 ? -i1
/ -i2
: - (i1
/ -i2
))
808 : (i1
< 0 ? - (-i1
/ i2
) : i1
/ i2
));
815 /* The C language's division operator gives us one remainder R, but
816 we want the remainder R1 on the other side of 0 if R1 is closer
817 to 0 than R is; because we want to round to even, we also want R1
818 if R and R1 are the same distance from 0 and if C's quotient is
820 EMACS_INT q
= i1
/ i2
;
821 EMACS_INT r
= i1
% i2
;
822 EMACS_INT abs_r
= r
< 0 ? -r
: r
;
823 EMACS_INT abs_r1
= (i2
< 0 ? -i2
: i2
) - abs_r
;
824 return q
+ (abs_r
+ (q
& 1) <= abs_r1
? 0 : (i2
^ r
) < 0 ? -1 : 1);
827 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
828 if `rint' exists but does not work right. */
830 #define emacs_rint rint
836 return floor (d
+ 0.5);
847 DEFUN ("ceiling", Fceiling
, Sceiling
, 1, 2, 0,
848 "Return the smallest integer no less than ARG. (Round toward +inf.)\n\
849 With optional DIVISOR, return the smallest integer no less than ARG/DIVISOR.")
851 Lisp_Object arg
, divisor
;
853 return rounding_driver (arg
, divisor
, ceil
, ceiling2
, "ceiling");
856 DEFUN ("floor", Ffloor
, Sfloor
, 1, 2, 0,
857 "Return the largest integer no greater than ARG. (Round towards -inf.)\n\
858 With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR.")
860 Lisp_Object arg
, divisor
;
862 return rounding_driver (arg
, divisor
, floor
, floor2
, "floor");
865 DEFUN ("round", Fround
, Sround
, 1, 2, 0,
866 "Return the nearest integer to ARG.\n\
867 With optional DIVISOR, return the nearest integer to ARG/DIVISOR.")
869 Lisp_Object arg
, divisor
;
871 return rounding_driver (arg
, divisor
, emacs_rint
, round2
, "round");
874 DEFUN ("truncate", Ftruncate
, Struncate
, 1, 2, 0,
875 "Truncate a floating point number to an int.\n\
876 Rounds ARG toward zero.\n\
877 With optional DIVISOR, truncate ARG/DIVISOR.")
879 Lisp_Object arg
, divisor
;
881 return rounding_driver (arg
, divisor
, double_identity
, truncate2
,
885 #ifdef LISP_FLOAT_TYPE
889 register Lisp_Object x
, y
;
893 f1
= FLOATP (x
) ? XFLOAT (x
)->data
: XINT (x
);
894 f2
= FLOATP (y
) ? XFLOAT (y
)->data
: XINT (y
);
896 if (! IEEE_FLOATING_POINT
&& f2
== 0)
897 Fsignal (Qarith_error
, Qnil
);
899 /* If the "remainder" comes out with the wrong sign, fix it. */
900 IN_FLOAT2 ((f1
= fmod (f1
, f2
),
901 f1
= (f2
< 0 ? f1
> 0 : f1
< 0) ? f1
+ f2
: f1
),
903 return make_float (f1
);
906 /* It's not clear these are worth adding. */
908 DEFUN ("fceiling", Ffceiling
, Sfceiling
, 1, 1, 0,
909 "Return the smallest integer no less than ARG, as a float.\n\
910 \(Round toward +inf.\)")
912 register Lisp_Object arg
;
914 double d
= extract_float (arg
);
915 IN_FLOAT (d
= ceil (d
), "fceiling", arg
);
916 return make_float (d
);
919 DEFUN ("ffloor", Fffloor
, Sffloor
, 1, 1, 0,
920 "Return the largest integer no greater than ARG, as a float.\n\
921 \(Round towards -inf.\)")
923 register Lisp_Object arg
;
925 double d
= extract_float (arg
);
926 IN_FLOAT (d
= floor (d
), "ffloor", arg
);
927 return make_float (d
);
930 DEFUN ("fround", Ffround
, Sfround
, 1, 1, 0,
931 "Return the nearest integer to ARG, as a float.")
933 register Lisp_Object arg
;
935 double d
= extract_float (arg
);
936 IN_FLOAT (d
= emacs_rint (d
), "fround", arg
);
937 return make_float (d
);
940 DEFUN ("ftruncate", Fftruncate
, Sftruncate
, 1, 1, 0,
941 "Truncate a floating point number to an integral float value.\n\
942 Rounds the value toward zero.")
944 register Lisp_Object arg
;
946 double d
= extract_float (arg
);
948 IN_FLOAT (d
= floor (d
), "ftruncate", arg
);
950 IN_FLOAT (d
= ceil (d
), "ftruncate", arg
);
951 return make_float (d
);
954 #ifdef FLOAT_CATCH_SIGILL
960 fatal_error_signal (signo
);
965 #else /* not BSD4_1 */
966 sigsetmask (SIGEMPTYMASK
);
967 #endif /* not BSD4_1 */
969 /* Must reestablish handler each time it is called. */
970 signal (SIGILL
, float_error
);
971 #endif /* BSD_SYSTEM */
975 Fsignal (Qarith_error
, Fcons (float_error_arg
, Qnil
));
978 /* Another idea was to replace the library function `infnan'
979 where SIGILL is signaled. */
981 #endif /* FLOAT_CATCH_SIGILL */
990 /* Not called from emacs-lisp float routines; do the default thing. */
992 if (!strcmp (x
->name
, "pow"))
996 = Fcons (build_string (x
->name
),
997 Fcons (make_float (x
->arg1
),
998 ((!strcmp (x
->name
, "log") || !strcmp (x
->name
, "pow"))
999 ? Fcons (make_float (x
->arg2
), Qnil
)
1003 case DOMAIN
: Fsignal (Qdomain_error
, args
); break;
1004 case SING
: Fsignal (Qsingularity_error
, args
); break;
1005 case OVERFLOW
: Fsignal (Qoverflow_error
, args
); break;
1006 case UNDERFLOW
: Fsignal (Qunderflow_error
, args
); break;
1007 default: Fsignal (Qarith_error
, args
); break;
1009 return (1); /* don't set errno or print a message */
1011 #endif /* HAVE_MATHERR */
1016 #ifdef FLOAT_CATCH_SIGILL
1017 signal (SIGILL
, float_error
);
1022 #else /* not LISP_FLOAT_TYPE */
1027 #endif /* not LISP_FLOAT_TYPE */
1032 #ifdef LISP_FLOAT_TYPE
1046 defsubr (&Sbessel_y0
);
1047 defsubr (&Sbessel_y1
);
1048 defsubr (&Sbessel_yn
);
1049 defsubr (&Sbessel_j0
);
1050 defsubr (&Sbessel_j1
);
1051 defsubr (&Sbessel_jn
);
1054 defsubr (&Slog_gamma
);
1055 defsubr (&Scube_root
);
1057 defsubr (&Sfceiling
);
1060 defsubr (&Sftruncate
);
1070 #endif /* LISP_FLOAT_TYPE */
1071 defsubr (&Sceiling
);
1074 defsubr (&Struncate
);