* callproc.c (init_callproc): Move the initialization of
[bpt/emacs.git] / src / floatfns.c
CommitLineData
b70021f4 1/* Primitive operations on floating point for GNU Emacs Lisp interpreter.
4746118a 2 Copyright (C) 1988, 1992 Free Software Foundation, Inc.
b70021f4
MR
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
4746118a 8the Free Software Foundation; either version 2, or (at your option)
b70021f4
MR
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
22
23#include "config.h"
24#include "lisp.h"
e065a56e 25#include "syssignal.h"
b70021f4
MR
26
27Lisp_Object Qarith_error;
28
29#ifdef LISP_FLOAT_TYPE
265a9e55 30
b70021f4 31#include <math.h>
265a9e55
JB
32#include <errno.h>
33
34extern int errno;
35
36/* Avoid traps on VMS from sinh and cosh.
37 All the other functions set errno instead. */
38
39#ifdef VMS
40#undef cosh
41#undef sinh
42#define cosh(x) ((exp(x)+exp(-x))*0.5)
43#define sinh(x) ((exp(x)-exp(-x))*0.5)
44#endif /* VMS */
45
4746118a 46static SIGTYPE float_error ();
b70021f4
MR
47
48/* Nonzero while executing in floating point.
49 This tells float_error what to do. */
50
51static int in_float;
52
53/* If an argument is out of range for a mathematical function,
265a9e55 54 here is the actual argument value to use in the error message. */
b70021f4
MR
55
56static Lisp_Object float_error_arg;
57
265a9e55
JB
58/* Evaluate the floating point expression D, recording NUM
59 as the original argument for error messages.
60 D is normally an assignment expression.
61 Handle errors which may result in signals or may set errno. */
62
63#define IN_FLOAT(D, NUM) \
4746118a
JB
64(in_float = 1, errno = 0, float_error_arg = NUM, (D), \
65 (errno == ERANGE || errno == EDOM ? float_error () : (SIGTYPE) 0), \
265a9e55 66 in_float = 0)
b70021f4
MR
67
68/* Extract a Lisp number as a `double', or signal an error. */
69
70double
71extract_float (num)
72 Lisp_Object num;
73{
74 CHECK_NUMBER_OR_FLOAT (num, 0);
75
76 if (XTYPE (num) == Lisp_Float)
77 return XFLOAT (num)->data;
78 return (double) XINT (num);
79}
c2d4ea74
RS
80\f
81/* Trig functions. */
b70021f4
MR
82
83DEFUN ("acos", Facos, Sacos, 1, 1, 0,
84 "Return the inverse cosine of ARG.")
85 (num)
86 register Lisp_Object num;
87{
88 double d = extract_float (num);
89 IN_FLOAT (d = acos (d), num);
90 return make_float (d);
91}
92
c2d4ea74
RS
93DEFUN ("asin", Fasin, Sasin, 1, 1, 0,
94 "Return the inverse sine of ARG.")
b70021f4
MR
95 (num)
96 register Lisp_Object num;
97{
98 double d = extract_float (num);
c2d4ea74 99 IN_FLOAT (d = asin (d), num);
b70021f4
MR
100 return make_float (d);
101}
102
c2d4ea74
RS
103DEFUN ("atan", Fatan, Satan, 1, 1, 0,
104 "Return the inverse tangent of ARG.")
b70021f4
MR
105 (num)
106 register Lisp_Object num;
107{
108 double d = extract_float (num);
c2d4ea74 109 IN_FLOAT (d = atan (d), num);
b70021f4
MR
110 return make_float (d);
111}
112
c2d4ea74
RS
113DEFUN ("cos", Fcos, Scos, 1, 1, 0,
114 "Return the cosine of ARG.")
b70021f4
MR
115 (num)
116 register Lisp_Object num;
117{
118 double d = extract_float (num);
c2d4ea74 119 IN_FLOAT (d = cos (d), num);
b70021f4
MR
120 return make_float (d);
121}
122
c2d4ea74
RS
123DEFUN ("sin", Fsin, Ssin, 1, 1, 0,
124 "Return the sine of ARG.")
b70021f4
MR
125 (num)
126 register Lisp_Object num;
127{
128 double d = extract_float (num);
c2d4ea74 129 IN_FLOAT (d = sin (d), num);
b70021f4
MR
130 return make_float (d);
131}
132
c2d4ea74
RS
133DEFUN ("tan", Ftan, Stan, 1, 1, 0,
134 "Return the tangent of ARG.")
b70021f4
MR
135 (num)
136 register Lisp_Object num;
137{
138 double d = extract_float (num);
c2d4ea74 139 IN_FLOAT (d = tan (d), num);
b70021f4
MR
140 return make_float (d);
141}
142\f
c2d4ea74
RS
143#if 0 /* Leave these out unless we find there's a reason for them. */
144
b70021f4
MR
145DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0,
146 "Return the bessel function j0 of ARG.")
147 (num)
148 register Lisp_Object num;
149{
150 double d = extract_float (num);
151 IN_FLOAT (d = j0 (d), num);
152 return make_float (d);
153}
154
155DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0,
156 "Return the bessel function j1 of ARG.")
157 (num)
158 register Lisp_Object num;
159{
160 double d = extract_float (num);
161 IN_FLOAT (d = j1 (d), num);
162 return make_float (d);
163}
164
165DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0,
166 "Return the order N bessel function output jn of ARG.\n\
167The first arg (the order) is truncated to an integer.")
168 (num1, num2)
169 register Lisp_Object num1, num2;
170{
171 int i1 = extract_float (num1);
172 double f2 = extract_float (num2);
173
174 IN_FLOAT (f2 = jn (i1, f2), num1);
175 return make_float (f2);
176}
177
178DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0,
179 "Return the bessel function y0 of ARG.")
180 (num)
181 register Lisp_Object num;
182{
183 double d = extract_float (num);
184 IN_FLOAT (d = y0 (d), num);
185 return make_float (d);
186}
187
188DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0,
189 "Return the bessel function y1 of ARG.")
190 (num)
191 register Lisp_Object num;
192{
193 double d = extract_float (num);
194 IN_FLOAT (d = y1 (d), num);
195 return make_float (d);
196}
197
198DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0,
199 "Return the order N bessel function output yn of ARG.\n\
200The first arg (the order) is truncated to an integer.")
201 (num1, num2)
202 register Lisp_Object num1, num2;
203{
204 int i1 = extract_float (num1);
205 double f2 = extract_float (num2);
206
207 IN_FLOAT (f2 = yn (i1, f2), num1);
208 return make_float (f2);
209}
b70021f4 210
c2d4ea74
RS
211#endif
212\f
213#if 0 /* Leave these out unless we see they are worth having. */
b70021f4
MR
214
215DEFUN ("erf", Ferf, Serf, 1, 1, 0,
216 "Return the mathematical error function of ARG.")
217 (num)
218 register Lisp_Object num;
219{
220 double d = extract_float (num);
221 IN_FLOAT (d = erf (d), num);
222 return make_float (d);
223}
224
225DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0,
226 "Return the complementary error function of ARG.")
227 (num)
228 register Lisp_Object num;
229{
230 double d = extract_float (num);
231 IN_FLOAT (d = erfc (d), num);
232 return make_float (d);
233}
234
b70021f4
MR
235DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0,
236 "Return the log gamma of ARG.")
237 (num)
238 register Lisp_Object num;
239{
240 double d = extract_float (num);
241 IN_FLOAT (d = lgamma (d), num);
242 return make_float (d);
243}
244
706ac90d 245DEFUN ("cbrt", Fcbrt, Scbrt, 1, 1, 0,
c2d4ea74 246 "Return the cube root of ARG.")
b70021f4
MR
247 (num)
248 register Lisp_Object num;
249{
250 double d = extract_float (num);
c2d4ea74 251 IN_FLOAT (d = cbrt (d), num);
b70021f4
MR
252 return make_float (d);
253}
254
706ac90d
RS
255#endif
256\f
c2d4ea74
RS
257DEFUN ("exp", Fexp, Sexp, 1, 1, 0,
258 "Return the exponential base e of ARG.")
b70021f4
MR
259 (num)
260 register Lisp_Object num;
261{
262 double d = extract_float (num);
c2d4ea74 263 IN_FLOAT (d = exp (d), num);
b70021f4
MR
264 return make_float (d);
265}
266
b70021f4 267DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
c2d4ea74 268 "Return the exponential X ** Y.")
b70021f4
MR
269 (num1, num2)
270 register Lisp_Object num1, num2;
271{
272 double f1, f2;
273
274 CHECK_NUMBER_OR_FLOAT (num1, 0);
275 CHECK_NUMBER_OR_FLOAT (num2, 0);
276 if ((XTYPE (num1) == Lisp_Int) && /* common lisp spec */
277 (XTYPE (num2) == Lisp_Int)) /* don't promote, if both are ints */
278 { /* this can be improved by pre-calculating */
279 int acc, x, y; /* some binary powers of x then acumulating */
280 /* these, therby saving some time. -wsr */
281 x = XINT (num1);
282 y = XINT (num2);
283 acc = 1;
284
285 if (y < 0)
286 {
287 for (; y < 0; y++)
288 acc /= x;
289 }
290 else
291 {
292 for (; y > 0; y--)
293 acc *= x;
294 }
1cee2045
JB
295 XFASTINT (x) = acc;
296 return x;
b70021f4
MR
297 }
298 f1 = (XTYPE (num1) == Lisp_Float) ? XFLOAT (num1)->data : XINT (num1);
299 f2 = (XTYPE (num2) == Lisp_Float) ? XFLOAT (num2)->data : XINT (num2);
300 IN_FLOAT (f1 = pow (f1, f2), num1);
301 return make_float (f1);
302}
c2d4ea74 303
56abb480 304DEFUN ("log", Flog, Slog, 1, 2, 0,
c2e42adb 305 "Return the natural logarithm of NUM.\n\
56abb480
JB
306If second optional argument BASE is given, return log NUM using that base.")
307 (num, base)
1cee2045 308 register Lisp_Object num, base;
b70021f4
MR
309{
310 double d = extract_float (num);
56abb480
JB
311
312 if (NILP (base))
313 IN_FLOAT (d = log (d), num);
314 else
315 {
316 double b = extract_float (base);
317
318 IN_FLOAT (d = log (num) / log (b), num);
319 }
b70021f4
MR
320 return make_float (d);
321}
322
c2d4ea74
RS
323DEFUN ("log10", Flog10, Slog10, 1, 1, 0,
324 "Return the logarithm base 10 of ARG.")
b70021f4
MR
325 (num)
326 register Lisp_Object num;
327{
328 double d = extract_float (num);
c2d4ea74
RS
329 IN_FLOAT (d = log10 (d), num);
330 return make_float (d);
331}
332
b70021f4
MR
333DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0,
334 "Return the square root of ARG.")
335 (num)
336 register Lisp_Object num;
337{
338 double d = extract_float (num);
339 IN_FLOAT (d = sqrt (d), num);
340 return make_float (d);
341}
c2d4ea74 342\f
706ac90d 343#if 0 /* Not clearly worth adding. */
b70021f4 344
c2d4ea74
RS
345DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0,
346 "Return the inverse hyperbolic cosine of ARG.")
b70021f4
MR
347 (num)
348 register Lisp_Object num;
349{
350 double d = extract_float (num);
c2d4ea74
RS
351 IN_FLOAT (d = acosh (d), num);
352 return make_float (d);
353}
354
355DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0,
356 "Return the inverse hyperbolic sine of ARG.")
357 (num)
358 register Lisp_Object num;
359{
360 double d = extract_float (num);
361 IN_FLOAT (d = asinh (d), num);
362 return make_float (d);
363}
364
365DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0,
366 "Return the inverse hyperbolic tangent of ARG.")
367 (num)
368 register Lisp_Object num;
369{
370 double d = extract_float (num);
371 IN_FLOAT (d = atanh (d), num);
372 return make_float (d);
373}
374
375DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0,
376 "Return the hyperbolic cosine of ARG.")
377 (num)
378 register Lisp_Object num;
379{
380 double d = extract_float (num);
381 IN_FLOAT (d = cosh (d), num);
382 return make_float (d);
383}
384
385DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0,
386 "Return the hyperbolic sine of ARG.")
387 (num)
388 register Lisp_Object num;
389{
390 double d = extract_float (num);
391 IN_FLOAT (d = sinh (d), num);
b70021f4
MR
392 return make_float (d);
393}
394
395DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0,
396 "Return the hyperbolic tangent of ARG.")
397 (num)
398 register Lisp_Object num;
399{
400 double d = extract_float (num);
401 IN_FLOAT (d = tanh (d), num);
402 return make_float (d);
403}
c2d4ea74 404#endif
b70021f4
MR
405\f
406DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
407 "Return the absolute value of ARG.")
408 (num)
409 register Lisp_Object num;
410{
411 CHECK_NUMBER_OR_FLOAT (num, 0);
412
413 if (XTYPE (num) == Lisp_Float)
414 IN_FLOAT (num = make_float (fabs (XFLOAT (num)->data)), num);
415 else if (XINT (num) < 0)
416 XSETINT (num, - XFASTINT (num));
417
418 return num;
419}
420
421DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
422 "Return the floating point number equal to ARG.")
423 (num)
424 register Lisp_Object num;
425{
426 CHECK_NUMBER_OR_FLOAT (num, 0);
427
428 if (XTYPE (num) == Lisp_Int)
429 return make_float ((double) XINT (num));
430 else /* give 'em the same float back */
431 return num;
432}
433
434DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
435 "Returns the integer that is the base 2 log of ARG.\n\
436This is the same as the exponent of a float.")
437 (num)
438Lisp_Object num;
439{
56abb480
JB
440#ifdef USG
441 /* System V apparently doesn't have a `logb' function. */
442 return Flog (num, make_number (2));
443#else
b70021f4 444 Lisp_Object val;
56abb480 445 double f = extract_float (num);
b70021f4 446
b70021f4
MR
447 IN_FLOAT (val = logb (f), num);
448 XSET (val, Lisp_Int, val);
449 return val;
56abb480 450#endif
b70021f4
MR
451}
452
453/* the rounding functions */
454
455DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0,
456 "Return the smallest integer no less than ARG. (Round toward +inf.)")
457 (num)
458 register Lisp_Object num;
459{
460 CHECK_NUMBER_OR_FLOAT (num, 0);
461
462 if (XTYPE (num) == Lisp_Float)
463 IN_FLOAT (XSET (num, Lisp_Int, ceil (XFLOAT (num)->data)), num);
464
465 return num;
466}
467
468DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0,
469 "Return the largest integer no greater than ARG. (Round towards -inf.)")
470 (num)
471 register Lisp_Object num;
472{
473 CHECK_NUMBER_OR_FLOAT (num, 0);
474
475 if (XTYPE (num) == Lisp_Float)
476 IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data)), num);
477
478 return num;
479}
480
481DEFUN ("round", Fround, Sround, 1, 1, 0,
482 "Return the nearest integer to ARG.")
483 (num)
484 register Lisp_Object num;
485{
486 CHECK_NUMBER_OR_FLOAT (num, 0);
487
488 if (XTYPE (num) == Lisp_Float)
56abb480
JB
489 {
490#ifdef USG
491 /* Screw the prevailing rounding mode. */
492 IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data + 0.5)), num);
493#else
494 IN_FLOAT (XSET (num, Lisp_Int, rint (XFLOAT (num)->data)), num);
495#endif
496 }
b70021f4
MR
497
498 return num;
499}
500
501DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0,
502 "Truncate a floating point number to an int.\n\
503Rounds the value toward zero.")
504 (num)
505 register Lisp_Object num;
506{
507 CHECK_NUMBER_OR_FLOAT (num, 0);
508
509 if (XTYPE (num) == Lisp_Float)
510 XSET (num, Lisp_Int, (int) XFLOAT (num)->data);
511
512 return num;
513}
514\f
4746118a 515static SIGTYPE
b70021f4
MR
516float_error (signo)
517 int signo;
518{
519 if (! in_float)
520 fatal_error_signal (signo);
521
265a9e55 522#ifdef BSD
b70021f4
MR
523#ifdef BSD4_1
524 sigrelse (SIGILL);
525#else /* not BSD4_1 */
e065a56e 526 sigsetmask (SIGEMPTYMASK);
b70021f4 527#endif /* not BSD4_1 */
265a9e55
JB
528#else
529 /* Must reestablish handler each time it is called. */
530 signal (SIGILL, float_error);
531#endif /* BSD */
b70021f4
MR
532
533 in_float = 0;
534
535 Fsignal (Qarith_error, Fcons (float_error_arg, Qnil));
536}
537
b70021f4
MR
538init_floatfns ()
539{
540 signal (SIGILL, float_error);
541 in_float = 0;
542}
543
544syms_of_floatfns ()
545{
546 defsubr (&Sacos);
b70021f4 547 defsubr (&Sasin);
b70021f4 548 defsubr (&Satan);
c2d4ea74
RS
549 defsubr (&Scos);
550 defsubr (&Ssin);
551 defsubr (&Stan);
552#if 0
553 defsubr (&Sacosh);
554 defsubr (&Sasinh);
b70021f4 555 defsubr (&Satanh);
c2d4ea74
RS
556 defsubr (&Scosh);
557 defsubr (&Ssinh);
558 defsubr (&Stanh);
b70021f4
MR
559 defsubr (&Sbessel_y0);
560 defsubr (&Sbessel_y1);
561 defsubr (&Sbessel_yn);
562 defsubr (&Sbessel_j0);
563 defsubr (&Sbessel_j1);
564 defsubr (&Sbessel_jn);
b70021f4
MR
565 defsubr (&Serf);
566 defsubr (&Serfc);
c2d4ea74 567 defsubr (&Slog_gamma);
706ac90d 568 defsubr (&Scbrt);
c2d4ea74 569#endif
b70021f4 570 defsubr (&Sexp);
c2d4ea74 571 defsubr (&Sexpt);
b70021f4
MR
572 defsubr (&Slog);
573 defsubr (&Slog10);
b70021f4 574 defsubr (&Ssqrt);
b70021f4
MR
575
576 defsubr (&Sabs);
577 defsubr (&Sfloat);
578 defsubr (&Slogb);
579 defsubr (&Sceiling);
580 defsubr (&Sfloor);
581 defsubr (&Sround);
582 defsubr (&Struncate);
583}
584
585#else /* not LISP_FLOAT_TYPE */
586
587init_floatfns ()
588{}
589
590syms_of_floatfns ()
591{}
592
593#endif /* not LISP_FLOAT_TYPE */