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