Merge changes made in Gnus trunk.
[bpt/emacs.git] / src / floatfns.c
CommitLineData
b70021f4 1/* Primitive operations on floating point for GNU Emacs Lisp interpreter.
73b0cd50 2 Copyright (C) 1988, 1993-1994, 1999, 2001-2011 Free Software Foundation, Inc.
b70021f4 3
0a9dd3a7
GM
4Author: Wolfgang Rupprecht
5(according to ack.texi)
6
b70021f4
MR
7This file is part of GNU Emacs.
8
9ec0b715 9GNU Emacs is free software: you can redistribute it and/or modify
b70021f4 10it under the terms of the GNU General Public License as published by
9ec0b715
GM
11the Free Software Foundation, either version 3 of the License, or
12(at your option) any later version.
b70021f4
MR
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
9ec0b715 20along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
b70021f4
MR
21
22
4b6baf5f
RS
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.
dca6c914 29 Define HAVE_RINT if you have a working rint.
4b6baf5f
RS
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
8e6208c5 42 either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and
4b6baf5f
RS
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
18160b98 48#include <config.h>
68c45bf0 49#include <signal.h>
d7306fe6 50#include <setjmp.h>
523e9291
RS
51#include "lisp.h"
52#include "syssignal.h"
53
2f261542
PE
54#if STDC_HEADERS
55#include <float.h>
56#endif
57
d137ae2f
PE
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
b70021f4 68#include <math.h>
4b6baf5f 69
32085e8e 70/* This declaration is omitted on some systems, like Ultrix. */
7a4720e2 71#if !defined (HPUX) && defined (HAVE_LOGB) && !defined (logb)
d2aa42f8 72extern double logb (double);
7a4720e2 73#endif /* not HPUX and HAVE_LOGB and no logb macro */
c26406fe 74
4b6baf5f
RS
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
c0f0a4a2 82#ifdef NO_MATHERR
f89182a2
RS
83#undef HAVE_MATHERR
84#endif
85
4b6baf5f
RS
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>
f12ef5eb 101#endif
265a9e55 102
311346bb 103#ifdef FLOAT_CATCH_SIGILL
4746118a 104static SIGTYPE float_error ();
311346bb 105#endif
b70021f4
MR
106
107/* Nonzero while executing in floating point.
108 This tells float_error what to do. */
109
110static int in_float;
111
112/* If an argument is out of range for a mathematical function,
21876236
RS
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. */
b70021f4 116
4b6baf5f
RS
117static Lisp_Object float_error_arg, float_error_arg2;
118
8ea90aa3 119static const char *float_error_fn_name;
b70021f4 120
265a9e55
JB
121/* Evaluate the floating point expression D, recording NUM
122 as the original argument for error messages.
123 D is normally an assignment expression.
f8d83099
JB
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. */
265a9e55 129
4b6baf5f
RS
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
f8131ed2 157#define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
4b6baf5f
RS
158#define IN_FLOAT2(d, name, num, num2) (in_float = 1, (d), in_float = 0)
159#endif
160
81a63ccc
KH
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 { \
29d823d6 166 if (FIXNUM_OVERFLOW_P (x)) \
81a63ccc 167 range_error (name, num); \
e0cb2a68 168 XSETINT (i, (EMACS_INT)(x)); \
81a63ccc
KH
169 } \
170 while (0)
171#define FLOAT_TO_INT2(x, i, name, num1, num2) \
172 do \
173 { \
29d823d6 174 if (FIXNUM_OVERFLOW_P (x)) \
81a63ccc 175 range_error2 (name, num1, num2); \
e0cb2a68 176 XSETINT (i, (EMACS_INT)(x)); \
81a63ccc
KH
177 } \
178 while (0)
179
4b6baf5f 180#define arith_error(op,arg) \
edef1631 181 xsignal2 (Qarith_error, build_string ((op)), (arg))
4b6baf5f 182#define range_error(op,arg) \
edef1631 183 xsignal2 (Qrange_error, build_string ((op)), (arg))
81a63ccc 184#define range_error2(op,a1,a2) \
edef1631 185 xsignal3 (Qrange_error, build_string ((op)), (a1), (a2))
4b6baf5f 186#define domain_error(op,arg) \
edef1631 187 xsignal2 (Qdomain_error, build_string ((op)), (arg))
4b6baf5f 188#define domain_error2(op,a1,a2) \
edef1631 189 xsignal3 (Qdomain_error, build_string ((op)), (a1), (a2))
b70021f4
MR
190
191/* Extract a Lisp number as a `double', or signal an error. */
192
193double
d5a3eaaf 194extract_float (Lisp_Object num)
b70021f4 195{
b7826503 196 CHECK_NUMBER_OR_FLOAT (num);
b70021f4 197
207a45c1 198 if (FLOATP (num))
70949dac 199 return XFLOAT_DATA (num);
b70021f4
MR
200 return (double) XINT (num);
201}
c2d4ea74
RS
202\f
203/* Trig functions. */
b70021f4
MR
204
205DEFUN ("acos", Facos, Sacos, 1, 1, 0,
335c5470 206 doc: /* Return the inverse cosine of ARG. */)
5842a27b 207 (register Lisp_Object arg)
b70021f4 208{
4b6baf5f
RS
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);
b70021f4
MR
215 return make_float (d);
216}
217
c2d4ea74 218DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
335c5470 219 doc: /* Return the inverse sine of ARG. */)
5842a27b 220 (register Lisp_Object arg)
b70021f4 221{
4b6baf5f
RS
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);
b70021f4
MR
228 return make_float (d);
229}
230
250ffca6
EZ
231DEFUN ("atan", Fatan, Satan, 1, 2, 0,
232 doc: /* Return the inverse tangent of the arguments.
233If only one argument Y is given, return the inverse tangent of Y.
234If two arguments Y and X are given, return the inverse tangent of Y
235divided by X, i.e. the angle in radians between the vector (X, Y)
236and the x-axis. */)
5842a27b 237 (register Lisp_Object y, Lisp_Object x)
b70021f4 238{
250ffca6
EZ
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 }
b70021f4
MR
249 return make_float (d);
250}
251
c2d4ea74 252DEFUN ("cos", Fcos, Scos, 1, 1, 0,
335c5470 253 doc: /* Return the cosine of ARG. */)
5842a27b 254 (register Lisp_Object arg)
b70021f4 255{
4b6baf5f
RS
256 double d = extract_float (arg);
257 IN_FLOAT (d = cos (d), "cos", arg);
b70021f4
MR
258 return make_float (d);
259}
260
c2d4ea74 261DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
335c5470 262 doc: /* Return the sine of ARG. */)
5842a27b 263 (register Lisp_Object arg)
b70021f4 264{
4b6baf5f
RS
265 double d = extract_float (arg);
266 IN_FLOAT (d = sin (d), "sin", arg);
b70021f4
MR
267 return make_float (d);
268}
269
c2d4ea74 270DEFUN ("tan", Ftan, Stan, 1, 1, 0,
335c5470 271 doc: /* Return the tangent of ARG. */)
5842a27b 272 (register Lisp_Object arg)
4b6baf5f
RS
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);
b70021f4
MR
281 return make_float (d);
282}
15e12598
VB
283
284#if defined HAVE_ISNAN && defined HAVE_COPYSIGN
285DEFUN ("isnan", Fisnan, Sisnan, 1, 1, 0,
286 doc: /* Return non nil iff argument X is a NaN. */)
5842a27b 287 (Lisp_Object x)
15e12598
VB
288{
289 CHECK_FLOAT (x);
290 return isnan (XFLOAT_DATA (x)) ? Qt : Qnil;
291}
292
293DEFUN ("copysign", Fcopysign, Scopysign, 1, 2, 0,
294 doc: /* Copy sign of X2 to value of X1, and return the result.
295Cause an error if X1 or X2 is not a float. */)
5842a27b 296 (Lisp_Object x1, Lisp_Object x2)
15e12598
VB
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
309DEFUN ("frexp", Ffrexp, Sfrexp, 1, 1, 0,
310 doc: /* Get significand and exponent of a floating point number.
311Breaks the floating point number X into its binary significand SGNFCAND
312\(a floating point value between 0.5 (included) and 1.0 (excluded))
313and an integral exponent EXP for 2, such that:
314
315 X = SGNFCAND * 2^EXP
316
317The function returns the cons cell (SGNFCAND . EXP).
318If X is zero, both parts (SGNFCAND and EXP) are zero. */)
5842a27b 319 (Lisp_Object x)
15e12598
VB
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
333DEFUN ("ldexp", Fldexp, Sldexp, 1, 2, 0,
334 doc: /* Construct number X from significand SGNFCAND and exponent EXP.
335Returns the floating point value resulting from multiplying SGNFCAND
336(the significand) by 2 raised to the power of EXP (the exponent). */)
5842a27b 337 (Lisp_Object sgnfcand, Lisp_Object exp)
15e12598
VB
338{
339 CHECK_NUMBER (exp);
340 return make_float (ldexp (XFLOATINT (sgnfcand), XINT (exp)));
341}
342#endif
b70021f4 343\f
c2d4ea74
RS
344#if 0 /* Leave these out unless we find there's a reason for them. */
345
b70021f4 346DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
335c5470 347 doc: /* Return the bessel function j0 of ARG. */)
5842a27b 348 (register Lisp_Object arg)
b70021f4 349{
4b6baf5f
RS
350 double d = extract_float (arg);
351 IN_FLOAT (d = j0 (d), "bessel-j0", arg);
b70021f4
MR
352 return make_float (d);
353}
354
355DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
335c5470 356 doc: /* Return the bessel function j1 of ARG. */)
5842a27b 357 (register Lisp_Object arg)
b70021f4 358{
4b6baf5f
RS
359 double d = extract_float (arg);
360 IN_FLOAT (d = j1 (d), "bessel-j1", arg);
b70021f4
MR
361 return make_float (d);
362}
363
364DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
335c5470
PJ
365 doc: /* Return the order N bessel function output jn of ARG.
366The first arg (the order) is truncated to an integer. */)
5842a27b 367 (register Lisp_Object n, Lisp_Object arg)
b70021f4 368{
3e670702
EN
369 int i1 = extract_float (n);
370 double f2 = extract_float (arg);
b70021f4 371
3e670702 372 IN_FLOAT (f2 = jn (i1, f2), "bessel-jn", n);
b70021f4
MR
373 return make_float (f2);
374}
375
376DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
335c5470 377 doc: /* Return the bessel function y0 of ARG. */)
5842a27b 378 (register Lisp_Object arg)
b70021f4 379{
4b6baf5f
RS
380 double d = extract_float (arg);
381 IN_FLOAT (d = y0 (d), "bessel-y0", arg);
b70021f4
MR
382 return make_float (d);
383}
384
385DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
335c5470 386 doc: /* Return the bessel function y1 of ARG. */)
5842a27b 387 (register Lisp_Object arg)
b70021f4 388{
4b6baf5f
RS
389 double d = extract_float (arg);
390 IN_FLOAT (d = y1 (d), "bessel-y0", arg);
b70021f4
MR
391 return make_float (d);
392}
393
394DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
335c5470
PJ
395 doc: /* Return the order N bessel function output yn of ARG.
396The first arg (the order) is truncated to an integer. */)
5842a27b 397 (register Lisp_Object n, Lisp_Object arg)
b70021f4 398{
3e670702
EN
399 int i1 = extract_float (n);
400 double f2 = extract_float (arg);
b70021f4 401
3e670702 402 IN_FLOAT (f2 = yn (i1, f2), "bessel-yn", n);
b70021f4
MR
403 return make_float (f2);
404}
b70021f4 405
c2d4ea74
RS
406#endif
407\f
408#if 0 /* Leave these out unless we see they are worth having. */
b70021f4
MR
409
410DEFUN ("erf", Ferf, Serf, 1, 1, 0,
335c5470 411 doc: /* Return the mathematical error function of ARG. */)
5842a27b 412 (register Lisp_Object arg)
b70021f4 413{
4b6baf5f
RS
414 double d = extract_float (arg);
415 IN_FLOAT (d = erf (d), "erf", arg);
b70021f4
MR
416 return make_float (d);
417}
418
419DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
335c5470 420 doc: /* Return the complementary error function of ARG. */)
5842a27b 421 (register Lisp_Object arg)
b70021f4 422{
4b6baf5f
RS
423 double d = extract_float (arg);
424 IN_FLOAT (d = erfc (d), "erfc", arg);
b70021f4
MR
425 return make_float (d);
426}
427
b70021f4 428DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
335c5470 429 doc: /* Return the log gamma of ARG. */)
5842a27b 430 (register Lisp_Object arg)
b70021f4 431{
4b6baf5f
RS
432 double d = extract_float (arg);
433 IN_FLOAT (d = lgamma (d), "log-gamma", arg);
b70021f4
MR
434 return make_float (d);
435}
436
4b6baf5f 437DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0,
335c5470 438 doc: /* Return the cube root of ARG. */)
5842a27b 439 (register Lisp_Object arg)
b70021f4 440{
4b6baf5f
RS
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
b70021f4
MR
450 return make_float (d);
451}
452
706ac90d
RS
453#endif
454\f
c2d4ea74 455DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
335c5470 456 doc: /* Return the exponential base e of ARG. */)
5842a27b 457 (register Lisp_Object arg)
4b6baf5f
RS
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);
b70021f4
MR
468 return make_float (d);
469}
470
b70021f4 471DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
335c5470 472 doc: /* Return the exponential ARG1 ** ARG2. */)
5842a27b 473 (register Lisp_Object arg1, Lisp_Object arg2)
b70021f4 474{
2742fe30 475 double f1, f2, f3;
b70021f4 476
b7826503
PJ
477 CHECK_NUMBER_OR_FLOAT (arg1);
478 CHECK_NUMBER_OR_FLOAT (arg2);
207a45c1 479 if (INTEGERP (arg1) /* common lisp spec */
5a9807a8
TTN
480 && INTEGERP (arg2) /* don't promote, if both are ints, and */
481 && 0 <= XINT (arg2)) /* we are sure the result is not fractional */
b70021f4 482 { /* this can be improved by pre-calculating */
9a51b24a 483 EMACS_INT acc, x, y; /* some binary powers of x then accumulating */
4be1d460
RS
484 Lisp_Object val;
485
4b6baf5f
RS
486 x = XINT (arg1);
487 y = XINT (arg2);
b70021f4 488 acc = 1;
177c0ea7 489
b70021f4
MR
490 if (y < 0)
491 {
4b6baf5f
RS
492 if (x == 1)
493 acc = 1;
494 else if (x == -1)
495 acc = (y & 1) ? -1 : 1;
496 else
497 acc = 0;
b70021f4
MR
498 }
499 else
500 {
4b6baf5f
RS
501 while (y > 0)
502 {
503 if (y & 1)
504 acc *= x;
505 x *= x;
506 y = (unsigned)y >> 1;
507 }
b70021f4 508 }
e0cb2a68 509 XSETINT (val, acc);
4be1d460 510 return val;
b70021f4 511 }
70949dac
KR
512 f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1);
513 f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2);
4b6baf5f
RS
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
2742fe30
MC
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);
b70021f4 526}
c2d4ea74 527
56abb480 528DEFUN ("log", Flog, Slog, 1, 2, 0,
335c5470 529 doc: /* Return the natural logarithm of ARG.
356e6d8d 530If the optional argument BASE is given, return log ARG using that base. */)
5842a27b 531 (register Lisp_Object arg, Lisp_Object base)
b70021f4 532{
4b6baf5f 533 double d = extract_float (arg);
56abb480 534
4b6baf5f
RS
535#ifdef FLOAT_CHECK_DOMAIN
536 if (d <= 0.0)
537 domain_error2 ("log", arg, base);
538#endif
56abb480 539 if (NILP (base))
4b6baf5f 540 IN_FLOAT (d = log (d), "log", arg);
56abb480
JB
541 else
542 {
543 double b = extract_float (base);
544
4b6baf5f
RS
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
f8131ed2 552 IN_FLOAT2 (d = log (d) / log (b), "log", arg, base);
56abb480 553 }
b70021f4
MR
554 return make_float (d);
555}
556
c2d4ea74 557DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
335c5470 558 doc: /* Return the logarithm base 10 of ARG. */)
5842a27b 559 (register Lisp_Object arg)
b70021f4 560{
4b6baf5f
RS
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);
c2d4ea74
RS
567 return make_float (d);
568}
569
b70021f4 570DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
335c5470 571 doc: /* Return the square root of ARG. */)
5842a27b 572 (register Lisp_Object arg)
b70021f4 573{
4b6baf5f
RS
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);
b70021f4
MR
580 return make_float (d);
581}
c2d4ea74 582\f
706ac90d 583#if 0 /* Not clearly worth adding. */
b70021f4 584
c2d4ea74 585DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
335c5470 586 doc: /* Return the inverse hyperbolic cosine of ARG. */)
5842a27b 587 (register Lisp_Object arg)
b70021f4 588{
4b6baf5f
RS
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
c2d4ea74
RS
599 return make_float (d);
600}
601
602DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
335c5470 603 doc: /* Return the inverse hyperbolic sine of ARG. */)
5842a27b 604 (register Lisp_Object arg)
c2d4ea74 605{
4b6baf5f
RS
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
c2d4ea74
RS
612 return make_float (d);
613}
614
615DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
335c5470 616 doc: /* Return the inverse hyperbolic tangent of ARG. */)
5842a27b 617 (register Lisp_Object arg)
c2d4ea74 618{
4b6baf5f
RS
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
c2d4ea74
RS
629 return make_float (d);
630}
631
632DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
335c5470 633 doc: /* Return the hyperbolic cosine of ARG. */)
5842a27b 634 (register Lisp_Object arg)
c2d4ea74 635{
4b6baf5f
RS
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);
c2d4ea74
RS
642 return make_float (d);
643}
644
645DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
335c5470 646 doc: /* Return the hyperbolic sine of ARG. */)
5842a27b 647 (register Lisp_Object arg)
c2d4ea74 648{
4b6baf5f
RS
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);
b70021f4
MR
655 return make_float (d);
656}
657
658DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
335c5470 659 doc: /* Return the hyperbolic tangent of ARG. */)
5842a27b 660 (register Lisp_Object arg)
b70021f4 661{
4b6baf5f
RS
662 double d = extract_float (arg);
663 IN_FLOAT (d = tanh (d), "tanh", arg);
b70021f4
MR
664 return make_float (d);
665}
c2d4ea74 666#endif
b70021f4
MR
667\f
668DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
335c5470 669 doc: /* Return the absolute value of ARG. */)
5842a27b 670 (register Lisp_Object arg)
b70021f4 671{
b7826503 672 CHECK_NUMBER_OR_FLOAT (arg);
b70021f4 673
207a45c1 674 if (FLOATP (arg))
70949dac 675 IN_FLOAT (arg = make_float (fabs (XFLOAT_DATA (arg))), "abs", arg);
4b6baf5f 676 else if (XINT (arg) < 0)
db37cb37 677 XSETINT (arg, - XINT (arg));
b70021f4 678
4b6baf5f 679 return arg;
b70021f4
MR
680}
681
682DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
335c5470 683 doc: /* Return the floating point number equal to ARG. */)
5842a27b 684 (register Lisp_Object arg)
b70021f4 685{
b7826503 686 CHECK_NUMBER_OR_FLOAT (arg);
b70021f4 687
207a45c1 688 if (INTEGERP (arg))
4b6baf5f 689 return make_float ((double) XINT (arg));
b70021f4 690 else /* give 'em the same float back */
4b6baf5f 691 return arg;
b70021f4
MR
692}
693
694DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
335c5470
PJ
695 doc: /* Returns largest integer <= the base 2 log of the magnitude of ARG.
696This is the same as the exponent of a float. */)
5842a27b 697 (Lisp_Object arg)
b70021f4 698{
340176df 699 Lisp_Object val;
a7bf3c54 700 EMACS_INT value;
5bf54166 701 double f = extract_float (arg);
340176df 702
6694b327 703 if (f == 0.0)
b916d672 704 value = MOST_NEGATIVE_FIXNUM;
6694b327
KH
705 else
706 {
6d3c6adb 707#ifdef HAVE_LOGB
6694b327 708 IN_FLOAT (value = logb (f), "logb", arg);
6d3c6adb
JB
709#else
710#ifdef HAVE_FREXP
c8bf6cf3
KH
711 int ivalue;
712 IN_FLOAT (frexp (f, &ivalue), "logb", arg);
713 value = ivalue - 1;
c26406fe 714#else
6694b327
KH
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 }
6d3c6adb 734#endif
340176df 735#endif
6694b327 736 }
e0cb2a68 737 XSETINT (val, value);
c26406fe 738 return val;
b70021f4
MR
739}
740
fc2157cb 741
acbbacbe
PE
742/* the rounding functions */
743
744static Lisp_Object
d2aa42f8
DN
745rounding_driver (Lisp_Object arg, Lisp_Object divisor,
746 double (*double_round) (double),
747 EMACS_INT (*int_round2) (EMACS_INT, EMACS_INT),
8ea90aa3 748 const char *name)
b70021f4 749{
b7826503 750 CHECK_NUMBER_OR_FLOAT (arg);
b70021f4 751
fc2157cb
PE
752 if (! NILP (divisor))
753 {
9a51b24a 754 EMACS_INT i1, i2;
fc2157cb 755
b7826503 756 CHECK_NUMBER_OR_FLOAT (divisor);
fc2157cb 757
207a45c1 758 if (FLOATP (arg) || FLOATP (divisor))
fc2157cb
PE
759 {
760 double f1, f2;
761
70949dac
KR
762 f1 = FLOATP (arg) ? XFLOAT_DATA (arg) : XINT (arg);
763 f2 = (FLOATP (divisor) ? XFLOAT_DATA (divisor) : XINT (divisor));
d137ae2f 764 if (! IEEE_FLOATING_POINT && f2 == 0)
edef1631 765 xsignal0 (Qarith_error);
fc2157cb 766
acbbacbe
PE
767 IN_FLOAT2 (f1 = (*double_round) (f1 / f2), name, arg, divisor);
768 FLOAT_TO_INT2 (f1, arg, name, arg, divisor);
fc2157cb
PE
769 return arg;
770 }
fc2157cb
PE
771
772 i1 = XINT (arg);
773 i2 = XINT (divisor);
774
775 if (i2 == 0)
edef1631 776 xsignal0 (Qarith_error);
fc2157cb 777
acbbacbe 778 XSETINT (arg, (*int_round2) (i1, i2));
fc2157cb
PE
779 return arg;
780 }
781
207a45c1 782 if (FLOATP (arg))
81a63ccc
KH
783 {
784 double d;
acbbacbe 785
70949dac 786 IN_FLOAT (d = (*double_round) (XFLOAT_DATA (arg)), name, arg);
acbbacbe 787 FLOAT_TO_INT (d, arg, name, arg);
81a63ccc 788 }
b70021f4 789
4b6baf5f 790 return arg;
b70021f4
MR
791}
792
acbbacbe
PE
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
797static EMACS_INT
d2aa42f8 798ceiling2 (EMACS_INT i1, EMACS_INT i2)
acbbacbe
PE
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
805static EMACS_INT
d2aa42f8 806floor2 (EMACS_INT i1, EMACS_INT i2)
acbbacbe
PE
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
813static EMACS_INT
d2aa42f8 814truncate2 (EMACS_INT i1, EMACS_INT i2)
acbbacbe
PE
815{
816 return (i2 < 0
817 ? (i1 < 0 ? -i1 / -i2 : - (i1 / -i2))
818 : (i1 < 0 ? - (-i1 / i2) : i1 / i2));
819}
820
821static EMACS_INT
d2aa42f8 822round2 (EMACS_INT i1, EMACS_INT i2)
acbbacbe
PE
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
dca6c914
RS
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
4b5878a8 841static double
d2aa42f8 842emacs_rint (double d)
4b5878a8 843{
1b65c684 844 return floor (d + 0.5);
4b5878a8
KH
845}
846#endif
847
acbbacbe 848static double
d2aa42f8 849double_identity (double d)
acbbacbe
PE
850{
851 return d;
852}
853
854DEFUN ("ceiling", Fceiling, Sceiling, 1, 2, 0,
1d6ea92f
RS
855 doc: /* Return the smallest integer no less than ARG.
856This rounds the value towards +inf.
335c5470 857With optional DIVISOR, return the smallest integer no less than ARG/DIVISOR. */)
5842a27b 858 (Lisp_Object arg, Lisp_Object divisor)
acbbacbe
PE
859{
860 return rounding_driver (arg, divisor, ceil, ceiling2, "ceiling");
861}
862
863DEFUN ("floor", Ffloor, Sfloor, 1, 2, 0,
1d6ea92f 864 doc: /* Return the largest integer no greater than ARG.
568b6e41 865This rounds the value towards -inf.
335c5470 866With optional DIVISOR, return the largest integer no greater than ARG/DIVISOR. */)
5842a27b 867 (Lisp_Object arg, Lisp_Object divisor)
acbbacbe
PE
868{
869 return rounding_driver (arg, divisor, floor, floor2, "floor");
870}
871
872DEFUN ("round", Fround, Sround, 1, 2, 0,
335c5470 873 doc: /* Return the nearest integer to ARG.
6ded2c89
EZ
874With optional DIVISOR, return the nearest integer to ARG/DIVISOR.
875
a32a4857
EZ
876Rounding a value equidistant between two integers may choose the
877integer closer to zero, or it may prefer an even integer, depending on
878your machine. For example, \(round 2.5\) can return 3 on some
59fe0cee 879systems, but 2 on others. */)
5842a27b 880 (Lisp_Object arg, Lisp_Object divisor)
acbbacbe 881{
dca6c914 882 return rounding_driver (arg, divisor, emacs_rint, round2, "round");
acbbacbe
PE
883}
884
885DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0,
335c5470
PJ
886 doc: /* Truncate a floating point number to an int.
887Rounds ARG toward zero.
888With optional DIVISOR, truncate ARG/DIVISOR. */)
5842a27b 889 (Lisp_Object arg, Lisp_Object divisor)
acbbacbe
PE
890{
891 return rounding_driver (arg, divisor, double_identity, truncate2,
892 "truncate");
893}
894
fc2157cb 895
d137ae2f 896Lisp_Object
dd4c5104 897fmod_float (Lisp_Object x, Lisp_Object y)
d137ae2f
PE
898{
899 double f1, f2;
900
70949dac
KR
901 f1 = FLOATP (x) ? XFLOAT_DATA (x) : XINT (x);
902 f2 = FLOATP (y) ? XFLOAT_DATA (y) : XINT (y);
d137ae2f
PE
903
904 if (! IEEE_FLOATING_POINT && f2 == 0)
edef1631 905 xsignal0 (Qarith_error);
d137ae2f
PE
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}
4b6baf5f 913\f
4b6baf5f
RS
914/* It's not clear these are worth adding. */
915
916DEFUN ("fceiling", Ffceiling, Sfceiling, 1, 1, 0,
335c5470
PJ
917 doc: /* Return the smallest integer no less than ARG, as a float.
918\(Round toward +inf.\) */)
5842a27b 919 (register Lisp_Object arg)
4b6baf5f
RS
920{
921 double d = extract_float (arg);
922 IN_FLOAT (d = ceil (d), "fceiling", arg);
923 return make_float (d);
924}
925
926DEFUN ("ffloor", Fffloor, Sffloor, 1, 1, 0,
335c5470
PJ
927 doc: /* Return the largest integer no greater than ARG, as a float.
928\(Round towards -inf.\) */)
5842a27b 929 (register Lisp_Object arg)
4b6baf5f
RS
930{
931 double d = extract_float (arg);
932 IN_FLOAT (d = floor (d), "ffloor", arg);
933 return make_float (d);
934}
b70021f4 935
4b6baf5f 936DEFUN ("fround", Ffround, Sfround, 1, 1, 0,
335c5470 937 doc: /* Return the nearest integer to ARG, as a float. */)
5842a27b 938 (register Lisp_Object arg)
4b6baf5f
RS
939{
940 double d = extract_float (arg);
dca6c914 941 IN_FLOAT (d = emacs_rint (d), "fround", arg);
4b6baf5f
RS
942 return make_float (d);
943}
944
945DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
335c5470
PJ
946 doc: /* Truncate a floating point number to an integral float value.
947Rounds the value toward zero. */)
5842a27b 948 (register Lisp_Object arg)
4b6baf5f
RS
949{
950 double d = extract_float (arg);
951 if (d >= 0.0)
952 IN_FLOAT (d = floor (d), "ftruncate", arg);
953 else
a3fc5236 954 IN_FLOAT (d = ceil (d), "ftruncate", arg);
4b6baf5f 955 return make_float (d);
b70021f4
MR
956}
957\f
4b6baf5f 958#ifdef FLOAT_CATCH_SIGILL
4746118a 959static SIGTYPE
b70021f4
MR
960float_error (signo)
961 int signo;
962{
963 if (! in_float)
964 fatal_error_signal (signo);
965
6df54671 966#ifdef BSD_SYSTEM
e065a56e 967 sigsetmask (SIGEMPTYMASK);
265a9e55
JB
968#else
969 /* Must reestablish handler each time it is called. */
970 signal (SIGILL, float_error);
6df54671 971#endif /* BSD_SYSTEM */
b70021f4 972
333f1b6f 973 SIGNAL_THREAD_CHECK (signo);
b70021f4
MR
974 in_float = 0;
975
edef1631 976 xsignal1 (Qarith_error, float_error_arg);
b70021f4
MR
977}
978
4b6baf5f
RS
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
177c0ea7 985int
d5a3eaaf 986matherr (struct exception *x)
4b6baf5f
RS
987{
988 Lisp_Object args;
42ca4633
J
989 const char *name = x->name;
990
4b6baf5f
RS
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"))
42ca4633 995 name = "expt";
4b6baf5f
RS
996
997 args
42ca4633 998 = Fcons (build_string (name),
4b6baf5f 999 Fcons (make_float (x->arg1),
42ca4633 1000 ((!strcmp (name, "log") || !strcmp (name, "pow"))
4b6baf5f
RS
1001 ? Fcons (make_float (x->arg2), Qnil)
1002 : Qnil)));
1003 switch (x->type)
1004 {
edef1631
KS
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;
4b6baf5f
RS
1010 }
1011 return (1); /* don't set errno or print a message */
1012}
1013#endif /* HAVE_MATHERR */
1014
dfcf069d 1015void
d5a3eaaf 1016init_floatfns (void)
b70021f4 1017{
4b6baf5f 1018#ifdef FLOAT_CATCH_SIGILL
b70021f4 1019 signal (SIGILL, float_error);
177c0ea7 1020#endif
b70021f4
MR
1021 in_float = 0;
1022}
1023
dfcf069d 1024void
d5a3eaaf 1025syms_of_floatfns (void)
b70021f4
MR
1026{
1027 defsubr (&Sacos);
b70021f4 1028 defsubr (&Sasin);
b70021f4 1029 defsubr (&Satan);
c2d4ea74
RS
1030 defsubr (&Scos);
1031 defsubr (&Ssin);
1032 defsubr (&Stan);
15e12598
VB
1033#if defined HAVE_ISNAN && defined HAVE_COPYSIGN
1034 defsubr (&Sisnan);
1035 defsubr (&Scopysign);
1036 defsubr (&Sfrexp);
1037 defsubr (&Sldexp);
1038#endif
c2d4ea74
RS
1039#if 0
1040 defsubr (&Sacosh);
1041 defsubr (&Sasinh);
b70021f4 1042 defsubr (&Satanh);
c2d4ea74
RS
1043 defsubr (&Scosh);
1044 defsubr (&Ssinh);
1045 defsubr (&Stanh);
b70021f4
MR
1046 defsubr (&Sbessel_y0);
1047 defsubr (&Sbessel_y1);
1048 defsubr (&Sbessel_yn);
1049 defsubr (&Sbessel_j0);
1050 defsubr (&Sbessel_j1);
1051 defsubr (&Sbessel_jn);
b70021f4
MR
1052 defsubr (&Serf);
1053 defsubr (&Serfc);
c2d4ea74 1054 defsubr (&Slog_gamma);
4b6baf5f 1055 defsubr (&Scube_root);
892ed7e0 1056#endif
4b6baf5f
RS
1057 defsubr (&Sfceiling);
1058 defsubr (&Sffloor);
1059 defsubr (&Sfround);
1060 defsubr (&Sftruncate);
b70021f4 1061 defsubr (&Sexp);
c2d4ea74 1062 defsubr (&Sexpt);
b70021f4
MR
1063 defsubr (&Slog);
1064 defsubr (&Slog10);
b70021f4 1065 defsubr (&Ssqrt);
b70021f4
MR
1066
1067 defsubr (&Sabs);
1068 defsubr (&Sfloat);
1069 defsubr (&Slogb);
1070 defsubr (&Sceiling);
acbbacbe 1071 defsubr (&Sfloor);
b70021f4
MR
1072 defsubr (&Sround);
1073 defsubr (&Struncate);
1074}
ab5796a9 1075