Rename uniquify-fix-list-* to uniquify-fix-item-*.
[emacs.git] / src / floatfns.c
blob6c8aece417d143ad9b1e3de79272bf2c18b246ca
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)
9 any later version.
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.)
47 #include <signal.h>
49 #include <config.h>
51 /* Put this before lisp.h so that lisp.h can define DBL_DIG if not defined. */
52 #if STDC_HEADERS
53 #include <float.h>
54 #endif
56 #include "lisp.h"
57 #include "syssignal.h"
59 #ifdef LISP_FLOAT_TYPE
61 /* If IEEE_FLOATING_POINT isn't defined, default it from FLT_*. */
62 #ifndef IEEE_FLOATING_POINT
63 #if (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
64 && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
65 #define IEEE_FLOATING_POINT 1
66 #else
67 #define IEEE_FLOATING_POINT 0
68 #endif
69 #endif
71 /* Work around a problem that happens because math.h on hpux 7
72 defines two static variables--which, in Emacs, are not really static,
73 because `static' is defined as nothing. The problem is that they are
74 defined both here and in lread.c.
75 These macros prevent the name conflict. */
76 #if defined (HPUX) && !defined (HPUX8)
77 #define _MAXLDBL floatfns_maxldbl
78 #define _NMAXLDBL floatfns_nmaxldbl
79 #endif
81 #include <math.h>
83 /* This declaration is omitted on some systems, like Ultrix. */
84 #if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
85 extern double logb ();
86 #endif /* not HPUX and HAVE_LOGB and no logb macro */
88 #if defined(DOMAIN) && defined(SING) && defined(OVERFLOW)
89 /* If those are defined, then this is probably a `matherr' machine. */
90 # ifndef HAVE_MATHERR
91 # define HAVE_MATHERR
92 # endif
93 #endif
95 #ifdef NO_MATHERR
96 #undef HAVE_MATHERR
97 #endif
99 #ifdef HAVE_MATHERR
100 # ifdef FLOAT_CHECK_ERRNO
101 # undef FLOAT_CHECK_ERRNO
102 # endif
103 # ifdef FLOAT_CHECK_DOMAIN
104 # undef FLOAT_CHECK_DOMAIN
105 # endif
106 #endif
108 #ifndef NO_FLOAT_CHECK_ERRNO
109 #define FLOAT_CHECK_ERRNO
110 #endif
112 #ifdef FLOAT_CHECK_ERRNO
113 # include <errno.h>
115 extern int errno;
116 #endif
118 /* Avoid traps on VMS from sinh and cosh.
119 All the other functions set errno instead. */
121 #ifdef VMS
122 #undef cosh
123 #undef sinh
124 #define cosh(x) ((exp(x)+exp(-x))*0.5)
125 #define sinh(x) ((exp(x)-exp(-x))*0.5)
126 #endif /* VMS */
128 static SIGTYPE float_error ();
130 /* Nonzero while executing in floating point.
131 This tells float_error what to do. */
133 static int in_float;
135 /* If an argument is out of range for a mathematical function,
136 here is the actual argument value to use in the error message.
137 These variables are used only across the floating point library call
138 so there is no need to staticpro them. */
140 static Lisp_Object float_error_arg, float_error_arg2;
142 static char *float_error_fn_name;
144 /* Evaluate the floating point expression D, recording NUM
145 as the original argument for error messages.
146 D is normally an assignment expression.
147 Handle errors which may result in signals or may set errno.
149 Note that float_error may be declared to return void, so you can't
150 just cast the zero after the colon to (SIGTYPE) to make the types
151 check properly. */
153 #ifdef FLOAT_CHECK_ERRNO
154 #define IN_FLOAT(d, name, num) \
155 do { \
156 float_error_arg = num; \
157 float_error_fn_name = name; \
158 in_float = 1; errno = 0; (d); in_float = 0; \
159 switch (errno) { \
160 case 0: break; \
161 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
162 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
163 default: arith_error (float_error_fn_name, float_error_arg); \
165 } while (0)
166 #define IN_FLOAT2(d, name, num, num2) \
167 do { \
168 float_error_arg = num; \
169 float_error_arg2 = num2; \
170 float_error_fn_name = name; \
171 in_float = 1; errno = 0; (d); in_float = 0; \
172 switch (errno) { \
173 case 0: break; \
174 case EDOM: domain_error (float_error_fn_name, float_error_arg); \
175 case ERANGE: range_error (float_error_fn_name, float_error_arg); \
176 default: arith_error (float_error_fn_name, float_error_arg); \
178 } while (0)
179 #else
180 #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
181 #define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
182 #endif
184 /* Convert float to Lisp_Int if it fits, else signal a range error
185 using the given arguments. */
186 #define FLOAT_TO_INT(x, i, name, num) \
187 do \
189 if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
190 (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
191 range_error (name, num); \
192 XSETINT (i, (EMACS_INT)(x)); \
194 while (0)
195 #define FLOAT_TO_INT2(x, i, name, num1, num2) \
196 do \
198 if ((x) >= (((EMACS_INT) 1) << (VALBITS-1)) || \
199 (x) <= - (((EMACS_INT) 1) << (VALBITS-1)) - 1) \
200 range_error2 (name, num1, num2); \
201 XSETINT (i, (EMACS_INT)(x)); \
203 while (0)
205 #define arith_error(op,arg) \
206 Fsignal (Qarith_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
207 #define range_error(op,arg) \
208 Fsignal (Qrange_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
209 #define range_error2(op,a1,a2) \
210 Fsignal (Qrange_error, Fcons (build_string ((op)), \
211 Fcons ((a1), Fcons ((a2), Qnil))))
212 #define domain_error(op,arg) \
213 Fsignal (Qdomain_error, Fcons (build_string ((op)), Fcons ((arg), Qnil)))
214 #define domain_error2(op,a1,a2) \
215 Fsignal (Qdomain_error, Fcons (build_string ((op)), \
216 Fcons ((a1), Fcons ((a2), Qnil))))
218 /* Extract a Lisp number as a `double', or signal an error. */
220 double
221 extract_float (num)
222 Lisp_Object num;
224 CHECK_NUMBER_OR_FLOAT (num, 0);
226 if (FLOATP (num))
227 return XFLOAT (num)->data;
228 return (double) XINT (num);
231 /* Trig functions. */
233 DEFUN ("acos", Facos, Sacos, 1, 1, 0,
234 "Return the inverse cosine of ARG.")
235 (arg)
236 register Lisp_Object arg;
238 double d = extract_float (arg);
239 #ifdef FLOAT_CHECK_DOMAIN
240 if (d > 1.0 || d < -1.0)
241 domain_error ("acos", arg);
242 #endif
243 IN_FLOAT (d = acos (d), "acos", arg);
244 return make_float (d);
247 DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
248 "Return the inverse sine of ARG.")
249 (arg)
250 register Lisp_Object arg;
252 double d = extract_float (arg);
253 #ifdef FLOAT_CHECK_DOMAIN
254 if (d > 1.0 || d < -1.0)
255 domain_error ("asin", arg);
256 #endif
257 IN_FLOAT (d = asin (d), "asin", arg);
258 return make_float (d);
261 DEFUN ("atan", Fatan, Satan, 1, 1, 0,
262 "Return the inverse tangent of ARG.")
263 (arg)
264 register Lisp_Object arg;
266 double d = extract_float (arg);
267 IN_FLOAT (d = atan (d), "atan", arg);
268 return make_float (d);
271 DEFUN ("cos", Fcos, Scos, 1, 1, 0,
272 "Return the cosine of ARG.")
273 (arg)
274 register Lisp_Object arg;
276 double d = extract_float (arg);
277 IN_FLOAT (d = cos (d), "cos", arg);
278 return make_float (d);
281 DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
282 "Return the sine of ARG.")
283 (arg)
284 register Lisp_Object arg;
286 double d = extract_float (arg);
287 IN_FLOAT (d = sin (d), "sin", arg);
288 return make_float (d);
291 DEFUN ("tan", Ftan, Stan, 1, 1, 0,
292 "Return the tangent of ARG.")
293 (arg)
294 register Lisp_Object arg;
296 double d = extract_float (arg);
297 double c = cos (d);
298 #ifdef FLOAT_CHECK_DOMAIN
299 if (c == 0.0)
300 domain_error ("tan", arg);
301 #endif
302 IN_FLOAT (d = sin (d) / c, "tan", arg);
303 return make_float (d);
306 #if 0 /* Leave these out unless we find there's a reason for them. */
308 DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
309 "Return the bessel function j0 of ARG.")
310 (arg)
311 register Lisp_Object arg;
313 double d = extract_float (arg);
314 IN_FLOAT (d = j0 (d), "bessel-j0", arg);
315 return make_float (d);
318 DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
319 "Return the bessel function j1 of ARG.")
320 (arg)
321 register Lisp_Object arg;
323 double d = extract_float (arg);
324 IN_FLOAT (d = j1 (d), "bessel-j1", arg);
325 return make_float (d);
328 DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
329 "Return the order N bessel function output jn of ARG.\n\
330 The first arg (the order) is truncated to an integer.")
331 (n, arg)
332 register Lisp_Object n, arg;
334 int i1 = extract_float (n);
335 double f2 = extract_float (arg);
337 IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
338 return make_float (f2);
341 DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
342 "Return the bessel function y0 of ARG.")
343 (arg)
344 register Lisp_Object arg;
346 double d = extract_float (arg);
347 IN_FLOAT (d = y0 (d), "bessel-y0", arg);
348 return make_float (d);
351 DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
352 "Return the bessel function y1 of ARG.")
353 (arg)
354 register Lisp_Object arg;
356 double d = extract_float (arg);
357 IN_FLOAT (d = y1 (d), "bessel-y0", arg);
358 return make_float (d);
361 DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
362 "Return the order N bessel function output yn of ARG.\n\
363 The first arg (the order) is truncated to an integer.")
364 (n, arg)
365 register Lisp_Object n, arg;
367 int i1 = extract_float (n);
368 double f2 = extract_float (arg);
370 IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
371 return make_float (f2);
374 #endif
376 #if 0 /* Leave these out unless we see they are worth having. */
378 DEFUN ("erf", Ferf, Serf, 1, 1, 0,
379 "Return the mathematical error function of ARG.")
380 (arg)
381 register Lisp_Object arg;
383 double d = extract_float (arg);
384 IN_FLOAT (d = erf (d), "erf", arg);
385 return make_float (d);
388 DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
389 "Return the complementary error function of ARG.")
390 (arg)
391 register Lisp_Object arg;
393 double d = extract_float (arg);
394 IN_FLOAT (d = erfc (d), "erfc", arg);
395 return make_float (d);
398 DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
399 "Return the log gamma of ARG.")
400 (arg)
401 register Lisp_Object arg;
403 double d = extract_float (arg);
404 IN_FLOAT (d = lgamma (d), "log-gamma", arg);
405 return make_float (d);
408 DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
409 "Return the cube root of ARG.")
410 (arg)
411 register Lisp_Object arg;
413 double d = extract_float (arg);
414 #ifdef HAVE_CBRT
415 IN_FLOAT (d = cbrt (d), "cube-root", arg);
416 #else
417 if (d >= 0.0)
418 IN_FLOAT (d = pow (d, 1.0/3.0), "cube-root", arg);
419 else
420 IN_FLOAT (d = -pow (-d, 1.0/3.0), "cube-root", arg);
421 #endif
422 return make_float (d);
425 #endif
427 DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
428 "Return the exponential base e of ARG.")
429 (arg)
430 register Lisp_Object arg;
432 double d = extract_float (arg);
433 #ifdef FLOAT_CHECK_DOMAIN
434 if (d > 709.7827) /* Assume IEEE doubles here */
435 range_error ("exp", arg);
436 else if (d < -709.0)
437 return make_float (0.0);
438 else
439 #endif
440 IN_FLOAT (d = exp (d), "exp", arg);
441 return make_float (d);
444 DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
445 "Return the exponential ARG1 ** ARG2.")
446 (arg1, arg2)
447 register Lisp_Object arg1, arg2;
449 double f1, f2;
451 CHECK_NUMBER_OR_FLOAT (arg1, 0);
452 CHECK_NUMBER_OR_FLOAT (arg2, 0);
453 if (INTEGERP (arg1) /* common lisp spec */
454 && INTEGERP (arg2)) /* don't promote, if both are ints */
455 { /* this can be improved by pre-calculating */
456 EMACS_INT acc, x, y; /* some binary powers of x then accumulating */
457 Lisp_Object val;
459 x = XINT (arg1);
460 y = XINT (arg2);
461 acc = 1;
463 if (y < 0)
465 if (x == 1)
466 acc = 1;
467 else if (x == -1)
468 acc = (y & 1) ? -1 : 1;
469 else
470 acc = 0;
472 else
474 while (y > 0)
476 if (y & 1)
477 acc *= x;
478 x *= x;
479 y = (unsigned)y >> 1;
482 XSETINT (val, acc);
483 return val;
485 f1 = FLOATP (arg1) ? XFLOAT (arg1)->data : XINT (arg1);
486 f2 = FLOATP (arg2) ? XFLOAT (arg2)->data : XINT (arg2);
487 /* Really should check for overflow, too */
488 if (f1 == 0.0 && f2 == 0.0)
489 f1 = 1.0;
490 #ifdef FLOAT_CHECK_DOMAIN
491 else if ((f1 == 0.0 && f2 < 0.0) || (f1 < 0 && f2 != floor(f2)))
492 domain_error2 ("expt", arg1, arg2);
493 #endif
494 IN_FLOAT2 (f1 = pow (f1, f2), "expt", arg1, arg2);
495 return make_float (f1);
498 DEFUN ("log", Flog, Slog, 1, 2, 0,
499 "Return the natural logarithm of ARG.\n\
500 If second optional argument BASE is given, return log ARG using that base.")
501 (arg, base)
502 register Lisp_Object arg, base;
504 double d = extract_float (arg);
506 #ifdef FLOAT_CHECK_DOMAIN
507 if (d <= 0.0)
508 domain_error2 ("log", arg, base);
509 #endif
510 if (NILP (base))
511 IN_FLOAT (d = log (d), "log", arg);
512 else
514 double b = extract_float (base);
516 #ifdef FLOAT_CHECK_DOMAIN
517 if (b <= 0.0 || b == 1.0)
518 domain_error2 ("log", arg, base);
519 #endif
520 if (b == 10.0)
521 IN_FLOAT2 (d = log10 (d), "log", arg, base);
522 else
523 IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
525 return make_float (d);
528 DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
529 "Return the logarithm base 10 of ARG.")
530 (arg)
531 register Lisp_Object arg;
533 double d = extract_float (arg);
534 #ifdef FLOAT_CHECK_DOMAIN
535 if (d <= 0.0)
536 domain_error ("log10", arg);
537 #endif
538 IN_FLOAT (d = log10 (d), "log10", arg);
539 return make_float (d);
542 DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
543 "Return the square root of ARG.")
544 (arg)
545 register Lisp_Object arg;
547 double d = extract_float (arg);
548 #ifdef FLOAT_CHECK_DOMAIN
549 if (d < 0.0)
550 domain_error ("sqrt", arg);
551 #endif
552 IN_FLOAT (d = sqrt (d), "sqrt", arg);
553 return make_float (d);
556 #if 0 /* Not clearly worth adding. */
558 DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
559 "Return the inverse hyperbolic cosine of ARG.")
560 (arg)
561 register Lisp_Object arg;
563 double d = extract_float (arg);
564 #ifdef FLOAT_CHECK_DOMAIN
565 if (d < 1.0)
566 domain_error ("acosh", arg);
567 #endif
568 #ifdef HAVE_INVERSE_HYPERBOLIC
569 IN_FLOAT (d = acosh (d), "acosh", arg);
570 #else
571 IN_FLOAT (d = log (d + sqrt (d*d - 1.0)), "acosh", arg);
572 #endif
573 return make_float (d);
576 DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
577 "Return the inverse hyperbolic sine of ARG.")
578 (arg)
579 register Lisp_Object arg;
581 double d = extract_float (arg);
582 #ifdef HAVE_INVERSE_HYPERBOLIC
583 IN_FLOAT (d = asinh (d), "asinh", arg);
584 #else
585 IN_FLOAT (d = log (d + sqrt (d*d + 1.0)), "asinh", arg);
586 #endif
587 return make_float (d);
590 DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
591 "Return the inverse hyperbolic tangent of ARG.")
592 (arg)
593 register Lisp_Object arg;
595 double d = extract_float (arg);
596 #ifdef FLOAT_CHECK_DOMAIN
597 if (d >= 1.0 || d <= -1.0)
598 domain_error ("atanh", arg);
599 #endif
600 #ifdef HAVE_INVERSE_HYPERBOLIC
601 IN_FLOAT (d = atanh (d), "atanh", arg);
602 #else
603 IN_FLOAT (d = 0.5 * log ((1.0 + d) / (1.0 - d)), "atanh", arg);
604 #endif
605 return make_float (d);
608 DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
609 "Return the hyperbolic cosine of ARG.")
610 (arg)
611 register Lisp_Object arg;
613 double d = extract_float (arg);
614 #ifdef FLOAT_CHECK_DOMAIN
615 if (d > 710.0 || d < -710.0)
616 range_error ("cosh", arg);
617 #endif
618 IN_FLOAT (d = cosh (d), "cosh", arg);
619 return make_float (d);
622 DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
623 "Return the hyperbolic sine of ARG.")
624 (arg)
625 register Lisp_Object arg;
627 double d = extract_float (arg);
628 #ifdef FLOAT_CHECK_DOMAIN
629 if (d > 710.0 || d < -710.0)
630 range_error ("sinh", arg);
631 #endif
632 IN_FLOAT (d = sinh (d), "sinh", arg);
633 return make_float (d);
636 DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
637 "Return the hyperbolic tangent of ARG.")
638 (arg)
639 register Lisp_Object arg;
641 double d = extract_float (arg);
642 IN_FLOAT (d = tanh (d), "tanh", arg);
643 return make_float (d);
645 #endif
647 DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
648 "Return the absolute value of ARG.")
649 (arg)
650 register Lisp_Object arg;
652 CHECK_NUMBER_OR_FLOAT (arg, 0);
654 if (FLOATP (arg))
655 IN_FLOAT (arg = make_float (fabs (XFLOAT (arg)->data)), "abs", arg);
656 else if (XINT (arg) < 0)
657 XSETINT (arg, - XINT (arg));
659 return arg;
662 DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
663 "Return the floating point number equal to ARG.")
664 (arg)
665 register Lisp_Object arg;
667 CHECK_NUMBER_OR_FLOAT (arg, 0);
669 if (INTEGERP (arg))
670 return make_float ((double) XINT (arg));
671 else /* give 'em the same float back */
672 return arg;
675 DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
676 "Returns largest integer <= the base 2 log of the magnitude of ARG.\n\
677 This is the same as the exponent of a float.")
678 (arg)
679 Lisp_Object arg;
681 Lisp_Object val;
682 EMACS_INT value;
683 double f = extract_float (arg);
685 if (f == 0.0)
686 value = -(VALMASK >> 1);
687 else
689 #ifdef HAVE_LOGB
690 IN_FLOAT (value = logb (f), "logb", arg);
691 #else
692 #ifdef HAVE_FREXP
693 int ivalue;
694 IN_FLOAT (frexp (f, &ivalue), "logb", arg);
695 value = ivalue - 1;
696 #else
697 int i;
698 double d;
699 if (f < 0.0)
700 f = -f;
701 value = -1;
702 while (f < 0.5)
704 for (i = 1, d = 0.5; d * d >= f; i += i)
705 d *= d;
706 f /= d;
707 value -= i;
709 while (f >= 1.0)
711 for (i = 1, d = 2.0; d * d <= f; i += i)
712 d *= d;
713 f /= d;
714 value += i;
716 #endif
717 #endif
719 XSETINT (val, value);
720 return val;
723 #endif /* LISP_FLOAT_TYPE */
726 /* the rounding functions */
728 static Lisp_Object
729 rounding_driver (arg, divisor, double_round, int_round2, name)
730 register Lisp_Object arg, divisor;
731 double (*double_round) ();
732 EMACS_INT (*int_round2) ();
733 char *name;
735 CHECK_NUMBER_OR_FLOAT (arg, 0);
737 if (! NILP (divisor))
739 EMACS_INT i1, i2;
741 CHECK_NUMBER_OR_FLOAT (divisor, 1);
743 #ifdef LISP_FLOAT_TYPE
744 if (FLOATP (arg) || FLOATP (divisor))
746 double f1, f2;
748 f1 = FLOATP (arg) ? XFLOAT (arg)->data : XINT (arg);
749 f2 = (FLOATP (divisor) ? XFLOAT (divisor)->data : XINT (divisor));
750 if (! IEEE_FLOATING_POINT && f2 == 0)
751 Fsignal (Qarith_error, Qnil);
753 IN_FLOAT2 (f1 = (*double_round) (f1 / f2), name, arg, divisor);
754 FLOAT_TO_INT2 (f1, arg, name, arg, divisor);
755 return arg;
757 #endif
759 i1 = XINT (arg);
760 i2 = XINT (divisor);
762 if (i2 == 0)
763 Fsignal (Qarith_error, Qnil);
765 XSETINT (arg, (*int_round2) (i1, i2));
766 return arg;
769 #ifdef LISP_FLOAT_TYPE
770 if (FLOATP (arg))
772 double d;
774 IN_FLOAT (d = (*double_round) (XFLOAT (arg)->data), name, arg);
775 FLOAT_TO_INT (d, arg, name, arg);
777 #endif
779 return arg;
782 /* With C's /, the result is implementation-defined if either operand
783 is negative, so take care with negative operands in the following
784 integer functions. */
786 static EMACS_INT
787 ceiling2 (i1, i2)
788 EMACS_INT i1, i2;
790 return (i2 < 0
791 ? (i1 < 0 ? ((-1 - i1) / -i2) + 1 : - (i1 / -i2))
792 : (i1 <= 0 ? - (-i1 / i2) : ((i1 - 1) / i2) + 1));
795 static EMACS_INT
796 floor2 (i1, i2)
797 EMACS_INT i1, i2;
799 return (i2 < 0
800 ? (i1 <= 0 ? -i1 / -i2 : -1 - ((i1 - 1) / -i2))
801 : (i1 < 0 ? -1 - ((-1 - i1) / i2) : i1 / i2));
804 static EMACS_INT
805 truncate2 (i1, i2)
806 EMACS_INT i1, i2;
808 return (i2 < 0
809 ? (i1 < 0 ? -i1 / -i2 : - (i1 / -i2))
810 : (i1 < 0 ? - (-i1 / i2) : i1 / i2));
813 static EMACS_INT
814 round2 (i1, i2)
815 EMACS_INT i1, i2;
817 /* The C language's division operator gives us one remainder R, but
818 we want the remainder R1 on the other side of 0 if R1 is closer
819 to 0 than R is; because we want to round to even, we also want R1
820 if R and R1 are the same distance from 0 and if C's quotient is
821 odd. */
822 EMACS_INT q = i1 / i2;
823 EMACS_INT r = i1 % i2;
824 EMACS_INT abs_r = r < 0 ? -r : r;
825 EMACS_INT abs_r1 = (i2 < 0 ? -i2 : i2) - abs_r;
826 return q + (abs_r + (q & 1) <= abs_r1 ? 0 : (i2 ^ r) < 0 ? -1 : 1);
829 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
830 if `rint' exists but does not work right. */
831 #ifdef HAVE_RINT
832 #define emacs_rint rint
833 #else
834 static double
835 emacs_rint (d)
836 double d;
838 return floor (d + 0.5);
840 #endif
842 static double
843 double_identity (d)
844 double d;
846 return d;
849 DEFUN ("ceiling", Fceiling, Sceiling, 1, 2, 0,
850 "Return the smallest integer no less than ARG. (Round toward +inf.)\n\
851 With optional DIVISOR, return the smallest integer no less than ARG/DIVISOR.")
852 (arg, divisor)
853 Lisp_Object arg, divisor;
855 return rounding_driver (arg, divisor, ceil, ceiling2, "ceiling");
858 DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
859 "Return the largest integer no greater than ARG. (Round towards -inf.)\n\
860 With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR.")
861 (arg, divisor)
862 Lisp_Object arg, divisor;
864 return rounding_driver (arg, divisor, floor, floor2, "floor");
867 DEFUN ("round", Fround, Sround, 1, 2, 0,
868 "Return the nearest integer to ARG.\n\
869 With optional DIVISOR, return the nearest integer to ARG/DIVISOR.")
870 (arg, divisor)
871 Lisp_Object arg, divisor;
873 return rounding_driver (arg, divisor, emacs_rint, round2, "round");
876 DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0,
877 "Truncate a floating point number to an int.\n\
878 Rounds ARG toward zero.\n\
879 With optional DIVISOR, truncate ARG/DIVISOR.")
880 (arg, divisor)
881 Lisp_Object arg, divisor;
883 return rounding_driver (arg, divisor, double_identity, truncate2,
884 "truncate");
887 #ifdef LISP_FLOAT_TYPE
889 Lisp_Object
890 fmod_float (x, y)
891 register Lisp_Object x, y;
893 double f1, f2;
895 f1 = FLOATP (x) ? XFLOAT (x)->data : XINT (x);
896 f2 = FLOATP (y) ? XFLOAT (y)->data : XINT (y);
898 if (! IEEE_FLOATING_POINT && f2 == 0)
899 Fsignal (Qarith_error, Qnil);
901 /* If the "remainder" comes out with the wrong sign, fix it. */
902 IN_FLOAT2 ((f1 = fmod (f1, f2),
903 f1 = (f2 < 0 ? f1 > 0 : f1 < 0) ? f1 + f2 : f1),
904 "mod", x, y);
905 return make_float (f1);
908 /* It's not clear these are worth adding. */
910 DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
911 "Return the smallest integer no less than ARG, as a float.\n\
912 \(Round toward +inf.\)")
913 (arg)
914 register Lisp_Object arg;
916 double d = extract_float (arg);
917 IN_FLOAT (d = ceil (d), "fceiling", arg);
918 return make_float (d);
921 DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
922 "Return the largest integer no greater than ARG, as a float.\n\
923 \(Round towards -inf.\)")
924 (arg)
925 register Lisp_Object arg;
927 double d = extract_float (arg);
928 IN_FLOAT (d = floor (d), "ffloor", arg);
929 return make_float (d);
932 DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
933 "Return the nearest integer to ARG, as a float.")
934 (arg)
935 register Lisp_Object arg;
937 double d = extract_float (arg);
938 IN_FLOAT (d = emacs_rint (d), "fround", arg);
939 return make_float (d);
942 DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
943 "Truncate a floating point number to an integral float value.\n\
944 Rounds the value toward zero.")
945 (arg)
946 register Lisp_Object arg;
948 double d = extract_float (arg);
949 if (d >= 0.0)
950 IN_FLOAT (d = floor (d), "ftruncate", arg);
951 else
952 IN_FLOAT (d = ceil (d), "ftruncate", arg);
953 return make_float (d);
956 #ifdef FLOAT_CATCH_SIGILL
957 static SIGTYPE
958 float_error (signo)
959 int signo;
961 if (! in_float)
962 fatal_error_signal (signo);
964 #ifdef BSD_SYSTEM
965 #ifdef BSD4_1
966 sigrelse (SIGILL);
967 #else /* not BSD4_1 */
968 sigsetmask (SIGEMPTYMASK);
969 #endif /* not BSD4_1 */
970 #else
971 /* Must reestablish handler each time it is called. */
972 signal (SIGILL, float_error);
973 #endif /* BSD_SYSTEM */
975 in_float = 0;
977 Fsignal (Qarith_error, Fcons (float_error_arg, Qnil));
980 /* Another idea was to replace the library function `infnan'
981 where SIGILL is signaled. */
983 #endif /* FLOAT_CATCH_SIGILL */
985 #ifdef HAVE_MATHERR
986 int
987 matherr (x)
988 struct exception *x;
990 Lisp_Object args;
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 x->name = "expt";
997 args
998 = Fcons (build_string (x->name),
999 Fcons (make_float (x->arg1),
1000 ((!strcmp (x->name, "log") || !strcmp (x->name, "pow"))
1001 ? Fcons (make_float (x->arg2), Qnil)
1002 : Qnil)));
1003 switch (x->type)
1005 case DOMAIN: Fsignal (Qdomain_error, args); break;
1006 case SING: Fsignal (Qsingularity_error, args); break;
1007 case OVERFLOW: Fsignal (Qoverflow_error, args); break;
1008 case UNDERFLOW: Fsignal (Qunderflow_error, args); break;
1009 default: Fsignal (Qarith_error, args); break;
1011 return (1); /* don't set errno or print a message */
1013 #endif /* HAVE_MATHERR */
1015 init_floatfns ()
1017 #ifdef FLOAT_CATCH_SIGILL
1018 signal (SIGILL, float_error);
1019 #endif
1020 in_float = 0;
1023 #else /* not LISP_FLOAT_TYPE */
1025 init_floatfns ()
1028 #endif /* not LISP_FLOAT_TYPE */
1030 syms_of_floatfns ()
1032 #ifdef LISP_FLOAT_TYPE
1033 defsubr (&Sacos);
1034 defsubr (&Sasin);
1035 defsubr (&Satan);
1036 defsubr (&Scos);
1037 defsubr (&Ssin);
1038 defsubr (&Stan);
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);
1067 defsubr (&Sabs);
1068 defsubr (&Sfloat);
1069 defsubr (&Slogb);
1070 #endif /* LISP_FLOAT_TYPE */
1071 defsubr (&Sceiling);
1072 defsubr (&Sfloor);
1073 defsubr (&Sround);
1074 defsubr (&Struncate);