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