Merge branch 'fix/ppc64' into next
[sxemacs] / src / ent / floatfns.c
1 /* Primitive operations on floating point for SXEmacs Lisp interpreter.
2    Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of SXEmacs
5
6 SXEmacs 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 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs 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 this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: FSF 19.30. */
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 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?  Let me know. -jwz)
39
40    Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by
41    either setting errno, or signalling 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 <config.h>
48 #include "lisp.h"
49 #include "syssignal.h"
50
51 #include "ent.h"
52
53 #ifdef HAVE_FPFLOAT
54
55 /* The code uses emacs_rint, so that it works to undefine HAVE_RINT
56    if `rint' exists but does not work right.  */
57 #ifdef HAVE_RINT
58 #define emacs_rint rint
59 #else
60 static fpfloat emacs_rint(fpfloat x)
61 {
62         fpfloat r = floor(x + 0.5);
63         fpfloat diff = fabs(r - x);
64         /* Round to even and correct for any roundoff errors.  */
65         if (diff >= 0.5 && (diff > 0.5 || r != 2.0 * floor(r / 2.0)))
66                 r += r < x ? 1.0 : -1.0;
67         return r;
68 }
69 #endif
70
71 /* Nonzero while executing in floating point.
72    This tells float_error what to do.  */
73 static int in_float;
74
75 /* If an argument is out of range for a mathematical function,
76    here is the actual argument value to use in the error message.  */
77 static Lisp_Object float_error_arg, float_error_arg2;
78 static const char *float_error_fn_name;
79
80 /* Evaluate the floating point expression D, recording NUM
81    as the original argument for error messages.
82    D is normally an assignment expression.
83    Handle errors which may result in signals or may set errno.
84
85    Note that float_error may be declared to return void, so you can't
86    just cast the zero after the colon to (SIGTYPE) to make the types
87    check properly.  */
88 #ifdef FLOAT_CHECK_ERRNO
89 #define IN_FLOAT(d, name, num)                          \
90   do {                                                  \
91     float_error_arg = num;                              \
92     float_error_fn_name = name;                         \
93     in_float = 1; errno = 0; (d); in_float = 0;         \
94     if (errno != 0) in_float_error ();                  \
95   } while (0)
96 #define IN_FLOAT2(d, name, num, num2)                   \
97   do {                                                  \
98     float_error_arg = num;                              \
99     float_error_arg2 = num2;                            \
100     float_error_fn_name = name;                         \
101     in_float = 2; errno = 0; (d); in_float = 0;         \
102     if (errno != 0) in_float_error ();                  \
103   } while (0)
104 #else
105 #define IN_FLOAT(d, name, num) (in_float = 1, (d), in_float = 0)
106 #define IN_FLOAT2(d, name, num, num2) (in_float = 2, (d), in_float = 0)
107 #endif
108
109 #define arith_error(op,arg) \
110   Fsignal (Qarith_error, list2 (build_string (op), arg))
111 #define range_error(op,arg) \
112   Fsignal (Qrange_error, list2 (build_string (op), arg))
113 #define range_error2(op,a1,a2) \
114   Fsignal (Qrange_error, list3 (build_string (op), a1, a2))
115 #define domain_error(op,arg) \
116   Fsignal (Qdomain_error, list2 (build_string (op), arg))
117 #define domain_error2(op,a1,a2) \
118   Fsignal (Qdomain_error, list3 (build_string (op), a1, a2))
119
120 /* Convert float to Lisp Integer if it fits, else signal a range
121    error using the given arguments.
122    If numbers from multi-prec libraries are available, range errors
123    are never signaled.
124 */
125 static Lisp_Object
126 float_to_int(fpfloat x, const char *name, Lisp_Object num, Lisp_Object num2)
127 {
128 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
129         bigz_set_fpfloat(ent_scratch_bigz, x);
130         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
131
132         if (name || NILP(num) || NILP(num2));
133         return Qnil;
134 #else  /* !HAVE_MPZ */
135         REGISTER EMACS_INT result = (EMACS_INT) x;
136
137         if (result > EMACS_INT_MAX || result < EMACS_INT_MIN) {
138                 if (!UNBOUNDP(num2))
139                         range_error2(name, num, num2);
140                 else
141                         range_error(name, num);
142         }
143         return make_int(result);
144 #endif  /* HAVE_MPZ */
145 }
146
147 static void in_float_error(void)
148 {
149         switch (errno) {
150         case 0:
151                 break;
152         case EDOM:
153                 if (in_float == 2)
154                         domain_error2(float_error_fn_name, float_error_arg,
155                                       float_error_arg2);
156                 else
157                         domain_error(float_error_fn_name, float_error_arg);
158                 break;
159         case ERANGE:
160                 range_error(float_error_fn_name, float_error_arg);
161                 break;
162         default:
163                 arith_error(float_error_fn_name, float_error_arg);
164                 break;
165         }
166 }
167
168 \f
169 #endif  /* HAVE_FPFLOAT */
170 \f
171 /* Trig functions.  */
172
173 #if defined HAVE_MPFR && defined WITH_MPFR
174 #define MPFR_TRIG_FUN(op) do                                            \
175 {                                                                       \
176         Lisp_Object bfrnumber;                                          \
177                                                                         \
178         if (INDEFP(number))                                             \
179                 return make_indef(NOT_A_NUMBER);                        \
180                                                                         \
181         bigfr_set_prec(ent_scratch_bigfr,                               \
182                        internal_get_precision(precision));              \
183                                                                         \
184         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);               \
185         bigfr_##op(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));          \
186         return make_bigfr_bfr(ent_scratch_bigfr);                       \
187 } while (0)
188 #endif
189
190 #if defined(HAVE_MPFR) && defined WITH_MPFR || defined(HAVE_FPFLOAT)
191
192 DEFUN("acos", Facos, 1, 2, 0,   /*
193 Return the inverse cosine of NUMBER.
194 If optional argument PRECISION is non-nil, its value
195 (an integer) is used as precision.
196 */
197       (number, precision))
198 {
199 #if defined HAVE_MPFR && defined WITH_MPFR
200
201         MPFR_TRIG_FUN(acos);
202
203 #else  /* !HAVE_MPFR */
204         if (INDEFP(number)) {
205                 return make_indef(NOT_A_NUMBER);
206         }
207
208         number = ent_lift(number, FLOAT_T, NULL);
209
210         if (FLOATP(number)) {
211                 fpfloat d;
212                 d = acos(XFLOAT_DATA(number));
213                 return make_float(d);
214         } else if (INDEFP(number)) {
215                 return make_indef(NOT_A_NUMBER);
216         }
217
218         Fsignal(Qarith_error, list1(number));
219         return Qnil;
220 #endif  /* HAVE_MPFR */
221 }
222
223 DEFUN("asin", Fasin, 1, 2, 0,   /*
224 Return the inverse sine of NUMBER.
225 If optional argument PRECISION is non-nil, its value
226 (an integer) is used as precision.
227 */
228       (number, precision))
229 {
230 #if defined HAVE_MPFR && defined WITH_MPFR
231
232         MPFR_TRIG_FUN(asin);
233
234 #else  /* !HAVE_MPFR */
235         if (INDEFP(number)) {
236                 return make_indef(NOT_A_NUMBER);
237         }
238
239         number = ent_lift(number, FLOAT_T, NULL);
240
241         if (FLOATP(number)) {
242                 fpfloat d;
243                 d = asin(XFLOAT_DATA(number));
244                 return make_float(d);
245         } else if (INDEFP(number)) {
246                 return make_indef(NOT_A_NUMBER);
247         }
248
249         Fsignal(Qarith_error, list1(number));
250         return Qnil;
251
252         if (NILP(precision));
253 #endif  /* HAVE_MPFR */
254 }
255
256 DEFUN("atan", Fatan, 1, 3, 0,   /*
257 Return the inverse tangent of NUMBER.
258 If optional second argument NUMBER2 is provided,
259 return atan2 (NUMBER, NUMBER2).
260 If optional argument PRECISION is non-nil, its value
261 (an integer) is used as precision.
262 */
263       (number, number2, precision))
264 {
265 #if defined HAVE_MPFR && defined WITH_MPFR
266         Lisp_Object result;
267
268         if (NILP(number2)) {
269                 Lisp_Object bfrnumber;
270
271                 if (INDEFP(number))
272                         return make_indef(NOT_A_NUMBER);
273
274                 bigfr_set_prec(ent_scratch_bigfr,
275                                internal_get_precision(precision));
276                 bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
277                 bigfr_atan(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
278                 result = make_bigfr_bfr(ent_scratch_bigfr);
279         } else {
280                 Lisp_Object bfrn1;
281                 Lisp_Object bfrn2;
282
283                 if (INDEFP(number))
284                         return make_indef(NOT_A_NUMBER);
285                 if (INFINITYP(number2))
286                         return Qzero;
287                 if (INDEFP(number2))
288                         return make_indef(NOT_A_NUMBER);
289
290                 bigfr_set_prec(ent_scratch_bigfr,
291                                internal_get_precision(precision));
292                 bfrn1 = Fcoerce_number(number, Qbigfr, Qnil);
293                 bfrn2 = Fcoerce_number(number2, Qbigfr, Qnil);
294                 bigfr_atan2(ent_scratch_bigfr,
295                             XBIGFR_DATA(bfrn1),
296                             XBIGFR_DATA(bfrn2));
297                 result = make_bigfr_bfr(ent_scratch_bigfr);
298         }
299
300         return result;
301
302 #else  /* !HAVE_MPFR */
303         if (INDEFP(number)) {
304                 return make_indef(NOT_A_NUMBER);
305         }
306
307         number = ent_lift(number, FLOAT_T, NULL);
308
309         if (INDEFP(number))
310                 return make_indef(NOT_A_NUMBER);
311
312         if (NILP(number2) && FLOATP(number)) {
313                 fpfloat d;
314                 d = atan(XFLOAT_DATA(number));
315                 return make_float(d);
316         } else if (FLOATP(number)) {
317                 number = ent_lift(number2, FLOAT_T, NULL);
318
319                 if (FLOATP(number2)) {
320                         fpfloat d;
321                         d = atan2(XFLOAT_DATA(number), XFLOAT_DATA(number2));
322                         return make_float(d);
323                 } else if (INFINITYP(number2)) {
324                         return Qzero;
325                 } else if (INDEFP(number2)) {
326                         return make_indef(NOT_A_NUMBER);
327                 }
328         }
329
330         /* Just signal here, I'm not in the mood to distinguish cases here */
331         Fsignal(Qarith_error, list1(number));
332         return Qnil;
333
334         if (NILP(precision));
335 #endif  /* HAVE_MPFR */
336 }
337
338 DEFUN("cos", Fcos, 1, 2, 0,     /*
339 Return the cosine of NUMBER.
340 If optional argument PRECISION is non-nil, its value
341 (an integer) is used as precision.
342 */
343       (number, precision))
344 {
345 #if defined HAVE_MPFR && defined WITH_MPFR
346
347         MPFR_TRIG_FUN(cos);
348
349 #else  /* !HAVE_MPFR */
350         if (INDEFP(number)) {
351                 return make_indef(NOT_A_NUMBER);
352         }
353
354         number = ent_lift(number, FLOAT_T, NULL);
355
356         if (FLOATP(number)) {
357                 fpfloat d;
358                 d = cos(XFLOAT_DATA(number));
359                 return make_float(d);
360         } else if (INDEFP(number)) {
361                 return make_indef(NOT_A_NUMBER);
362         }
363
364         Fsignal(Qarith_error, list1(number));
365         return Qnil;
366
367         if (NILP(precision));
368 #endif  /* HAVE_MPFR */
369 }
370
371 DEFUN("sin", Fsin, 1, 2, 0,     /*
372 Return the sine of NUMBER.
373 If optional argument PRECISION is non-nil, its value
374 (an integer) is used as precision.
375 */
376       (number, precision))
377 {
378 #if defined HAVE_MPFR && defined WITH_MPFR
379
380         MPFR_TRIG_FUN(sin);
381
382 #else  /* !HAVE_MPFR */
383         if (INDEFP(number)) {
384                 return make_indef(NOT_A_NUMBER);
385         }
386
387         number = ent_lift(number, FLOAT_T, NULL);
388
389         if (FLOATP(number)) {
390                 fpfloat d;
391                 d = sin(XFLOAT_DATA(number));
392                 return make_float(d);
393         } else if (INDEFP(number)) {
394                 return make_indef(NOT_A_NUMBER);
395         }
396
397         Fsignal(Qarith_error, list1(number));
398         return Qnil;
399
400         if (NILP(precision));
401 #endif  /* HAVE_MPFR */
402 }
403
404 DEFUN("tan", Ftan, 1, 2, 0,     /*
405 Return the tangent of NUMBER.
406 If optional argument PRECISION is non-nil, its value
407 (an integer) is used as precision.
408 */
409       (number, precision))
410 {
411 #if defined HAVE_MPFR && defined WITH_MPFR
412
413         MPFR_TRIG_FUN(tan);
414
415 #else  /* !HAVE_MPFR */
416         if (INDEFP(number)) {
417                 return make_indef(NOT_A_NUMBER);
418         }
419
420         number = ent_lift(number, FLOAT_T, NULL);
421
422         if (FLOATP(number)) {
423                 fpfloat d;
424                 d = XFLOAT_DATA(number);
425                 d = sin(d) / cos(d);
426                 return make_float(d);
427         } else if (INDEFP(number)) {
428                 return make_indef(NOT_A_NUMBER);
429         }
430
431         Fsignal(Qarith_error, list1(number));
432         return Qnil;
433
434         if (NILP(precision));
435 #endif  /* HAVE_MPFR */
436 }
437
438 #if defined HAVE_MPFR && defined WITH_MPFR
439 DEFUN("sec", Fsec, 1, 2, 0,     /*
440 Return the secant of NUMBER.
441 If optional argument PRECISION is non-nil, its value
442 (an integer) is used as precision.
443 */
444       (number, precision))
445 {
446         MPFR_TRIG_FUN(sec);
447 }
448
449 DEFUN("csc", Fcsc, 1, 2, 0,     /*
450 Return the cosecant of NUMBER.
451 If optional argument PRECISION is non-nil, its value
452 (an integer) is used as precision.
453 */
454       (number, precision))
455 {
456         MPFR_TRIG_FUN(csc);
457 }
458
459 DEFUN("cot", Fcot, 1, 2, 0,     /*
460 Return the cotangent of NUMBER.
461 If optional argument PRECISION is non-nil, its value
462 (an integer) is used as precision.
463 */
464       (number, precision))
465 {
466         MPFR_TRIG_FUN(cot);
467 }
468 #endif  /* HAVE_MPFR */
469
470 #endif  /* HAVE_MPFR || HAVE_FPFLOAT (trig functions) */
471 \f
472 /* Bessel functions */
473 #if 0                           /* Leave these out unless we find there's a reason for them.  */
474 /* #ifdef HAVE_FPFLOAT */
475
476 DEFUN("bessel-j0", Fbessel_j0, 1, 1, 0, /*
477 Return the bessel function j0 of NUMBER.
478 */
479       (number))
480 {
481         fpfloat d = extract_float(number);
482         IN_FLOAT(d = j0(d), "bessel-j0", number);
483         return make_float(d);
484 }
485
486 DEFUN("bessel-j1", Fbessel_j1, 1, 1, 0, /*
487 Return the bessel function j1 of NUMBER.
488 */
489       (number))
490 {
491         fpfloat d = extract_float(number);
492         IN_FLOAT(d = j1(d), "bessel-j1", number);
493         return make_float(d);
494 }
495
496 DEFUN("bessel-jn", Fbessel_jn, 2, 2, 0, /*
497 Return the order N bessel function output jn of NUMBER.
498 The first number (the order) is truncated to an integer.
499 */
500       (number1, number2))
501 {
502         int i1 = extract_float(number1);
503         fpfloat f2 = extract_float(number2);
504
505         IN_FLOAT(f2 = jn(i1, f2), "bessel-jn", number1);
506         return make_float(f2);
507 }
508
509 DEFUN("bessel-y0", Fbessel_y0, 1, 1, 0, /*
510 Return the bessel function y0 of NUMBER.
511 */
512       (number))
513 {
514         fpfloat d = extract_float(number);
515         IN_FLOAT(d = y0(d), "bessel-y0", number);
516         return make_float(d);
517 }
518
519 DEFUN("bessel-y1", Fbessel_y1, 1, 1, 0, /*
520 Return the bessel function y1 of NUMBER.
521 */
522       (number))
523 {
524         fpfloat d = extract_float(number);
525         IN_FLOAT(d = y1(d), "bessel-y0", number);
526         return make_float(d);
527 }
528
529 DEFUN("bessel-yn", Fbessel_yn, 2, 2, 0, /*
530 Return the order N bessel function output yn of NUMBER.
531 The first number (the order) is truncated to an integer.
532 */
533       (number1, number2))
534 {
535         int i1 = extract_float(number1);
536         fpfloat f2 = extract_float(number2);
537
538         IN_FLOAT(f2 = yn(i1, f2), "bessel-yn", number1);
539         return make_float(f2);
540 }
541
542 #endif                          /* 0 (bessel functions) */
543
544 \f
545 /* Error functions. */
546 #if defined(HAVE_MPFR) && defined WITH_MPFR || defined(HAVE_FPFLOAT)
547 DEFUN("erf", Ferf, 1, 2, 0,     /*
548 Return the mathematical error function of NUMBER.
549 */
550       (number, precision))
551 {
552 #if defined HAVE_MPFR && defined WITH_MPFR
553
554         MPFR_TRIG_FUN(erf);
555
556 #else  /* !HAVE_MPFR */
557         if (INDEFP(number)) {
558                 return make_indef(NOT_A_NUMBER);
559         }
560
561         number = ent_lift(number, FLOAT_T, NULL);
562
563         if (FLOATP(number)) {
564                 fpfloat d;
565                 d = erf(XFLOAT_DATA(number));
566                 return make_float(d);
567         } else if (INDEFP(number)) {
568                 return make_indef(NOT_A_NUMBER);
569         }
570
571         Fsignal(Qarith_error, list1(number));
572         return Qnil;
573
574         if (NILP(precision));
575 #endif  /* HAVE_MPFR */
576 }
577
578 DEFUN("erfc", Ferfc, 1, 2, 0,   /*
579 Return the complementary error function of NUMBER.
580 */
581       (number, precision))
582 {
583 #if defined HAVE_MPFR && defined WITH_MPFR
584
585         MPFR_TRIG_FUN(erfc);
586
587 #else  /* !HAVE_MPFR */
588         if (INDEFP(number)) {
589                 return make_indef(NOT_A_NUMBER);
590         }
591
592         number = ent_lift(number, FLOAT_T, NULL);
593
594         if (FLOATP(number)) {
595                 fpfloat d;
596                 d = erfc(XFLOAT_DATA(number));
597                 return make_float(d);
598         } else if (INDEFP(number)) {
599                 return make_indef(NOT_A_NUMBER);
600         }
601
602         Fsignal(Qarith_error, list1(number));
603         return Qnil;
604
605         if (NILP(precision));
606 #endif  /* HAVE_MPFR */
607 }
608
609 DEFUN("log-gamma", Flog_gamma, 1, 2, 0, /*
610 Return the log gamma of NUMBER.
611 */
612       (number, precision))
613 {
614 #if defined HAVE_MPFR && defined WITH_MPFR
615
616         MPFR_TRIG_FUN(lgamma);
617
618 #else  /* !HAVE_MPFR */
619         if (INDEFP(number)) {
620                 return make_indef(NOT_A_NUMBER);
621         }
622
623         number = ent_lift(number, FLOAT_T, NULL);
624
625         if (FLOATP(number)) {
626                 fpfloat d;
627                 d = lgamma(XFLOAT_DATA(number));
628                 return make_float(d);
629         } else if (INDEFP(number)) {
630                 return make_indef(NOT_A_NUMBER);
631         }
632
633         Fsignal(Qarith_error, list1(number));
634         return Qnil;
635
636         if (NILP(precision));
637 #endif  /* HAVE_MPFR */
638 }
639 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
640
641 \f
642 /* Root and Log functions. */
643
644 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
645 DEFUN("exp", Fexp, 1, 2, 0,     /*
646 Return the exponential base e of NUMBER.
647 If optional argument PRECISION is non-nil, its value
648 (an integer) is used as precision.
649 */
650       (number, precision))
651 {
652 /* Attention, somehow the precision must be large enough to make the result
653  * fit, otherwise this is a good memory test :)
654  */
655 #if defined(HAVE_MPFR) && defined WITH_MPFR ||  \
656         defined(HAVE_MPC) && defined WITH_MPC ||        \
657         defined HAVE_PSEUC && defined WITH_PSEUC
658
659         if (INDEFP(number)) {
660                 if (XINDEF_DATA(number) == POS_INFINITY)
661                         return number;
662                 else if (XINDEF_DATA(number) == NEG_INFINITY)
663                         return Fcoerce_number(Qzero, Qbigfr, precision);
664                 else
665                         return number;
666         }
667
668         if (COMPARABLEP(number)) {
669 #if defined HAVE_MPFR && defined WITH_MPFR
670                 Lisp_Object bfrnumber;
671
672                 bigfr_set_prec(ent_scratch_bigfr,
673                                internal_get_precision(precision));
674
675                 bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
676                 bigfr_exp(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
677                 return make_bigfr_bfr(ent_scratch_bigfr);
678
679 #endif  /* HAVE_MPFR */
680 #if defined HAVE_MPC && defined WITH_MPC ||     \
681         defined HAVE_PSEUC && defined WITH_PSEUC
682         } else if (BIGCP(number)) {
683                 bigc_set_prec(ent_scratch_bigc,
684                               internal_get_precision(precision));
685
686                 bigc_exp(ent_scratch_bigc, XBIGC_DATA(number));
687                 return make_bigc_bc(ent_scratch_bigc);
688 #endif  /* HAVE_MPC */
689         }
690
691         return wrong_type_argument(Qnumberp, number);
692 #else  /* !HAVE_MPFR && !HAVE_MPC */
693         if (INDEFP(number)) {
694                 goto indefcase;
695         }
696
697         number = ent_lift(number, FLOAT_T, NULL);
698
699         if (FLOATP(number)) {
700                 fpfloat d;
701                 d = exp(XFLOAT_DATA(number));
702                 return make_float(d);
703         } else if (INDEFP(number)) {
704         indefcase:
705                 if (XINDEF_DATA(number) == POS_INFINITY)
706                         return number;
707                 else if (XINDEF_DATA(number) == NEG_INFINITY)
708                         return Fcoerce_number(Qzero, Qfloat, precision);
709                 else
710                         return number;
711         }
712
713         Fsignal(Qarith_error, list1(number));
714         return Qnil;
715
716         if (NILP(precision));
717 #endif  /* HAVE_MPFR */
718 }
719 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
720
721 DEFUN("2^", Fexp2, 1, 2, 0,     /*
722 Return the exponential of NUMBER to 2 power.
723 If optional argument PRECISION is non-nil, its value
724 \(an integer\) is used as precision in float computations.
725 */
726       (number, precision))
727 {
728 #if defined HAVE_MPFR && defined WITH_MPFR
729         Lisp_Object bfrnumber;
730 #endif
731 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
732         if (INTP(number))
733                 return _ent_binop(ASE_BINARY_OP_POW,
734                                   INT_T, make_int(2), INT_T, number);
735 #endif
736         if (INDEFP(number))
737                 return _ent_binop(ASE_BINARY_OP_POW,
738                                   INT_T, make_int(2), INDEF_T, number);
739
740 #if defined HAVE_MPFR && defined WITH_MPFR
741         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
742         bigfr_set_prec(ent_scratch_bigfr,
743                        internal_get_precision(precision));
744
745         bigfr_exp2(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
746         return make_bigfr_bfr(ent_scratch_bigfr);
747 #endif
748         /* fallback */
749         if (NILP(precision));
750         return Qnil;
751 }
752
753 DEFUN("10^", Fexp10, 1, 2, 0,   /*
754 Return the exponential of NUMBER to 10 power.
755 If optional argument PRECISION is non-nil, its value
756 \(an integer\) is used as precision in float computations.
757 */
758       (number, precision))
759 {
760 #if defined HAVE_MPFR && defined WITH_MPFR
761         Lisp_Object bfrnumber;
762 #endif
763 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
764         if (INTP(number))
765                 return _ent_binop(ASE_BINARY_OP_POW,
766                                   INT_T, make_int(10), INT_T, number);
767 #endif
768         if (INDEFP(number))
769                 return _ent_binop(ASE_BINARY_OP_POW,
770                                   INT_T, make_int(10), INDEF_T, number);
771
772 #if defined HAVE_MPFR && defined WITH_MPFR
773         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
774         bigfr_set_prec(ent_scratch_bigfr,
775                        internal_get_precision(precision));
776
777         bigfr_exp10(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
778         return make_bigfr_bfr(ent_scratch_bigfr);
779 #endif
780         /* fallback */
781         if (NILP(precision));
782         return Qnil;
783 }
784
785 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
786 DEFUN("log", Flog, 1, 3, 0,     /*
787 Return the natural logarithm of NUMBER.
788 If second optional argument BASE is given, return the logarithm of
789 NUMBER using that base.
790 If third optional argument PRECISION is given, use its value
791 (an integer) as precision.
792 */
793       (number, base, precision))
794 {
795 #if defined HAVE_MPFR && defined WITH_MPFR
796         Lisp_Object bfrnumber;
797
798         if (!NILP(base)) {
799                 Lisp_Object _logn, _logb;
800                 _logn = Flog(number, Qnil, precision);
801                 if (UNLIKELY(INDEFP(_logn))) {
802                         return _logn;
803                 }
804                 _logb = Flog(base, Qnil, precision);
805                 return ent_binop(ASE_BINARY_OP_QUO, _logn, _logb);
806         }
807
808         if (INDEFP(number)) {
809                 if (XINDEF_DATA(number) == POS_INFINITY) {
810                         return number;
811                 } else if (XINDEF_DATA(number) == NEG_INFINITY) {
812                         return make_indef(NOT_A_NUMBER);
813                 } else {
814                         return number;
815                 }
816         }
817
818         bigfr_set_prec(ent_scratch_bigfr,
819                        internal_get_precision(precision));
820
821         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
822         bigfr_log(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
823         return make_bigfr_bfr(ent_scratch_bigfr);
824
825 #else  /* !HAVE_MPFR */
826         if (INDEFP(number)) {
827                 goto indefcase;
828         }
829
830         number = ent_lift(number, FLOAT_T, NULL);
831
832         if (FLOATP(number)) {
833                 fpfloat d;
834                 d = log(XFLOAT_DATA(number));
835                 return make_float(d);
836         } else if (INDEFP(number)) {
837         indefcase:
838                 if (XINDEF_DATA(number) == POS_INFINITY) {
839                         return number;
840                 } else if (XINDEF_DATA(number) == NEG_INFINITY) {
841                         return make_indef(NOT_A_NUMBER);
842                 } else {
843                         return number;
844                 }
845         }
846
847         Fsignal(Qarith_error, list1(number));
848         return Qnil;
849
850         if (NILP(precision));
851 #endif  /* HAVE_MPFR */
852 }
853
854 DEFUN("log10", Flog10, 1, 2, 0, /*
855 Return the logarithm base 10 of NUMBER.
856 If second optional argument PRECISION is given, use its value
857 (an integer) as precision.
858 */
859       (number, precision))
860 {
861 #if defined HAVE_MPFR && defined WITH_MPFR
862         Lisp_Object bfrnumber;
863
864         if (INDEFP(number)) {
865                 if (XINDEF_DATA(number) == POS_INFINITY)
866                         return number;
867                 else if (XINDEF_DATA(number) == NEG_INFINITY)
868                         return make_indef(NOT_A_NUMBER);
869                 else
870                         return number;
871         }
872
873         bigfr_set_prec(ent_scratch_bigfr,
874                        internal_get_precision(precision));
875
876         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
877         bigfr_log10(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
878         return make_bigfr_bfr(ent_scratch_bigfr);
879
880 #else  /* !HAVE_MPFR */
881         if (INDEFP(number)) {
882                 goto indefcase;
883         }
884
885         number = ent_lift(number, FLOAT_T, NULL);
886
887         if (FLOATP(number)) {
888                 fpfloat d;
889                 d = log10(XFLOAT_DATA(number));
890                 return make_float(d);
891         } else if (INDEFP(number)) {
892         indefcase:
893                 if (XINDEF_DATA(number) == POS_INFINITY)
894                         return number;
895                 else if (XINDEF_DATA(number) == NEG_INFINITY)
896                         return make_indef(NOT_A_NUMBER);
897                 else
898                         return number;
899         }
900
901         Fsignal(Qarith_error, list1(number));
902         return Qnil;
903
904         if (NILP(precision));
905 #endif  /* HAVE_MPFR */
906 }
907
908 #if defined HAVE_MPFR && defined WITH_MPFR
909 DEFUN("log2", Flog2, 1, 2, 0,   /*
910 Return the logarithm base 2 of NUMBER.
911 If second optional argument PRECISION is given, use its value
912 (an integer) as precision.
913 */
914       (number, precision))
915 {
916         Lisp_Object bfrnumber;
917
918         if (INDEFP(number)) {
919                 if (XINDEF_DATA(number) == POS_INFINITY)
920                         return number;
921                 else if (XINDEF_DATA(number) == NEG_INFINITY)
922                         return make_indef(NOT_A_NUMBER);
923                 else
924                         return number;
925         }
926
927         bigfr_set_prec(ent_scratch_bigfr,
928                        internal_get_precision(precision));
929
930         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
931         bigfr_log2(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
932         return make_bigfr_bfr(ent_scratch_bigfr);
933 }
934 #endif  /* HAVE_MPFR */
935
936
937 DEFUN("sqrt", Fsqrt, 1, 2, 0,   /*
938 Return the square root of NUMBER.
939 If second optional argument PRECISION is given, use its value
940 (an integer) as precision.
941 */
942       (number, precision))
943 {
944 #if defined(HAVE_MPFR) && defined WITH_MPFR ||  \
945         defined(HAVE_MPC) && defined WITH_MPC ||        \
946         defined(HAVE_PSEUC) && defined WITH_PSEUC
947
948         if (INDEFP(number)) {
949                 if (XINDEF_DATA(number) == POS_INFINITY)
950                         return number;
951                 else if (XINDEF_DATA(number) == NEG_INFINITY)
952                         return make_indef(COMPLEX_INFINITY);
953                 else
954                         return number;
955         }
956
957         if (COMPARABLEP(number)) {
958 #if defined HAVE_MPFR && defined WITH_MPFR
959                 bigfr_set_prec(ent_scratch_bigfr,
960                                internal_get_precision(precision));
961
962                 if (NATNUMP(number))
963                         bigfr_sqrt_ui(ent_scratch_bigfr,
964                                       (unsigned long)XUINT(number));
965                 else if (BIGZP(number) &&
966                          bigz_fits_ulong_p(XBIGZ_DATA(number)) &&
967                          bigz_sign(XBIGZ_DATA(number)) >= 0) {
968                         bigfr_sqrt_ui(ent_scratch_bigfr,
969                                       (unsigned long)bigz_to_ulong(
970                                               XBIGZ_DATA(number)));
971                 } else if (!NILP(Fnonnegativep(number))) {
972                         Lisp_Object bfrnumber;
973                         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
974                         bigfr_sqrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
975                 } else {
976 #if defined HAVE_MPC && defined WITH_MPC ||     \
977         defined HAVE_PSEUC && defined WITH_PSEUC
978                         Lisp_Object bcnumber;
979                         bigc_set_prec(ent_scratch_bigc,
980                                       internal_get_precision(precision));
981                         bcnumber = Fcoerce_number(number, Qbigc, precision);
982                         bigc_sqrt(ent_scratch_bigc, XBIGC_DATA(bcnumber));
983                         return make_bigc_bc(ent_scratch_bigc);
984 #else  /* !HAVE_MPC */
985                         Lisp_Object bfrnumber;
986                         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
987                         bigfr_sqrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
988 #endif  /* HAVE_MPC */
989                 }
990                 return make_bigfr_bfr(ent_scratch_bigfr);
991 #endif  /* HAVE_MPFR */
992 #if defined HAVE_MPC && defined WITH_MPC ||     \
993         defined HAVE_PSEUC && defined WITH_PSEUC
994         } else if (BIGCP(number) || BIGGP(number)) {
995                 Lisp_Object bcnumber;
996                 bigc_set_prec(ent_scratch_bigc,
997                               internal_get_precision(precision));
998
999                 bcnumber = Fcoerce_number(number, Qbigc, precision);
1000                 bigc_sqrt(ent_scratch_bigc, XBIGC_DATA(bcnumber));
1001                 return make_bigc_bc(ent_scratch_bigc);
1002 #endif  /* HAVE_MPC */
1003         }
1004
1005         if (NILP(precision));
1006         return wrong_type_argument(Qnumberp, number);
1007
1008 #else  /* !HAVE_MPFR && !HAVE_MPC */
1009         if (INDEFP(number)) {
1010                 goto indefcase;
1011         }
1012
1013         number = ent_lift(number, FLOAT_T, NULL);
1014
1015         if (FLOATP(number)) {
1016                 fpfloat d;
1017                 d = sqrt(XFLOAT_DATA(number));
1018                 return make_float(d);
1019         } else if (INDEFP(number)) {
1020         indefcase:
1021                 if (XINDEF_DATA(number) == POS_INFINITY)
1022                         return number;
1023                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1024                         return make_indef(COMPLEX_INFINITY);
1025                 else
1026                         return number;
1027         }
1028
1029         Fsignal(Qarith_error, list1(number));
1030         return Qnil;
1031
1032         if (NILP(precision));
1033 #endif  /* HAVE_MPFR */
1034 }
1035
1036 DEFUN("cube-root", Fcube_root, 1, 2, 0, /*
1037 Return the cube root of NUMBER.
1038 If second optional argument PRECISION is given, use its value
1039 (an integer) as precision.
1040 */
1041       (number, precision))
1042 {
1043 #if defined HAVE_MPFR && defined WITH_MPFR
1044         Lisp_Object bfrnumber;
1045
1046         if (INDEFP(number))
1047                 return number;
1048
1049         bigfr_set_prec(ent_scratch_bigfr,
1050                        internal_get_precision(precision));
1051
1052         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1053         bigfr_cbrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
1054         return make_bigfr_bfr(ent_scratch_bigfr);
1055
1056 #else  /* !HAVE_MPFR */
1057         if (INDEFP(number)) {
1058                 goto indefcase;
1059         }
1060
1061         number = ent_lift(number, FLOAT_T, NULL);
1062
1063         if (FLOATP(number)) {
1064                 fpfloat d;
1065 #ifdef HAVE_CBRT
1066                 d = cbrt(XFLOAT_DATA(number));
1067 #else
1068                 d = XFLOAT_DATA(number);
1069                 if (d >= 0.0)
1070                         d = pow(d, 1.0 / 3.0);
1071                 else
1072                         d = -pow(-d, 1.0 / 3.0);
1073 #endif
1074                 return make_float(d);
1075         } else if (INDEFP(number)) {
1076         indefcase:
1077                 return number;
1078         }
1079
1080         Fsignal(Qarith_error, list1(number));
1081         return Qnil;
1082
1083         if (NILP(precision));
1084 #endif  /* HAVE_MPFR */
1085 }
1086 #endif  /* HAVE_FPFLOAT || MPFR */
1087
1088
1089 #if defined HAVE_MPFR && defined WITH_MPFR
1090 DEFUN("root", Froot, 2, 3, 0,   /*
1091 Return the RADIX-th root of NUMBER.
1092 If third optional argument PRECISION is given, use its value
1093 (an integer) as precision.
1094 */
1095       (number, radix, precision))
1096 {
1097         Lisp_Object bfrnumber;
1098
1099         if (!NATNUMP(radix)) {
1100                 dead_wrong_type_argument(Qnatnump, radix);
1101                 return Qnil;
1102         }
1103
1104         if (INDEFP(number)) {
1105                 if (XINDEF_DATA(number) == POS_INFINITY)
1106                         return number;
1107                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1108                         return make_indef(COMPLEX_INFINITY);
1109                 else
1110                         return number;
1111         }
1112
1113         bigfr_set_prec(ent_scratch_bigfr,
1114                        internal_get_precision(precision));
1115
1116         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1117         bigfr_root(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber), XUINT(radix));
1118         return make_bigfr_bfr(ent_scratch_bigfr);
1119 }
1120 #endif  /* HAVE_MPFR */
1121
1122 \f
1123 /* (Inverse) hyperbolic trig functions. */
1124 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
1125
1126 DEFUN("acosh", Facosh, 1, 2, 0, /*
1127 Return the inverse hyperbolic cosine of NUMBER.
1128 If optional argument PRECISION is non-nil, its value
1129 (an integer) is used as precision.
1130 */
1131       (number, precision))
1132 {
1133 #if defined HAVE_MPFR && defined WITH_MPFR
1134
1135         MPFR_TRIG_FUN(acosh);
1136
1137 #else  /* !HAVE_MPFR */
1138         if (INDEFP(number)) {
1139                 return make_indef(NOT_A_NUMBER);
1140         }
1141
1142         number = ent_lift(number, FLOAT_T, NULL);
1143
1144         if (FLOATP(number)) {
1145                 fpfloat d = XFLOAT_DATA(number);
1146 #ifdef HAVE_INVERSE_HYPERBOLIC
1147                 d = acosh(d);
1148 #else
1149                 d = log(d + sqrt(d * d - 1.0));
1150 #endif
1151                 return make_float(d);
1152         } else if (INDEFP(number)) {
1153                 return make_indef(NOT_A_NUMBER);
1154         }
1155
1156         Fsignal(Qarith_error, list1(number));
1157         return Qnil;
1158
1159         if (NILP(precision));
1160 #endif  /* HAVE_MPFR */
1161 }
1162
1163 DEFUN("asinh", Fasinh, 1, 2, 0, /*
1164 Return the inverse hyperbolic sine of NUMBER.
1165 If optional argument PRECISION is non-nil, its value
1166 (an integer) is used as precision.
1167 */
1168       (number, precision))
1169 {
1170 #if defined HAVE_MPFR && defined WITH_MPFR
1171
1172         MPFR_TRIG_FUN(asinh);
1173
1174 #else  /* !HAVE_MPFR */
1175         if (INDEFP(number)) {
1176                 return make_indef(NOT_A_NUMBER);
1177         }
1178
1179         number = ent_lift(number, FLOAT_T, NULL);
1180
1181         if (FLOATP(number)) {
1182                 fpfloat d = XFLOAT_DATA(number);
1183 #ifdef HAVE_INVERSE_HYPERBOLIC
1184                 d = acosh(d);
1185 #else
1186                 d = log(d + sqrt(d * d + 1.0));
1187 #endif
1188                 return make_float(d);
1189         } else if (INDEFP(number)) {
1190                 return make_indef(NOT_A_NUMBER);
1191         }
1192
1193         Fsignal(Qarith_error, list1(number));
1194         return Qnil;
1195
1196         if (NILP(precision));
1197 #endif  /* HAVE_MPFR */
1198 }
1199
1200 DEFUN("atanh", Fatanh, 1, 2, 0, /*
1201 Return the inverse hyperbolic tangent of NUMBER.
1202 If optional argument PRECISION is non-nil, its value
1203 (an integer) is used as precision.
1204 */
1205       (number, precision))
1206 {
1207 #if defined HAVE_MPFR && defined WITH_MPFR
1208
1209         MPFR_TRIG_FUN(atanh);
1210
1211 #else  /* !HAVE_MPFR */
1212         if (INDEFP(number)) {
1213                 return make_indef(NOT_A_NUMBER);
1214         }
1215
1216         number = ent_lift(number, FLOAT_T, NULL);
1217
1218         if (FLOATP(number)) {
1219                 fpfloat d = XFLOAT_DATA(number);
1220 #ifdef HAVE_INVERSE_HYPERBOLIC
1221                 d = atanh(d);
1222 #else
1223                 d = 0.5 * log((1.0 + d) / (1.0 - d));
1224 #endif
1225                 return make_float(d);
1226         } else if (INDEFP(number)) {
1227                 return make_indef(NOT_A_NUMBER);
1228         }
1229
1230         Fsignal(Qarith_error, list1(number));
1231         return Qnil;
1232
1233         if (NILP(precision));
1234 #endif  /* HAVE_MPFR */
1235 }
1236
1237 DEFUN("cosh", Fcosh, 1, 2, 0,   /*
1238 Return the hyperbolic cosine of NUMBER.
1239 If optional argument PRECISION is non-nil, its value
1240 (an integer) is used as precision.
1241 */
1242       (number, precision))
1243 {
1244 #if defined HAVE_MPFR && defined WITH_MPFR
1245
1246         MPFR_TRIG_FUN(cosh);
1247
1248 #else  /* !HAVE_MPFR */
1249         if (INDEFP(number)) {
1250                 return make_indef(NOT_A_NUMBER);
1251         }
1252
1253         number = ent_lift(number, FLOAT_T, NULL);
1254
1255         if (FLOATP(number)) {
1256                 fpfloat d;
1257                 d = cosh(XFLOAT_DATA(number));
1258                 return make_float(d);
1259         } else if (INDEFP(number)) {
1260                 return make_indef(NOT_A_NUMBER);
1261         }
1262
1263         Fsignal(Qarith_error, list1(number));
1264         return Qnil;
1265
1266         if (NILP(precision));
1267 #endif  /* HAVE_MPFR */
1268 }
1269
1270 DEFUN("sinh", Fsinh, 1, 2, 0,   /*
1271 Return the hyperbolic sine of NUMBER.
1272 If optional argument PRECISION is non-nil, its value
1273 (an integer) is used as precision.
1274 */
1275       (number, precision))
1276 {
1277 #if defined HAVE_MPFR && defined WITH_MPFR
1278
1279         MPFR_TRIG_FUN(sinh);
1280
1281 #else  /* !HAVE_MPFR */
1282         if (INDEFP(number)) {
1283                 return make_indef(NOT_A_NUMBER);
1284         }
1285
1286         number = ent_lift(number, FLOAT_T, NULL);
1287
1288         if (FLOATP(number)) {
1289                 fpfloat d;
1290                 d = sinh(XFLOAT_DATA(number));
1291                 return make_float(d);
1292         } else if (INDEFP(number)) {
1293                 return make_indef(NOT_A_NUMBER);
1294         }
1295
1296         Fsignal(Qarith_error, list1(number));
1297         return Qnil;
1298
1299         if (NILP(precision));
1300 #endif  /* HAVE_MFPR */
1301 }
1302
1303 DEFUN("tanh", Ftanh, 1, 2, 0,   /*
1304 Return the hyperbolic tangent of NUMBER.
1305 If optional argument PRECISION is non-nil, its value
1306 (an integer) is used as precision.
1307 */
1308       (number, precision))
1309 {
1310 #if defined HAVE_MPFR && defined WITH_MPFR
1311
1312         MPFR_TRIG_FUN(tanh);
1313
1314 #else  /* !HAVE_MPFR */
1315         if (INDEFP(number)) {
1316                 return make_indef(NOT_A_NUMBER);
1317         }
1318
1319         number = ent_lift(number, FLOAT_T, NULL);
1320
1321         if (FLOATP(number)) {
1322                 fpfloat d = XFLOAT_DATA(number);
1323                 d = tanh(d);
1324                 return make_float(d);
1325         } else if (INDEFP(number)) {
1326                 return make_indef(NOT_A_NUMBER);
1327         }
1328
1329         Fsignal(Qarith_error, list1(number));
1330         return Qnil;
1331
1332         if (NILP(precision));
1333 #endif  /* HAVE_MPFR */
1334 }
1335
1336 #if defined HAVE_MPFR && defined WITH_MPFR
1337
1338 DEFUN("sech", Fsech, 1, 2, 0,   /*
1339 Return the hyperbolic secant of NUMBER.
1340 If optional argument PRECISION is non-nil, its value
1341 (an integer) is used as precision.
1342 */
1343       (number, precision))
1344 {
1345         MPFR_TRIG_FUN(sech);
1346 }
1347
1348 DEFUN("csch", Fcsch, 1, 2, 0,   /*
1349 Return the hyperbolic cosecant of NUMBER.
1350 If optional argument PRECISION is non-nil, its value
1351 (an integer) is used as precision.
1352 */
1353       (number, precision))
1354 {
1355         MPFR_TRIG_FUN(csch);
1356 }
1357
1358 DEFUN("coth", Fcoth, 1, 2, 0,   /*
1359 Return the hyperbolic cotangent of NUMBER.
1360 If optional argument PRECISION is non-nil, its value
1361 (an integer) is used as precision.
1362 */
1363       (number, precision))
1364 {
1365         MPFR_TRIG_FUN(coth);
1366 }
1367 #endif  /* HAVE_MPFR */
1368
1369 #endif  /* HAVE_MPFR || HAVE_FPFLOAT (inverse trig functions) */
1370
1371 \f
1372 /* Rounding functions */
1373
1374 DEFUN("abs", Fabs, 1, 1, 0,     /*
1375 Return the absolute value of NUMBER.
1376 */
1377       (number))
1378 {
1379 #ifdef HAVE_FPFLOAT
1380         if (FLOATP(number)) {
1381                 return make_float(fabs(XFLOAT_DATA(number)));
1382         }
1383 #endif                          /* HAVE_FPFLOAT */
1384
1385         if (INTP(number)) {
1386 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1387                 /* The most negative Lisp int will overflow */
1388                 return (XINT(number) >= 0)
1389                         ? number : make_integer(-XINT(number));
1390 #else  /* !HAVE_MPZ */
1391                 return (XINT(number) >= 0) ? number : make_int(-XINT(number));
1392 #endif  /* HAVE_MPZ */
1393         }
1394
1395 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1396         if (BIGZP(number)) {
1397                 if (bigz_sign(XBIGZ_DATA(number)) >= 0)
1398                         return number;
1399
1400                 bigz_abs(ent_scratch_bigz, XBIGZ_DATA(number));
1401                 return make_bigz_bz(ent_scratch_bigz);
1402         }
1403 #endif  /* HAVE_MPZ */
1404
1405 #if defined HAVE_MPQ && defined WITH_GMP
1406         if (BIGQP(number)) {
1407                 if (bigq_sign(XBIGQ_DATA(number)) >= 0)
1408                         return number;
1409
1410                 bigq_abs(ent_scratch_bigq, XBIGQ_DATA(number));
1411                 return make_bigq_bq(ent_scratch_bigq);
1412         }
1413 #endif  /* HAVE_MPQ */
1414
1415 #if defined HAVE_MPF && defined WITH_GMP
1416         if (BIGFP(number)) {
1417                 if (bigf_sign(XBIGF_DATA (number)) >= 0)
1418                         return number;
1419
1420                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
1421
1422                 bigf_abs(ent_scratch_bigf, XBIGF_DATA(number));
1423                 return make_bigf_bf(ent_scratch_bigf);
1424         }
1425 #endif  /* HAVE_MPF */
1426
1427 #if defined HAVE_MPFR && defined WITH_MPFR
1428         if (BIGFRP(number)) {
1429                 if (bigfr_sign(XBIGFR_DATA (number)) >= 0)
1430                         return number;
1431
1432                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
1433
1434                 bigfr_abs(ent_scratch_bigfr, XBIGFR_DATA(number));
1435                 return make_bigfr_bfr(ent_scratch_bigfr);
1436         }
1437 #endif  /* HAVE_MPFR */
1438
1439 #if defined(HAVE_PSEUG) && defined WITH_PSEUG && defined(HAVE_MPFR)
1440         if (BIGGP(number)) {
1441                 bigfr_set_prec(ent_scratch_bigfr,
1442                                internal_get_precision(Qnil));
1443
1444                 bigg_abs(ent_scratch_bigfr, XBIGG_DATA(number));
1445                 return make_bigfr_bfr(ent_scratch_bigfr);
1446         }
1447 #endif  /* HAVE_PSEUG && HAVE_MPFR */
1448
1449 #if defined HAVE_MPC && defined WITH_MPC ||     \
1450         defined HAVE_PSEUC && defined WITH_PSEUC
1451         if (BIGCP(number)) {
1452                 bigfr_set_prec(ent_scratch_bigfr, XBIGC_GET_PREC(number));
1453
1454                 if (bigc_nan_p(XBIGC_DATA(number)))
1455                         return make_indef(NOT_A_NUMBER);
1456                 else if (bigc_inf_p(XBIGC_DATA(number)))
1457                         return make_indef(POS_INFINITY);
1458                 else
1459                         bigc_abs(ent_scratch_bigfr, XBIGC_DATA(number));
1460
1461                 return make_bigfr_bfr(ent_scratch_bigfr);
1462         }
1463 #endif  /* HAVE_PSEUG */
1464
1465         if (INDEFP(number)) {
1466                 if (XINDEF_DATA(number) == POS_INFINITY)
1467                         return number;
1468                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1469                         return make_indef(POS_INFINITY);
1470                 else
1471                         return number;
1472         }
1473
1474         return Fabs(wrong_type_argument(Qnumberp, number));
1475 }
1476
1477 #if defined(HAVE_FPFLOAT)
1478 /* fuck fuck fuck, I want this in number.el */
1479 DEFUN("float", Ffloat, 1, 1, 0, /*
1480 Return the floating point number numerically equal to NUMBER.
1481 */
1482       (number))
1483 {
1484         /* Just create the float in order of preference */
1485         return Fcoerce_number(number, Qfloat, Qnil);
1486 }
1487 #endif  /* HAVE_FPFLOAT */
1488
1489 #ifdef HAVE_FPFLOAT
1490 DEFUN("logb", Flogb, 1, 1, 0,   /*
1491 Return largest integer <= the base 2 log of the magnitude of NUMBER.
1492 This is the same as the exponent of a float.
1493 */
1494       (number))
1495 {
1496         fpfloat f = extract_float(number);
1497
1498         if (f == 0.0)
1499                 return make_int(EMACS_INT_MIN);
1500 #ifdef HAVE_LOGB
1501         {
1502                 fpfloat _lb = logb(f);
1503                 Lisp_Object val;
1504                 IN_FLOAT(val = make_int((EMACS_INT)_lb), "logb", number);
1505                 return val;
1506         }
1507 #else
1508 #ifdef HAVE_FREXP
1509         {
1510                 int exqp;
1511                 IN_FLOAT(frexp(f, &exqp), "logb", number);
1512                 return make_int(exqp - 1);
1513         }
1514 #else
1515         {
1516                 int i;
1517                 fpfloat d;
1518                 EMACS_INT val;
1519                 if (f < 0.0)
1520                         f = -f;
1521                 val = -1;
1522                 while (f < 0.5) {
1523                         for (i = 1, d = 0.5; d * d >= f; i += i)
1524                                 d *= d;
1525                         f /= d;
1526                         val -= i;
1527                 }
1528                 while (f >= 1.0) {
1529                         for (i = 1, d = 2.0; d * d <= f; i += i)
1530                                 d *= d;
1531                         f /= d;
1532                         val += i;
1533                 }
1534                 return make_int(val);
1535         }
1536 #endif                          /* ! HAVE_FREXP */
1537 #endif                          /* ! HAVE_LOGB */
1538 }
1539 #endif                          /* HAVE_FPFLOAT */
1540
1541 DEFUN("ceiling", Fceiling, 1, 1, 0,     /*
1542 Return the smallest integer no less than NUMBER.  (Round toward +inf.)
1543 */
1544       (number))
1545 {
1546 #ifdef HAVE_FPFLOAT
1547         if (FLOATP(number)) {
1548                 fpfloat d;
1549                 d = ceil(XFLOAT_DATA(number));
1550                 return (float_to_int(d, "ceiling", number, Qunbound));
1551         }
1552 #endif                          /* HAVE_FPFLOAT */
1553
1554 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1555         if (INTEGERP(number))
1556 #else  /* !HAVE_MPZ */
1557         if (INTP(number))
1558 #endif  /* HAVE_MPZ */
1559                 return number;
1560
1561 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1562         if (BIGQP(number)) {
1563                 bigz_ceil(ent_scratch_bigz,
1564                           XBIGQ_NUMERATOR(number),
1565                           XBIGQ_DENOMINATOR(number));
1566                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1567         }
1568 #endif
1569
1570 #if defined HAVE_MPF && defined WITH_GMP
1571         else if (BIGFP(number)) {
1572 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1573                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
1574                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1575                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1576 #else  /* !HAVE_MPZ */
1577                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
1578                 return make_int((EMACS_INT)bigf_to_long(ent_scratch_bigf));
1579 #endif  /* HAVE_MPZ */
1580         }
1581 #endif  /* HAVE_MPF */
1582
1583 #if defined HAVE_MPFR && defined WITH_MPFR
1584         else if (BIGFRP(number)) {
1585 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1586                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
1587                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1588                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1589 #else  /* !HAVE_MPZ */
1590                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
1591                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1592 #endif  /* HAVE_MPZ */
1593         }
1594 #endif  /* HAVE_MPFR */
1595
1596         if (INDEFP(number))
1597                 return number;
1598
1599 #if defined HAVE_MPC && defined WITH_MPC ||     \
1600         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1601         defined HAVE_PSEUG && defined WITH_PSEUG
1602         return Fceiling(wrong_type_argument(Qcomparablep, number));
1603 #else  /* !HAVE_MPC */
1604         return Fceiling(wrong_type_argument(Qnumberp, number));
1605 #endif  /* HAVE_MPC */
1606 }
1607
1608 DEFUN("floor", Ffloor, 1, 2, 0, /*
1609 Return the largest integer no greater than NUMBER.  (Round towards -inf.)
1610 With optional second argument DIVISOR, return the largest integer no
1611 greater than NUMBER/DIVISOR.
1612 */
1613       (number, divisor))
1614 {
1615         ase_object_type_t ntquo;
1616         Lisp_Object quo;
1617
1618         CHECK_COMPARABLE(number);
1619         if (NILP(divisor)) {
1620                 return Ffloor(number, make_int(1L));
1621
1622         }
1623
1624         /* !NILP(divisor) */
1625
1626         CHECK_COMPARABLE(divisor);
1627
1628         if (INTEGERP(number) && INTEGERP(divisor)) {
1629 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1630                 /* this is the optimised version, since
1631                  * bigz_floor always takes two arguments
1632                  */
1633                 number = ent_lift(number, BIGZ_T, NULL);
1634                 divisor = ent_lift(divisor, BIGZ_T, NULL);
1635
1636                 bigz_floor(ent_scratch_bigz,
1637                            XBIGZ_DATA(number),
1638                            XBIGZ_DATA(divisor));
1639                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1640 #else
1641                 number = ent_lift(number, FLOAT_T, NULL);
1642                 divisor = ent_lift(divisor, FLOAT_T, NULL);
1643 #endif
1644         }
1645
1646         quo = ent_binop(ASE_BINARY_OP_QUO, number, divisor);
1647         ntquo = ase_optable_index(quo);
1648
1649         switch (ntquo) {
1650         case INT_T:             /* trivial */
1651         case BIGZ_T:
1652         case INDEF_T:
1653                 return quo;
1654                 break;
1655         case FLOAT_T: {
1656                 fpfloat d;
1657                 IN_FLOAT((d = floor(XFLOAT_DATA(quo))), "floor", quo);
1658                 return (float_to_int(d, "floor", quo, Qunbound));
1659         }
1660         case BIGQ_T:
1661 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1662                 bigz_floor(ent_scratch_bigz,
1663                            XBIGQ_NUMERATOR(quo), XBIGQ_DENOMINATOR(quo));
1664                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1665                 break;
1666 #else
1667                 return quo;
1668 #endif
1669         case BIGF_T:
1670 #if defined HAVE_MPF && defined WITH_GMP
1671                 bigf_floor(ent_scratch_bigf, XBIGF_DATA(quo));
1672 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1673                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1674                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1675 #else  /* !HAVE_MPZ */
1676                 return make_int(
1677                         (EMACS_INT)bigf_to_long(ent_scratch_bigf));
1678 #endif  /* HAVE_MPZ */
1679                 break;
1680 #endif  /* HAVE_MPF */
1681
1682         case BIGFR_T:
1683 #if defined HAVE_MPFR && defined WITH_MPFR
1684                 bigfr_floor(ent_scratch_bigfr, XBIGFR_DATA(quo));
1685 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1686                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1687                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1688 #else  /* !HAVE_MPZ */
1689                 return make_int(
1690                         (EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1691 #endif  /* HAVE_MPZ */
1692                 break;
1693 #endif  /* HAVE_MPFR */
1694
1695         default:
1696                 return quo;
1697         }
1698
1699         return Fsignal(Qdomain_error, Qnil);
1700 }
1701
1702 DEFUN("round", Fround, 1, 1, 0, /*
1703 Return the nearest integer to NUMBER.
1704
1705 NUMBER has to have an archimedian valuation, #'round returns the
1706 integer z for which | number - z | is minimal.
1707 */
1708       (number))
1709 {
1710 #ifdef HAVE_FPFLOAT
1711         if (FLOATP(number)) {
1712                 fpfloat d;
1713                 /* Screw the prevailing rounding mode.  */
1714                 d = emacs_rint(XFLOAT_DATA(number));
1715                 return (float_to_int(d, "round", number, Qunbound));
1716         }
1717 #endif                          /* HAVE_FPFLOAT */
1718
1719 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1720         if (INTEGERP(number))
1721 #else  /* !HAVE_MPZ */
1722         if (INTP(number))
1723 #endif  /* HAVE_MPZ */
1724                 return number;
1725
1726 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1727         else if (BIGQP(number)) {
1728                 /* first off, let's create the division, remainder as well */
1729                 /* fuck ugly? */
1730                 mpz_tdiv_qr(ent_scratch_bigz,
1731                             bigq_numerator(ent_scratch_bigq),
1732                             XBIGQ_NUMERATOR(number),
1733                             XBIGQ_DENOMINATOR(number));
1734
1735                 /* <- denom(number) * 2 */
1736                 mpz_mul_2exp(bigq_numerator(ent_scratch_bigq),
1737                              bigq_numerator(ent_scratch_bigq), 1);
1738
1739                 /* check if we had to add one */
1740                 if (mpz_cmpabs(bigq_numerator(ent_scratch_bigq),
1741                                XBIGQ_DENOMINATOR(number)) >= 0) {
1742                         /* >= ceil(denom(number) / 2) */
1743                         if (mpz_sgn(bigq_numerator(ent_scratch_bigq)) > 0) {
1744                                 mpz_add_ui(ent_scratch_bigz,
1745                                            ent_scratch_bigz, 1UL);
1746                         } else {
1747                                 mpz_sub_ui(ent_scratch_bigz,
1748                                            ent_scratch_bigz, 1UL);
1749                         }
1750                 }
1751                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1752         }
1753 #endif  /* HAVE_MPQ && HAVE_MPZ */
1754
1755 #if defined HAVE_MPF && defined WITH_GMP
1756         else if (BIGFP(number)) {
1757                 warn_when_safe(Qbigf, Qnotice,
1758                                "rounding number of type 'bigf (mpf-floats)"
1759                                "not yet implemented");
1760                 return number;
1761         }
1762 #endif  /* HAVE_MPF */
1763
1764 #if defined HAVE_MPFR && defined WITH_MPFR
1765         else if (BIGFRP(number)) {
1766 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1767                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
1768                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1769                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1770 #else  /* !HAVE_MPZ */
1771                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
1772                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1773 #endif  /* HAVE_MPZ */
1774         }
1775 #endif  /* HAVE_MPFR */
1776
1777         else if (INDEFP(number))
1778                 return number;
1779
1780 #if defined HAVE_MPC && defined WITH_MPC ||     \
1781         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1782         defined HAVE_PSEUG && defined WITH_PSEUG
1783         return Fround(wrong_type_argument(Qcomparablep, number));
1784 #else  /* !HAVE_MPC */
1785         return Fround(wrong_type_argument(Qnumberp, number));
1786 #endif  /* HAVE_MPC */
1787 }
1788
1789 DEFUN("truncate", Ftruncate, 1, 1, 0,   /*
1790 Truncate a floating point number to an integer.
1791 Rounds the value toward zero.
1792 */
1793       (number))
1794 {
1795 #ifdef HAVE_FPFLOAT
1796         if (FLOATP(number))
1797                 return float_to_int(XFLOAT_DATA(number), "truncate", number,
1798                                     Qunbound);
1799 #endif                          /* HAVE_FPFLOAT */
1800
1801 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1802         if (INTEGERP(number))
1803 #else  /* !HAVE_MPZ */
1804         if (INTP(number))
1805 #endif  /* HAVE_MPZ */
1806                 return number;
1807
1808 #if defined HAVE_MPQ && defined WITH_GMP
1809         else if (BIGQP(number)) {
1810                 bigz_div(ent_scratch_bigz,
1811                          XBIGQ_NUMERATOR(number),
1812                          XBIGQ_DENOMINATOR(number));
1813                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1814         }
1815 #endif
1816
1817 #if defined HAVE_MPF && defined WITH_GMP
1818         else if (BIGFP(number)) {
1819 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1820                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
1821                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1822                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1823 #else  /* !HAVE_MPZ */
1824                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
1825                 return make_int((EMACS_INT)bigf_to_long(ent_scratch_bigf));
1826 #endif  /* HAVE_MPZ */
1827         }
1828 #endif  /* HAVE_MPF */
1829
1830 #if defined HAVE_MPFR && defined WITH_MPFR
1831         else if (BIGFRP(number)) {
1832 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1833                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
1834                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1835                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1836 #else  /* !HAVE_MPZ */
1837                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
1838                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1839 #endif  /* HAVE_MPZ */
1840         }
1841 #endif  /* HAVE_MPFR */
1842
1843         else if (INDEFP(number))
1844                 return number;
1845
1846 #if defined HAVE_MPC && defined WITH_MPC ||     \
1847         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1848         defined HAVE_PSEUG && defined WITH_PSEUG
1849         return Ftruncate(wrong_type_argument(Qcomparablep, number));
1850 #else  /* !HAVE_MPC */
1851         return Ftruncate(wrong_type_argument(Qnumberp, number));
1852 #endif  /* HAVE_MPC */
1853 }
1854
1855 DEFUN("almost=", Falmost_eq, 2, 3, 0,   /*
1856 Return t if NUMBER1 is almost equal to NUMBER2.
1857
1858 Optional argument THRES can be used to specify the threshold,
1859 float-epsilon by default.
1860 */
1861       (number1, number2, thres))
1862 {
1863 #if defined HAVE_FPFLOAT
1864         if (NILP(thres)) {
1865                 thres = Vfloat_epsilon;
1866         }
1867         CHECK_FLOAT(thres);
1868
1869         if (FLOATP(number1) && FLOATP(number2)) {
1870                 fpfloat n1 = XFLOAT_DATA(number1);
1871                 fpfloat n2 = XFLOAT_DATA(number2);
1872                 fpfloat thr = XFLOAT_DATA(thres);
1873                 fpfloat d;
1874                 if (n1 >= n2) {
1875                         d = n1 - n2;
1876                 } else {
1877                         d = n2 - n1;
1878                 }
1879                 return d < thr ? Qt : Qnil;
1880         }
1881 #endif  /* HAVE_FPFLOAT */
1882         return ent_binrel(ASE_BINARY_REL_EQUALP, number1, number2) ? Qt : Qnil;
1883 }
1884
1885 DEFUN("almost/=", Falmost_neq, 2, 3, 0, /*
1886 Return t if NUMBER1 is clearly different from NUMBER2.
1887
1888 Optional argument THRES can be used to specify the threshold,
1889 float-epsilon by default.
1890 */
1891       (number1, number2, thres))
1892 {
1893 #if defined HAVE_FPFLOAT
1894         if (NILP(thres)) {
1895                 thres = Vfloat_epsilon;
1896         }
1897         CHECK_FLOAT(thres);
1898
1899         if (FLOATP(number1) && FLOATP(number2)) {
1900                 fpfloat n1 = XFLOAT_DATA(number1);
1901                 fpfloat n2 = XFLOAT_DATA(number2);
1902                 fpfloat thr = XFLOAT_DATA(thres);
1903                 fpfloat d;
1904                 if (n1 >= n2) {
1905                         d = n1 - n2;
1906                 } else {
1907                         d = n2 - n1;
1908                 }
1909                 return d < thr ? Qnil : Qt;
1910         }
1911 #endif  /* HAVE_FPFLOAT */
1912         return ent_binrel(ASE_BINARY_REL_NEQP, number1, number2) ? Qt : Qnil;
1913 }
1914
1915 \f
1916 /* misc complex functions */
1917 DEFUN("conjugate", Fconjugate, 1, 1, 0, /*
1918 Return the \(canonical\) conjugate of NUMBER.
1919 If NUMBER is a comparable, just return NUMBER.
1920 */
1921       (number))
1922 {
1923         if (COMPARABLEP(number)) {
1924                 return number;
1925 #if defined HAVE_PSEUG && defined WITH_PSEUG
1926         } else if (BIGGP(number)) {
1927                 bigg_conj(ent_scratch_bigg, XBIGG_DATA(number));
1928                 return make_bigg_bg(ent_scratch_bigg);
1929 #endif
1930 #if defined HAVE_MPC && defined WITH_MPC ||     \
1931         defined HAVE_PSEUC && defined WITH_PSEUC
1932         } else if (BIGCP(number)) {
1933                 bigc_set_prec(ent_scratch_bigc, XBIGC_GET_PREC(number));
1934                 bigc_conj(ent_scratch_bigc, XBIGC_DATA(number));
1935                 return make_bigc_bc(ent_scratch_bigc);
1936 #endif
1937 #if defined HAVE_QUATERN && defined WITH_QUATERN
1938         } else if (QUATERNP(number)) {
1939                 quatern_conj(ent_scratch_quatern, XQUATERN_DATA(number));
1940                 return make_quatern_qu(ent_scratch_quatern);
1941 #endif
1942         } else if (INDEFP(number)) {
1943                 return number;
1944         }
1945
1946         /* what should the rest do? */
1947         return Fconjugate(wrong_type_argument(Qnumberp, number));
1948 }
1949
1950 DEFUN("canonical-norm", Fcanonical_norm, 1, 1, 0,       /*
1951 Return the canonical norm of NUMBER.
1952 */
1953       (number))
1954 {
1955         if (INDEFP(number)) {
1956                 if (INFINITYP(number))
1957                         return make_indef(POS_INFINITY);
1958                 else
1959                         return make_indef(NOT_A_NUMBER);
1960         } else if (COMPARABLEP(number)) {
1961                 return Fabs(number);
1962 #if defined HAVE_PSEUG && defined WITH_PSEUG
1963         } else if (BIGGP(number)) {
1964                 bigg_norm(ent_scratch_bigz, XBIGG_DATA(number));
1965                 return make_bigz_bz(ent_scratch_bigz);
1966 #endif
1967 #if defined HAVE_MPC && defined WITH_MPC ||     \
1968         defined HAVE_PSEUC && defined WITH_PSEUC
1969         } else if (BIGCP(number)) {
1970                 bigfr_set_prec(ent_scratch_bigfr, XBIGC_GET_PREC(number));
1971                 bigc_norm(ent_scratch_bigfr, XBIGC_DATA(number));
1972                 return make_bigfr_bfr(ent_scratch_bigfr);
1973 #endif
1974 #if defined HAVE_QUATERN && defined WITH_QUATERN
1975         } else if (QUATERNP(number)) {
1976                 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(number));
1977                 return make_bigz_bz(ent_scratch_bigz);
1978 #endif
1979         }
1980
1981         /* what should the rest do? */
1982         return Fcanonical_norm(wrong_type_argument(Qnumberp, number));
1983 }
1984
1985 DEFUN("real-part", Freal_part, 1, 1, 0, /*
1986 Return the real part of NUMBER.
1987 */
1988       (number))
1989 {
1990         if (INDEFP(number)) {
1991                 if (COMPARABLE_INDEF_P(number))
1992                         return number;
1993                 else if (INFINITYP(number))
1994                         return make_indef(POS_INFINITY);
1995                 else
1996                         return make_indef(NOT_A_NUMBER);
1997         } else if (COMPARABLEP(number)) {
1998                 return number;
1999 #if defined HAVE_PSEUG && defined WITH_PSEUG
2000         } else if (BIGGP(number)) {
2001                 return make_bigz_bz(bigg_re(XBIGG_DATA(number)));
2002 #endif
2003 #if defined HAVE_MPC && defined WITH_MPC ||     \
2004         defined HAVE_PSEUC && defined WITH_PSEUC
2005         } else if (BIGCP(number)) {
2006                 return make_bigfr_bfr(bigc_re(XBIGC_DATA(number)));
2007 #endif
2008         }
2009
2010         /* what should the rest do? */
2011         return Freal_part(wrong_type_argument(Qnumberp, number));
2012 }
2013
2014 DEFUN("imaginary-part", Fimaginary_part, 1, 1, 0,       /*
2015 Return the imaginary part of NUMBER.
2016 If NUMBER is a comparable, 0 is returned.
2017 */
2018       (number))
2019 {
2020         if (INDEFP(number)) {
2021                 if (COMPARABLE_INDEF_P(number))
2022                         return Qzero;
2023                 else if (INFINITYP(number))
2024                         return make_indef(POS_INFINITY);
2025                 else
2026                         return make_indef(NOT_A_NUMBER);
2027         } else if (RATIONALP(number)) {
2028                 return make_int(0);
2029 #if defined HAVE_MPFR && defined WITH_MPFR
2030         } else if (REALP(number)) {
2031                 return make_bigfr(0.0, 0UL);
2032 #endif
2033 #if defined HAVE_PSEUG && defined WITH_PSEUG
2034         } else if (BIGGP(number)) {
2035                 return make_bigz_bz(bigg_im(XBIGG_DATA(number)));
2036 #endif
2037 #if defined HAVE_MPC && defined WITH_MPC ||     \
2038         defined HAVE_PSEUC && defined WITH_PSEUC
2039         } else if (BIGCP(number)) {
2040                 return make_bigfr_bfr(bigc_im(XBIGC_DATA(number)));
2041 #endif
2042         }
2043
2044         /* what should the rest do? */
2045         return Fimaginary_part(wrong_type_argument(Qnumberp, number));
2046 }
2047
2048 \f
2049 /* Float-rounding functions. */
2050 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR || \
2051         defined(HAVE_MPF) && defined WITH_GMP
2052
2053 DEFUN("fceiling", Ffceiling, 1, 1, 0,   /*
2054 Return the smallest integer no less than NUMBER, as a float.
2055 \(Round toward +inf.\)
2056 */
2057       (number))
2058 {
2059 #if defined HAVE_MPF && defined WITH_GMP
2060         if (BIGFP(number)) {
2061                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2062
2063                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
2064                 return make_bigf_bf(ent_scratch_bigf);
2065         }
2066 #endif  /* HAVE_MPF */
2067
2068 #if defined HAVE_MPFR && defined WITH_MPFR
2069         if (BIGFRP(number)) {
2070                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2071
2072                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
2073                 return make_bigfr_bfr(ent_scratch_bigfr);
2074         }
2075 #endif  /* HAVE_MPFR */
2076
2077         if (INDEFP(number))
2078                 return number;
2079
2080         number = ent_lift(number, FLOAT_T, NULL);
2081
2082         if (FLOATP(number))
2083                 return make_float(ceil(XFLOAT_DATA(number)));
2084         else
2085                 return number;
2086 }
2087
2088 DEFUN("ffloor", Fffloor, 1, 1, 0,       /*
2089 Return the largest integer no greater than NUMBER, as a float.
2090 \(Round towards -inf.\)
2091 */
2092       (number))
2093 {
2094 #if defined HAVE_MPF && defined WITH_GMP
2095         if (BIGFP(number)) {
2096                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2097
2098                 bigf_floor(ent_scratch_bigf, XBIGF_DATA(number));
2099                 return make_bigf_bf(ent_scratch_bigf);
2100         }
2101 #endif  /* HAVE_MPF */
2102
2103 #if defined HAVE_MPFR && defined WITH_MPFR
2104         if (BIGFRP(number)) {
2105                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2106
2107                 bigfr_floor(ent_scratch_bigfr, XBIGFR_DATA(number));
2108                 return make_bigfr_bfr(ent_scratch_bigfr);
2109         }
2110 #endif  /* HAVE_MPFR */
2111
2112         if (INDEFP(number))
2113                 return number;
2114
2115         number = ent_lift(number, FLOAT_T, NULL);
2116
2117         if (FLOATP(number))
2118                 return make_float(floor(XFLOAT_DATA(number)));
2119         else
2120                 return number;
2121 }
2122
2123 DEFUN("fround", Ffround, 1, 1, 0,       /*
2124 Return the nearest integer to NUMBER, as a float.
2125 */
2126       (number))
2127 {
2128 #if defined HAVE_MPF && defined WITH_GMP
2129         if (BIGFP(number)) {
2130                 warn_when_safe(Qbigf, Qnotice,
2131                                "rounding number of type 'bigf (mpf-floats)"
2132                                "not yet implemented");
2133                 return number;
2134         }
2135 #endif  /* HAVE_MPF */
2136
2137 #if defined HAVE_MPFR && defined WITH_MPFR
2138         if (BIGFRP(number)) {
2139                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2140
2141                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
2142                 return make_bigfr_bfr(ent_scratch_bigfr);
2143         }
2144 #endif  /* HAVE_MPFR */
2145
2146         if (INDEFP(number))
2147                 return number;
2148
2149         number = ent_lift(number, FLOAT_T, NULL);
2150
2151         if (FLOATP(number))
2152                 return make_float(emacs_rint(XFLOAT_DATA(number)));
2153         else
2154                 return number;
2155 }
2156
2157 DEFUN("ftruncate", Fftruncate, 1, 1, 0, /*
2158 Truncate a floating point number to an integral float value.
2159 Rounds the value toward zero.
2160 */
2161       (number))
2162 {
2163         fpfloat d;
2164 #if defined HAVE_MPF && defined WITH_GMP
2165         if (BIGFP(number)) {
2166                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2167
2168                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
2169                 return make_bigf_bf(ent_scratch_bigf);
2170         }
2171 #endif  /* HAVE_MPF */
2172
2173 #if defined HAVE_MPFR && defined WITH_MPFR
2174         if (BIGFRP(number)) {
2175                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2176
2177                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
2178                 return make_bigfr_bfr(ent_scratch_bigfr);
2179         }
2180 #endif  /* HAVE_MPFR */
2181
2182         if (INDEFP(number))
2183                 return number;
2184
2185         number = ent_lift(number, FLOAT_T, NULL);
2186
2187         if (FLOATP(number)) {
2188                 d = XFLOAT_DATA(number);
2189                 if (d >= 0.0)
2190                         d = floor(d);
2191                 else
2192                         d = ceil(d);
2193                 return make_float(d);
2194         } else {
2195                 return number;
2196         }
2197 }
2198 #endif  /* HAVE_MPF(R) || HAVE_FPFLOAT (float-rounding functions) */
2199
2200 \f
2201 #ifdef HAVE_FPFLOAT
2202 #ifdef FLOAT_CATCH_SIGILL
2203 static SIGTYPE float_error(int signo)
2204 {
2205         if (!in_float)
2206                 fatal_error_signal(signo);
2207
2208         EMACS_REESTABLISH_SIGNAL(signo, arith_error);
2209         EMACS_UNBLOCK_SIGNAL(signo);
2210
2211         in_float = 0;
2212
2213         /* Was Fsignal(), but it just doesn't make sense for an error
2214            occurring inside a signal handler to be restartable, considering
2215            that anything could happen when the error is signaled and trapped
2216            and considering the asynchronous nature of signal handlers. */
2217         signal_error(Qarith_error, list1(float_error_arg));
2218 }
2219
2220 /* Another idea was to replace the library function `infnan'
2221    where SIGILL is signaled.  */
2222
2223 #endif                          /* FLOAT_CATCH_SIGILL */
2224
2225 /* In C++, it is impossible to determine what type matherr expects
2226    without some more configure magic.
2227    We shouldn't be using matherr anyways - it's a non-standard SYSVism. */
2228 #if defined (HAVE_MATHERR) && !defined(__cplusplus)
2229 int matherr(struct exception *x)
2230 {
2231         Lisp_Object args;
2232         if (!in_float)
2233                 /* Not called from emacs-lisp float routines; do the default thing. */
2234                 return 0;
2235
2236         /* if (!strcmp (x->name, "pow")) x->name = "expt"; */
2237
2238         args = Fcons(build_string(x->name),
2239                      Fcons(make_float(x->arg1), ((in_float == 2)
2240                                                  ? Fcons(make_float(x->arg2),
2241                                                          Qnil)
2242                                                  : Qnil)));
2243         switch (x->type) {
2244         case DOMAIN:
2245                 Fsignal(Qdomain_error, args);
2246                 break;
2247         case SING:
2248                 Fsignal(Qsingularity_error, args);
2249                 break;
2250         case OVERFLOW:
2251                 Fsignal(Qoverflow_error, args);
2252                 break;
2253         case UNDERFLOW:
2254                 Fsignal(Qunderflow_error, args);
2255                 break;
2256         default:
2257                 Fsignal(Qarith_error, args);
2258                 break;
2259         }
2260         return 1;               /* don't set errno or print a message */
2261 }
2262 #endif                          /* HAVE_MATHERR */
2263 #endif                          /* HAVE_FPFLOAT */
2264 \f
2265 void init_floatfns_very_early(void)
2266 {
2267 #ifdef HAVE_FPFLOAT
2268 # ifdef FLOAT_CATCH_SIGILL
2269         signal(SIGILL, float_error);
2270 # endif
2271         in_float = 0;
2272 #endif                          /* HAVE_FPFLOAT */
2273 }
2274
2275 void syms_of_floatfns(void)
2276 {
2277
2278         /* Trig functions.  */
2279
2280 #if defined(HAVE_FPFLOAT) || defined HAVE_MPFR && defined WITH_MPFR
2281         DEFSUBR(Facos);
2282         DEFSUBR(Fasin);
2283         DEFSUBR(Fatan);
2284         DEFSUBR(Fcos);
2285         DEFSUBR(Fsin);
2286         DEFSUBR(Ftan);
2287 #endif  /* HAVE_FPFLOAT || HAVE_MPFR*/
2288 #if defined HAVE_MPFR && defined WITH_MPFR
2289         DEFSUBR(Fsec);
2290         DEFSUBR(Fcsc);
2291         DEFSUBR(Fcot);
2292 #endif
2293
2294         /* Bessel functions */
2295
2296 #if 0
2297         DEFSUBR(Fbessel_y0);
2298         DEFSUBR(Fbessel_y1);
2299         DEFSUBR(Fbessel_yn);
2300         DEFSUBR(Fbessel_j0);
2301         DEFSUBR(Fbessel_j1);
2302         DEFSUBR(Fbessel_jn);
2303 #endif                          /* 0 */
2304
2305         /* Error functions. */
2306
2307 #if 1
2308 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2309         DEFSUBR(Ferf);
2310         DEFSUBR(Ferfc);
2311         DEFSUBR(Flog_gamma);
2312 #endif
2313 #endif                          /* 0 */
2314
2315         /* Root and Log functions. */
2316
2317 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2318         DEFSUBR(Fexp);
2319 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
2320         DEFSUBR(Fexp2);
2321         DEFSUBR(Fexp10);
2322 #if 0
2323         DEFSUBR(Fexpt);
2324 #endif
2325 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2326         DEFSUBR(Flog);
2327 #if defined HAVE_MPFR && defined WITH_MPFR
2328         DEFSUBR(Flog2);
2329 #endif  /* HAVE_MPFR */
2330         DEFSUBR(Flog10);
2331         DEFSUBR(Fsqrt);
2332         DEFSUBR(Fcube_root);
2333 #if defined HAVE_MPFR && defined WITH_MPFR
2334         DEFSUBR(Froot);
2335 #endif
2336 #endif  /* HAVE_FPFLOAT || HAVE_MPFR*/
2337
2338         /* Inverse trig functions. */
2339
2340 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2341         DEFSUBR(Facosh);
2342         DEFSUBR(Fasinh);
2343         DEFSUBR(Fatanh);
2344         DEFSUBR(Fcosh);
2345         DEFSUBR(Fsinh);
2346         DEFSUBR(Ftanh);
2347 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
2348 #if defined HAVE_MPFR && defined WITH_MPFR
2349         DEFSUBR(Fsech);
2350         DEFSUBR(Fcsch);
2351         DEFSUBR(Fcoth);
2352 #endif  /* HAVE_MPFR */
2353
2354         /* Rounding functions */
2355
2356         DEFSUBR(Fabs);
2357 #ifdef HAVE_FPFLOAT
2358         DEFSUBR(Ffloat);
2359         DEFSUBR(Flogb);
2360 #endif                          /* HAVE_FPFLOAT */
2361         DEFSUBR(Fceiling);
2362         DEFSUBR(Ffloor);
2363         DEFSUBR(Fround);
2364         DEFSUBR(Ftruncate);
2365         DEFSUBR(Falmost_eq);
2366         DEFSUBR(Falmost_neq);
2367
2368         /* misc complex functions */
2369         DEFSUBR(Fconjugate);
2370         DEFSUBR(Fcanonical_norm);
2371         DEFSUBR(Freal_part);
2372         DEFSUBR(Fimaginary_part);
2373
2374         /* Float-rounding functions. */
2375
2376 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPF) && defined WITH_GMP ||   \
2377         defined(HAVE_MPFR) && defined WITH_MPFR
2378         DEFSUBR(Ffceiling);
2379         DEFSUBR(Fffloor);
2380         DEFSUBR(Ffround);
2381         DEFSUBR(Fftruncate);
2382 #endif  /* HAVE_FPFLOAT || HAVE_MPF(R) */
2383 }
2384
2385 void vars_of_floatfns(void)
2386 {
2387 }