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