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