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