Build Fix -- compatibility issue with newer autoconf
[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
787 #define RETURN_WHEN_INDEF(number)                                   \
788         if (INDEFP(number)) {                                       \
789                 if (XINDEF_DATA(number) == POS_INFINITY) {          \
790                         return number;                              \
791                 } else if (XINDEF_DATA(number) == NEG_INFINITY) {       \
792                         return make_indef(NOT_A_NUMBER);            \
793                 } else {                                            \
794                         return number;                              \
795                 }                                                   \
796         }
797
798 DEFUN("log10", Flog10, 1, 2, 0, /*
799 Return the logarithm base 10 of NUMBER.
800 If second optional argument PRECISION is given, use its value
801 (an integer) as precision.
802 */
803       (number, precision))
804 {
805         RETURN_WHEN_INDEF(number);
806
807 #if defined HAVE_MPFR && defined WITH_MPFR
808         Lisp_Object bfrnumber;
809
810         bigfr_set_prec(ent_scratch_bigfr,
811                        internal_get_precision(precision));
812
813         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
814         bigfr_log10(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
815         return make_bigfr_bfr(ent_scratch_bigfr);
816
817 #else  /* !HAVE_MPFR */
818         number = ent_lift(number, FLOAT_T, NULL);
819
820         RETURN_WHEN_INDEF(number);
821
822         if (FLOATP(number)) {
823                 fpfloat d;
824 #if HAVE_LOG10
825                 d = log10(XFLOAT_DATA(number));
826                 return make_float(d);
827 #elif HAVE_LOG2
828                 static const fpflot log2_10 = log2(10);
829                 d = log2(XFLOAT_DATA(number));
830                 RETURN_WHEN_INDEF(d);
831                 return make_float(d/log2_10);
832 #elif HAVE_LOG
833                 static const fpflot log_10 - log(10);
834                 d = log(XFLOAT_DATA(number));
835                 RETURN_WHEN_INDEF(d);
836                 return make_float(d/log_10);
837 #else
838                 return ase_unary_operation_undefined(number);
839 #endif
840         }
841
842         Fsignal(Qarith_error, list1(number));
843         return Qnil;
844
845         if (NILP(precision));
846 #endif  /* HAVE_MPFR */
847 }
848
849 DEFUN("log2", Flog2, 1, 2, 0,   /*
850 Return the logarithm base 2 of NUMBER.
851 If second optional argument PRECISION is given, use its value
852 (an integer) as precision.
853 */
854       (number, precision))
855 {
856         RETURN_WHEN_INDEF(number);
857
858 #if defined HAVE_MPFR && defined WITH_MPFR
859         Lisp_Object bfrnumber;
860
861         bigfr_set_prec(ent_scratch_bigfr,
862                        internal_get_precision(precision));
863
864         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
865         bigfr_log2(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
866         return make_bigfr_bfr(ent_scratch_bigfr);
867 #else
868         number = ent_lift(number, FLOAT_T, NULL);
869
870         RETURN_WHEN_INDEF(number);
871
872         if (FLOATP(number)) {
873                 fpfloat d;
874 #if HAVE_LOG2
875                 d = log2(XFLOAT_DATA(number));
876                 return make_float(d);
877 #elif HAVE_LOG
878                 static const fpflot log_2 - log(2);
879                 d = log(XFLOAT_DATA(number));
880                 RETURN_WHEN_INDEF(d);
881                 return make_float(d/log_2);
882 #else
883                 return ase_unary_operation_undefined(number);
884 #endif
885         }
886
887         Fsignal(Qarith_error, list1(number));
888         return Qnil;
889
890         if (NILP(precision));
891 #endif  /* HAVE_MPFR */
892 }
893
894 DEFUN("log", Flog, 1, 3, 0,     /*
895 Return the natural logarithm of NUMBER.
896 If second optional argument BASE is given, return the logarithm of
897 NUMBER using that base.
898 If third optional argument PRECISION is given, use its value
899 (an integer) as precision.
900 */
901       (number, base, precision))
902 {
903         RETURN_WHEN_INDEF(number);
904
905         if (INTEGERP(base)) {
906                 switch(XINT(base)) {
907                 case 2 : return Flog2 (number, precision);
908                 case 10: return Flog10(number, precision);
909                 default: break; /* Intentional Fall through */
910                 }
911         }
912
913
914 #if defined HAVE_MPFR && defined WITH_MPFR
915         if (!NILP(base)) {
916                 /* Not all bignumber libs optimize log2, for instance MPFR
917                    implements log2 in function of log. */
918                 Lisp_Object _logn, _logb;
919                 _logn = Flog(number, Qnil, precision);
920                 RETURN_WHEN_INDEF(_logn);
921                 _logb = Flog(base, Qnil, precision);
922                 return ent_binop(ASE_BINARY_OP_QUO, _logn, _logb);
923         }
924
925         Lisp_Object bfrnumber;
926
927         bigfr_set_prec(ent_scratch_bigfr,
928                        internal_get_precision(precision));
929
930         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
931         bigfr_log(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
932         return make_bigfr_bfr(ent_scratch_bigfr);
933
934 #else  /* !HAVE_MPFR */
935         if (!NILP(base)) {
936                 /* Processor implementations tend to give an edge to log2 */
937                 Lisp_Object _logn, _logb;
938                 _logn = Flog2(number, precision);
939                 RETURN_WHEN_INDEF(_logn);
940                 _logb = Flog2(base, precision);
941                 return ent_binop(ASE_BINARY_OP_QUO, _logn, _logb);
942         }
943
944         number = ent_lift(number, FLOAT_T, NULL);
945
946         RETURN_WHEN_INDEF(number);
947
948         if (FLOATP(number)) {
949                 fpfloat d;
950                 d = log(XFLOAT_DATA(number));
951                 return make_float(d);
952         }
953
954         Fsignal(Qarith_error, list1(number));
955         return Qnil;
956
957         if (NILP(precision));
958 #endif  /* HAVE_MPFR */
959 }
960
961 #undef RETURN_WHEN_INDEF
962
963 DEFUN("sqrt", Fsqrt, 1, 2, 0,   /*
964 Return the square root of NUMBER.
965 If second optional argument PRECISION is given, use its value
966 (an integer) as precision.
967 */
968       (number, precision))
969 {
970 #if defined(HAVE_MPFR) && defined WITH_MPFR ||  \
971         defined(HAVE_MPC) && defined WITH_MPC ||        \
972         defined(HAVE_PSEUC) && defined WITH_PSEUC
973
974         if (INDEFP(number)) {
975                 if (XINDEF_DATA(number) == POS_INFINITY)
976                         return number;
977                 else if (XINDEF_DATA(number) == NEG_INFINITY)
978                         return make_indef(COMPLEX_INFINITY);
979                 else
980                         return number;
981         }
982
983         if (COMPARABLEP(number)) {
984 #if defined HAVE_MPFR && defined WITH_MPFR
985                 bigfr_set_prec(ent_scratch_bigfr,
986                                internal_get_precision(precision));
987
988                 if (NATNUMP(number))
989                         bigfr_sqrt_ui(ent_scratch_bigfr,
990                                       (unsigned long)XUINT(number));
991                 else if (BIGZP(number) &&
992                          bigz_fits_ulong_p(XBIGZ_DATA(number)) &&
993                          bigz_sign(XBIGZ_DATA(number)) >= 0) {
994                         bigfr_sqrt_ui(ent_scratch_bigfr,
995                                       (unsigned long)bigz_to_ulong(
996                                               XBIGZ_DATA(number)));
997                 } else if (!NILP(Fnonnegativep(number))) {
998                         Lisp_Object bfrnumber;
999                         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1000                         bigfr_sqrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
1001                 } else {
1002 #if defined HAVE_MPC && defined WITH_MPC ||     \
1003         defined HAVE_PSEUC && defined WITH_PSEUC
1004                         Lisp_Object bcnumber;
1005                         bigc_set_prec(ent_scratch_bigc,
1006                                       internal_get_precision(precision));
1007                         bcnumber = Fcoerce_number(number, Qbigc, precision);
1008                         bigc_sqrt(ent_scratch_bigc, XBIGC_DATA(bcnumber));
1009                         return make_bigc_bc(ent_scratch_bigc);
1010 #else  /* !HAVE_MPC */
1011                         Lisp_Object bfrnumber;
1012                         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1013                         bigfr_sqrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
1014 #endif  /* HAVE_MPC */
1015                 }
1016                 return make_bigfr_bfr(ent_scratch_bigfr);
1017 #endif  /* HAVE_MPFR */
1018 #if defined HAVE_MPC && defined WITH_MPC ||     \
1019         defined HAVE_PSEUC && defined WITH_PSEUC
1020         } else if (BIGCP(number) || BIGGP(number)) {
1021                 Lisp_Object bcnumber;
1022                 bigc_set_prec(ent_scratch_bigc,
1023                               internal_get_precision(precision));
1024
1025                 bcnumber = Fcoerce_number(number, Qbigc, precision);
1026                 bigc_sqrt(ent_scratch_bigc, XBIGC_DATA(bcnumber));
1027                 return make_bigc_bc(ent_scratch_bigc);
1028 #endif  /* HAVE_MPC */
1029         }
1030
1031         if (NILP(precision));
1032         return wrong_type_argument(Qnumberp, number);
1033
1034 #else  /* !HAVE_MPFR && !HAVE_MPC */
1035         if (INDEFP(number)) {
1036                 goto indefcase;
1037         }
1038
1039         number = ent_lift(number, FLOAT_T, NULL);
1040
1041         if (FLOATP(number)) {
1042                 fpfloat d;
1043                 d = sqrt(XFLOAT_DATA(number));
1044                 return make_float(d);
1045         } else if (INDEFP(number)) {
1046         indefcase:
1047                 if (XINDEF_DATA(number) == POS_INFINITY)
1048                         return number;
1049                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1050                         return make_indef(COMPLEX_INFINITY);
1051                 else
1052                         return number;
1053         }
1054
1055         Fsignal(Qarith_error, list1(number));
1056         return Qnil;
1057
1058         if (NILP(precision));
1059 #endif  /* HAVE_MPFR */
1060 }
1061
1062 DEFUN("cube-root", Fcube_root, 1, 2, 0, /*
1063 Return the cube root of NUMBER.
1064 If second optional argument PRECISION is given, use its value
1065 (an integer) as precision.
1066 */
1067       (number, precision))
1068 {
1069 #if defined HAVE_MPFR && defined WITH_MPFR
1070         Lisp_Object bfrnumber;
1071
1072         if (INDEFP(number))
1073                 return number;
1074
1075         bigfr_set_prec(ent_scratch_bigfr,
1076                        internal_get_precision(precision));
1077
1078         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1079         bigfr_cbrt(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
1080         return make_bigfr_bfr(ent_scratch_bigfr);
1081
1082 #else  /* !HAVE_MPFR */
1083         if (INDEFP(number)) {
1084                 goto indefcase;
1085         }
1086
1087         number = ent_lift(number, FLOAT_T, NULL);
1088
1089         if (FLOATP(number)) {
1090                 fpfloat d;
1091 #ifdef HAVE_CBRT
1092                 d = cbrt(XFLOAT_DATA(number));
1093 #else
1094                 d = XFLOAT_DATA(number);
1095                 if (d >= 0.0)
1096                         d = pow(d, 1.0 / 3.0);
1097                 else
1098                         d = -pow(-d, 1.0 / 3.0);
1099 #endif
1100                 return make_float(d);
1101         } else if (INDEFP(number)) {
1102         indefcase:
1103                 return number;
1104         }
1105
1106         Fsignal(Qarith_error, list1(number));
1107         return Qnil;
1108
1109         if (NILP(precision));
1110 #endif  /* HAVE_MPFR */
1111 }
1112 #endif  /* HAVE_FPFLOAT || MPFR */
1113
1114
1115 #if defined HAVE_MPFR && defined WITH_MPFR
1116 DEFUN("root", Froot, 2, 3, 0,   /*
1117 Return the RADIX-th root of NUMBER.
1118 If third optional argument PRECISION is given, use its value
1119 (an integer) as precision.
1120 */
1121       (number, radix, precision))
1122 {
1123         Lisp_Object bfrnumber;
1124
1125         if (!NATNUMP(radix)) {
1126                 dead_wrong_type_argument(Qnatnump, radix);
1127                 return Qnil;
1128         }
1129
1130         if (INDEFP(number)) {
1131                 if (XINDEF_DATA(number) == POS_INFINITY)
1132                         return number;
1133                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1134                         return make_indef(COMPLEX_INFINITY);
1135                 else
1136                         return number;
1137         }
1138
1139         bigfr_set_prec(ent_scratch_bigfr,
1140                        internal_get_precision(precision));
1141
1142         bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
1143         bigfr_root(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber), XUINT(radix));
1144         return make_bigfr_bfr(ent_scratch_bigfr);
1145 }
1146 #endif  /* HAVE_MPFR */
1147
1148 \f
1149 /* (Inverse) hyperbolic trig functions. */
1150 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
1151
1152 DEFUN("acosh", Facosh, 1, 2, 0, /*
1153 Return the inverse hyperbolic cosine of NUMBER.
1154 If optional argument PRECISION is non-nil, its value
1155 (an integer) is used as precision.
1156 */
1157       (number, precision))
1158 {
1159 #if defined HAVE_MPFR && defined WITH_MPFR
1160
1161         MPFR_TRIG_FUN(acosh);
1162
1163 #else  /* !HAVE_MPFR */
1164         if (INDEFP(number)) {
1165                 return make_indef(NOT_A_NUMBER);
1166         }
1167
1168         number = ent_lift(number, FLOAT_T, NULL);
1169
1170         if (FLOATP(number)) {
1171                 fpfloat d = XFLOAT_DATA(number);
1172 #ifdef HAVE_INVERSE_HYPERBOLIC
1173                 d = acosh(d);
1174 #else
1175                 d = log(d + sqrt(d * d - 1.0));
1176 #endif
1177                 return make_float(d);
1178         } else if (INDEFP(number)) {
1179                 return make_indef(NOT_A_NUMBER);
1180         }
1181
1182         Fsignal(Qarith_error, list1(number));
1183         return Qnil;
1184
1185         if (NILP(precision));
1186 #endif  /* HAVE_MPFR */
1187 }
1188
1189 DEFUN("asinh", Fasinh, 1, 2, 0, /*
1190 Return the inverse hyperbolic sine of NUMBER.
1191 If optional argument PRECISION is non-nil, its value
1192 (an integer) is used as precision.
1193 */
1194       (number, precision))
1195 {
1196 #if defined HAVE_MPFR && defined WITH_MPFR
1197
1198         MPFR_TRIG_FUN(asinh);
1199
1200 #else  /* !HAVE_MPFR */
1201         if (INDEFP(number)) {
1202                 return make_indef(NOT_A_NUMBER);
1203         }
1204
1205         number = ent_lift(number, FLOAT_T, NULL);
1206
1207         if (FLOATP(number)) {
1208                 fpfloat d = XFLOAT_DATA(number);
1209 #ifdef HAVE_INVERSE_HYPERBOLIC
1210                 d = acosh(d);
1211 #else
1212                 d = log(d + sqrt(d * d + 1.0));
1213 #endif
1214                 return make_float(d);
1215         } else if (INDEFP(number)) {
1216                 return make_indef(NOT_A_NUMBER);
1217         }
1218
1219         Fsignal(Qarith_error, list1(number));
1220         return Qnil;
1221
1222         if (NILP(precision));
1223 #endif  /* HAVE_MPFR */
1224 }
1225
1226 DEFUN("atanh", Fatanh, 1, 2, 0, /*
1227 Return the inverse hyperbolic tangent of NUMBER.
1228 If optional argument PRECISION is non-nil, its value
1229 (an integer) is used as precision.
1230 */
1231       (number, precision))
1232 {
1233 #if defined HAVE_MPFR && defined WITH_MPFR
1234
1235         MPFR_TRIG_FUN(atanh);
1236
1237 #else  /* !HAVE_MPFR */
1238         if (INDEFP(number)) {
1239                 return make_indef(NOT_A_NUMBER);
1240         }
1241
1242         number = ent_lift(number, FLOAT_T, NULL);
1243
1244         if (FLOATP(number)) {
1245                 fpfloat d = XFLOAT_DATA(number);
1246 #ifdef HAVE_INVERSE_HYPERBOLIC
1247                 d = atanh(d);
1248 #else
1249                 d = 0.5 * log((1.0 + d) / (1.0 - d));
1250 #endif
1251                 return make_float(d);
1252         } else if (INDEFP(number)) {
1253                 return make_indef(NOT_A_NUMBER);
1254         }
1255
1256         Fsignal(Qarith_error, list1(number));
1257         return Qnil;
1258
1259         if (NILP(precision));
1260 #endif  /* HAVE_MPFR */
1261 }
1262
1263 DEFUN("cosh", Fcosh, 1, 2, 0,   /*
1264 Return the hyperbolic cosine of NUMBER.
1265 If optional argument PRECISION is non-nil, its value
1266 (an integer) is used as precision.
1267 */
1268       (number, precision))
1269 {
1270 #if defined HAVE_MPFR && defined WITH_MPFR
1271
1272         MPFR_TRIG_FUN(cosh);
1273
1274 #else  /* !HAVE_MPFR */
1275         if (INDEFP(number)) {
1276                 return make_indef(NOT_A_NUMBER);
1277         }
1278
1279         number = ent_lift(number, FLOAT_T, NULL);
1280
1281         if (FLOATP(number)) {
1282                 fpfloat d;
1283                 d = cosh(XFLOAT_DATA(number));
1284                 return make_float(d);
1285         } else if (INDEFP(number)) {
1286                 return make_indef(NOT_A_NUMBER);
1287         }
1288
1289         Fsignal(Qarith_error, list1(number));
1290         return Qnil;
1291
1292         if (NILP(precision));
1293 #endif  /* HAVE_MPFR */
1294 }
1295
1296 DEFUN("sinh", Fsinh, 1, 2, 0,   /*
1297 Return the hyperbolic sine of NUMBER.
1298 If optional argument PRECISION is non-nil, its value
1299 (an integer) is used as precision.
1300 */
1301       (number, precision))
1302 {
1303 #if defined HAVE_MPFR && defined WITH_MPFR
1304
1305         MPFR_TRIG_FUN(sinh);
1306
1307 #else  /* !HAVE_MPFR */
1308         if (INDEFP(number)) {
1309                 return make_indef(NOT_A_NUMBER);
1310         }
1311
1312         number = ent_lift(number, FLOAT_T, NULL);
1313
1314         if (FLOATP(number)) {
1315                 fpfloat d;
1316                 d = sinh(XFLOAT_DATA(number));
1317                 return make_float(d);
1318         } else if (INDEFP(number)) {
1319                 return make_indef(NOT_A_NUMBER);
1320         }
1321
1322         Fsignal(Qarith_error, list1(number));
1323         return Qnil;
1324
1325         if (NILP(precision));
1326 #endif  /* HAVE_MFPR */
1327 }
1328
1329 DEFUN("tanh", Ftanh, 1, 2, 0,   /*
1330 Return the hyperbolic tangent of NUMBER.
1331 If optional argument PRECISION is non-nil, its value
1332 (an integer) is used as precision.
1333 */
1334       (number, precision))
1335 {
1336 #if defined HAVE_MPFR && defined WITH_MPFR
1337
1338         MPFR_TRIG_FUN(tanh);
1339
1340 #else  /* !HAVE_MPFR */
1341         if (INDEFP(number)) {
1342                 return make_indef(NOT_A_NUMBER);
1343         }
1344
1345         number = ent_lift(number, FLOAT_T, NULL);
1346
1347         if (FLOATP(number)) {
1348                 fpfloat d = XFLOAT_DATA(number);
1349                 d = tanh(d);
1350                 return make_float(d);
1351         } else if (INDEFP(number)) {
1352                 return make_indef(NOT_A_NUMBER);
1353         }
1354
1355         Fsignal(Qarith_error, list1(number));
1356         return Qnil;
1357
1358         if (NILP(precision));
1359 #endif  /* HAVE_MPFR */
1360 }
1361
1362 #if defined HAVE_MPFR && defined WITH_MPFR
1363
1364 DEFUN("sech", Fsech, 1, 2, 0,   /*
1365 Return the hyperbolic secant of NUMBER.
1366 If optional argument PRECISION is non-nil, its value
1367 (an integer) is used as precision.
1368 */
1369       (number, precision))
1370 {
1371         MPFR_TRIG_FUN(sech);
1372 }
1373
1374 DEFUN("csch", Fcsch, 1, 2, 0,   /*
1375 Return the hyperbolic cosecant of NUMBER.
1376 If optional argument PRECISION is non-nil, its value
1377 (an integer) is used as precision.
1378 */
1379       (number, precision))
1380 {
1381         MPFR_TRIG_FUN(csch);
1382 }
1383
1384 DEFUN("coth", Fcoth, 1, 2, 0,   /*
1385 Return the hyperbolic cotangent of NUMBER.
1386 If optional argument PRECISION is non-nil, its value
1387 (an integer) is used as precision.
1388 */
1389       (number, precision))
1390 {
1391         MPFR_TRIG_FUN(coth);
1392 }
1393 #endif  /* HAVE_MPFR */
1394
1395 #endif  /* HAVE_MPFR || HAVE_FPFLOAT (inverse trig functions) */
1396
1397 \f
1398 /* Rounding functions */
1399
1400 DEFUN("abs", Fabs, 1, 1, 0,     /*
1401 Return the absolute value of NUMBER.
1402 */
1403       (number))
1404 {
1405 #ifdef HAVE_FPFLOAT
1406         if (FLOATP(number)) {
1407                 return make_float(fabs(XFLOAT_DATA(number)));
1408         }
1409 #endif                          /* HAVE_FPFLOAT */
1410
1411         if (INTP(number)) {
1412 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1413                 /* The most negative Lisp int will overflow */
1414                 return (XINT(number) >= 0)
1415                         ? number : make_integer(-XINT(number));
1416 #else  /* !HAVE_MPZ */
1417                 return (XINT(number) >= 0) ? number : make_int(-XINT(number));
1418 #endif  /* HAVE_MPZ */
1419         }
1420
1421 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1422         if (BIGZP(number)) {
1423                 if (bigz_sign(XBIGZ_DATA(number)) >= 0)
1424                         return number;
1425
1426                 bigz_abs(ent_scratch_bigz, XBIGZ_DATA(number));
1427                 return make_bigz_bz(ent_scratch_bigz);
1428         }
1429 #endif  /* HAVE_MPZ */
1430
1431 #if defined HAVE_MPQ && defined WITH_GMP
1432         if (BIGQP(number)) {
1433                 if (bigq_sign(XBIGQ_DATA(number)) >= 0)
1434                         return number;
1435
1436                 bigq_abs(ent_scratch_bigq, XBIGQ_DATA(number));
1437                 return make_bigq_bq(ent_scratch_bigq);
1438         }
1439 #endif  /* HAVE_MPQ */
1440
1441 #if defined HAVE_MPF && defined WITH_GMP
1442         if (BIGFP(number)) {
1443                 if (bigf_sign(XBIGF_DATA (number)) >= 0)
1444                         return number;
1445
1446                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
1447
1448                 bigf_abs(ent_scratch_bigf, XBIGF_DATA(number));
1449                 return make_bigf_bf(ent_scratch_bigf);
1450         }
1451 #endif  /* HAVE_MPF */
1452
1453 #if defined HAVE_MPFR && defined WITH_MPFR
1454         if (BIGFRP(number)) {
1455                 if (bigfr_sign(XBIGFR_DATA (number)) >= 0)
1456                         return number;
1457
1458                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
1459
1460                 bigfr_abs(ent_scratch_bigfr, XBIGFR_DATA(number));
1461                 return make_bigfr_bfr(ent_scratch_bigfr);
1462         }
1463 #endif  /* HAVE_MPFR */
1464
1465 #if defined(HAVE_PSEUG) && defined WITH_PSEUG && defined(HAVE_MPFR)
1466         if (BIGGP(number)) {
1467                 bigfr_set_prec(ent_scratch_bigfr,
1468                                internal_get_precision(Qnil));
1469
1470                 bigg_abs(ent_scratch_bigfr, XBIGG_DATA(number));
1471                 return make_bigfr_bfr(ent_scratch_bigfr);
1472         }
1473 #endif  /* HAVE_PSEUG && HAVE_MPFR */
1474
1475 #if defined HAVE_MPC && defined WITH_MPC ||     \
1476         defined HAVE_PSEUC && defined WITH_PSEUC
1477         if (BIGCP(number)) {
1478                 bigfr_set_prec(ent_scratch_bigfr, XBIGC_GET_PREC(number));
1479
1480                 if (bigc_nan_p(XBIGC_DATA(number)))
1481                         return make_indef(NOT_A_NUMBER);
1482                 else if (bigc_inf_p(XBIGC_DATA(number)))
1483                         return make_indef(POS_INFINITY);
1484                 else
1485                         bigc_abs(ent_scratch_bigfr, XBIGC_DATA(number));
1486
1487                 return make_bigfr_bfr(ent_scratch_bigfr);
1488         }
1489 #endif  /* HAVE_PSEUG */
1490
1491         if (INDEFP(number)) {
1492                 if (XINDEF_DATA(number) == POS_INFINITY)
1493                         return number;
1494                 else if (XINDEF_DATA(number) == NEG_INFINITY)
1495                         return make_indef(POS_INFINITY);
1496                 else
1497                         return number;
1498         }
1499
1500         return Fabs(wrong_type_argument(Qnumberp, number));
1501 }
1502
1503 #if defined(HAVE_FPFLOAT)
1504 /* fuck fuck fuck, I want this in number.el */
1505 DEFUN("float", Ffloat, 1, 1, 0, /*
1506 Return the floating point number numerically equal to NUMBER.
1507 */
1508       (number))
1509 {
1510         /* Just create the float in order of preference */
1511         return Fcoerce_number(number, Qfloat, Qnil);
1512 }
1513 #endif  /* HAVE_FPFLOAT */
1514
1515 #ifdef HAVE_FPFLOAT
1516 DEFUN("logb", Flogb, 1, 1, 0,   /*
1517 Return largest integer <= the base 2 log of the magnitude of NUMBER.
1518 This is the same as the exponent of a float.
1519 */
1520       (number))
1521 {
1522         fpfloat f = extract_float(number);
1523
1524         if (f == 0.0)
1525                 return make_int(EMACS_INT_MIN);
1526 #ifdef HAVE_LOGB
1527         {
1528                 fpfloat _lb = logb(f);
1529                 Lisp_Object val;
1530                 IN_FLOAT(val = make_int((EMACS_INT)_lb), "logb", number);
1531                 return val;
1532         }
1533 #else
1534 #ifdef HAVE_FREXP
1535         {
1536                 int exqp;
1537                 IN_FLOAT(frexp(f, &exqp), "logb", number);
1538                 return make_int(exqp - 1);
1539         }
1540 #else
1541         {
1542                 int i;
1543                 fpfloat d;
1544                 EMACS_INT val;
1545                 if (f < 0.0)
1546                         f = -f;
1547                 val = -1;
1548                 while (f < 0.5) {
1549                         for (i = 1, d = 0.5; d * d >= f; i += i)
1550                                 d *= d;
1551                         f /= d;
1552                         val -= i;
1553                 }
1554                 while (f >= 1.0) {
1555                         for (i = 1, d = 2.0; d * d <= f; i += i)
1556                                 d *= d;
1557                         f /= d;
1558                         val += i;
1559                 }
1560                 return make_int(val);
1561         }
1562 #endif                          /* ! HAVE_FREXP */
1563 #endif                          /* ! HAVE_LOGB */
1564 }
1565 #endif                          /* HAVE_FPFLOAT */
1566
1567 DEFUN("ceiling", Fceiling, 1, 1, 0,     /*
1568 Return the smallest integer no less than NUMBER.  (Round toward +inf.)
1569 */
1570       (number))
1571 {
1572 #ifdef HAVE_FPFLOAT
1573         if (FLOATP(number)) {
1574                 fpfloat d;
1575                 d = ceil(XFLOAT_DATA(number));
1576                 return (float_to_int(d, "ceiling", number, Qunbound));
1577         }
1578 #endif                          /* HAVE_FPFLOAT */
1579
1580 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1581         if (INTEGERP(number))
1582 #else  /* !HAVE_MPZ */
1583         if (INTP(number))
1584 #endif  /* HAVE_MPZ */
1585                 return number;
1586
1587 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1588         if (BIGQP(number)) {
1589                 bigz_ceil(ent_scratch_bigz,
1590                           XBIGQ_NUMERATOR(number),
1591                           XBIGQ_DENOMINATOR(number));
1592                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1593         }
1594 #endif
1595
1596 #if defined HAVE_MPF && defined WITH_GMP
1597         else if (BIGFP(number)) {
1598 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1599                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
1600                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1601                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1602 #else  /* !HAVE_MPZ */
1603                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
1604                 return make_int((EMACS_INT)bigf_to_long(ent_scratch_bigf));
1605 #endif  /* HAVE_MPZ */
1606         }
1607 #endif  /* HAVE_MPF */
1608
1609 #if defined HAVE_MPFR && defined WITH_MPFR
1610         else if (BIGFRP(number)) {
1611 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1612                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
1613                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1614                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1615 #else  /* !HAVE_MPZ */
1616                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
1617                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1618 #endif  /* HAVE_MPZ */
1619         }
1620 #endif  /* HAVE_MPFR */
1621
1622         if (INDEFP(number))
1623                 return number;
1624
1625 #if defined HAVE_MPC && defined WITH_MPC ||     \
1626         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1627         defined HAVE_PSEUG && defined WITH_PSEUG
1628         return Fceiling(wrong_type_argument(Qcomparablep, number));
1629 #else  /* !HAVE_MPC */
1630         return Fceiling(wrong_type_argument(Qnumberp, number));
1631 #endif  /* HAVE_MPC */
1632 }
1633
1634 DEFUN("floor", Ffloor, 1, 2, 0, /*
1635 Return the largest integer no greater than NUMBER.  (Round towards -inf.)
1636 With optional second argument DIVISOR, return the largest integer no
1637 greater than NUMBER/DIVISOR.
1638 */
1639       (number, divisor))
1640 {
1641         ase_object_type_t ntquo;
1642         Lisp_Object quo;
1643
1644         CHECK_COMPARABLE(number);
1645         if (NILP(divisor)) {
1646                 return Ffloor(number, make_int(1L));
1647
1648         }
1649
1650         /* !NILP(divisor) */
1651
1652         CHECK_COMPARABLE(divisor);
1653
1654         if (INTEGERP(number) && INTEGERP(divisor)) {
1655 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1656                 /* this is the optimised version, since
1657                  * bigz_floor always takes two arguments
1658                  */
1659                 number = ent_lift(number, BIGZ_T, NULL);
1660                 divisor = ent_lift(divisor, BIGZ_T, NULL);
1661
1662                 bigz_floor(ent_scratch_bigz,
1663                            XBIGZ_DATA(number),
1664                            XBIGZ_DATA(divisor));
1665                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1666 #else
1667                 number = ent_lift(number, FLOAT_T, NULL);
1668                 divisor = ent_lift(divisor, FLOAT_T, NULL);
1669 #endif
1670         }
1671
1672         quo = ent_binop(ASE_BINARY_OP_QUO, number, divisor);
1673         ntquo = ase_optable_index(quo);
1674
1675         switch (ntquo) {
1676         case INT_T:             /* trivial */
1677         case BIGZ_T:
1678         case INDEF_T:
1679                 return quo;
1680                 break;
1681         case FLOAT_T: {
1682                 fpfloat d;
1683                 IN_FLOAT((d = floor(XFLOAT_DATA(quo))), "floor", quo);
1684                 return (float_to_int(d, "floor", quo, Qunbound));
1685         }
1686         case BIGQ_T:
1687 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1688                 bigz_floor(ent_scratch_bigz,
1689                            XBIGQ_NUMERATOR(quo), XBIGQ_DENOMINATOR(quo));
1690                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1691                 break;
1692 #else
1693                 return quo;
1694 #endif
1695         case BIGF_T:
1696 #if defined HAVE_MPF && defined WITH_GMP
1697                 bigf_floor(ent_scratch_bigf, XBIGF_DATA(quo));
1698 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1699                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1700                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1701 #else  /* !HAVE_MPZ */
1702                 return make_int(
1703                         (EMACS_INT)bigf_to_long(ent_scratch_bigf));
1704 #endif  /* HAVE_MPZ */
1705                 break;
1706 #endif  /* HAVE_MPF */
1707
1708         case BIGFR_T:
1709 #if defined HAVE_MPFR && defined WITH_MPFR
1710                 bigfr_floor(ent_scratch_bigfr, XBIGFR_DATA(quo));
1711 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1712                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1713                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1714 #else  /* !HAVE_MPZ */
1715                 return make_int(
1716                         (EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1717 #endif  /* HAVE_MPZ */
1718                 break;
1719 #endif  /* HAVE_MPFR */
1720
1721         default:
1722                 return quo;
1723         }
1724
1725         return Fsignal(Qdomain_error, Qnil);
1726 }
1727
1728 DEFUN("round", Fround, 1, 1, 0, /*
1729 Return the nearest integer to NUMBER.
1730
1731 NUMBER has to have an archimedian valuation, #'round returns the
1732 integer z for which | number - z | is minimal.
1733 */
1734       (number))
1735 {
1736 #ifdef HAVE_FPFLOAT
1737         if (FLOATP(number)) {
1738                 fpfloat d;
1739                 /* Screw the prevailing rounding mode.  */
1740                 d = emacs_rint(XFLOAT_DATA(number));
1741                 return (float_to_int(d, "round", number, Qunbound));
1742         }
1743 #endif                          /* HAVE_FPFLOAT */
1744
1745 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1746         if (INTEGERP(number))
1747 #else  /* !HAVE_MPZ */
1748         if (INTP(number))
1749 #endif  /* HAVE_MPZ */
1750                 return number;
1751
1752 #if defined(HAVE_MPQ) && defined(HAVE_MPZ) && defined WITH_GMP
1753         else if (BIGQP(number)) {
1754                 /* first off, let's create the division, remainder as well */
1755                 /* fuck ugly? */
1756                 mpz_tdiv_qr(ent_scratch_bigz,
1757                             bigq_numerator(ent_scratch_bigq),
1758                             XBIGQ_NUMERATOR(number),
1759                             XBIGQ_DENOMINATOR(number));
1760
1761                 /* <- denom(number) * 2 */
1762                 mpz_mul_2exp(bigq_numerator(ent_scratch_bigq),
1763                              bigq_numerator(ent_scratch_bigq), 1);
1764
1765                 /* check if we had to add one */
1766                 if (mpz_cmpabs(bigq_numerator(ent_scratch_bigq),
1767                                XBIGQ_DENOMINATOR(number)) >= 0) {
1768                         /* >= ceil(denom(number) / 2) */
1769                         if (mpz_sgn(bigq_numerator(ent_scratch_bigq)) > 0) {
1770                                 mpz_add_ui(ent_scratch_bigz,
1771                                            ent_scratch_bigz, 1UL);
1772                         } else {
1773                                 mpz_sub_ui(ent_scratch_bigz,
1774                                            ent_scratch_bigz, 1UL);
1775                         }
1776                 }
1777                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1778         }
1779 #endif  /* HAVE_MPQ && HAVE_MPZ */
1780
1781 #if defined HAVE_MPF && defined WITH_GMP
1782         else if (BIGFP(number)) {
1783                 warn_when_safe(Qbigf, Qnotice,
1784                                "rounding number of type 'bigf (mpf-floats)"
1785                                "not yet implemented");
1786                 return number;
1787         }
1788 #endif  /* HAVE_MPF */
1789
1790 #if defined HAVE_MPFR && defined WITH_MPFR
1791         else if (BIGFRP(number)) {
1792 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1793                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
1794                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1795                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1796 #else  /* !HAVE_MPZ */
1797                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
1798                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1799 #endif  /* HAVE_MPZ */
1800         }
1801 #endif  /* HAVE_MPFR */
1802
1803         else if (INDEFP(number))
1804                 return number;
1805
1806 #if defined HAVE_MPC && defined WITH_MPC ||     \
1807         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1808         defined HAVE_PSEUG && defined WITH_PSEUG
1809         return Fround(wrong_type_argument(Qcomparablep, number));
1810 #else  /* !HAVE_MPC */
1811         return Fround(wrong_type_argument(Qnumberp, number));
1812 #endif  /* HAVE_MPC */
1813 }
1814
1815 DEFUN("truncate", Ftruncate, 1, 1, 0,   /*
1816 Truncate a floating point number to an integer.
1817 Rounds the value toward zero.
1818 */
1819       (number))
1820 {
1821 #ifdef HAVE_FPFLOAT
1822         if (FLOATP(number))
1823                 return float_to_int(XFLOAT_DATA(number), "truncate", number,
1824                                     Qunbound);
1825 #endif                          /* HAVE_FPFLOAT */
1826
1827 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1828         if (INTEGERP(number))
1829 #else  /* !HAVE_MPZ */
1830         if (INTP(number))
1831 #endif  /* HAVE_MPZ */
1832                 return number;
1833
1834 #if defined HAVE_MPQ && defined WITH_GMP
1835         else if (BIGQP(number)) {
1836                 bigz_div(ent_scratch_bigz,
1837                          XBIGQ_NUMERATOR(number),
1838                          XBIGQ_DENOMINATOR(number));
1839                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1840         }
1841 #endif
1842
1843 #if defined HAVE_MPF && defined WITH_GMP
1844         else if (BIGFP(number)) {
1845 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1846                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
1847                 bigz_set_bigf(ent_scratch_bigz, ent_scratch_bigf);
1848                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1849 #else  /* !HAVE_MPZ */
1850                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
1851                 return make_int((EMACS_INT)bigf_to_long(ent_scratch_bigf));
1852 #endif  /* HAVE_MPZ */
1853         }
1854 #endif  /* HAVE_MPF */
1855
1856 #if defined HAVE_MPFR && defined WITH_MPFR
1857         else if (BIGFRP(number)) {
1858 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1859                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
1860                 bigz_set_bigfr(ent_scratch_bigz, ent_scratch_bigfr);
1861                 return ent_mpz_downgrade_maybe(ent_scratch_bigz);
1862 #else  /* !HAVE_MPZ */
1863                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
1864                 return make_int((EMACS_INT)bigfr_to_long(ent_scratch_bigfr));
1865 #endif  /* HAVE_MPZ */
1866         }
1867 #endif  /* HAVE_MPFR */
1868
1869         else if (INDEFP(number))
1870                 return number;
1871
1872 #if defined HAVE_MPC && defined WITH_MPC ||     \
1873         defined HAVE_PSEUC && defined WITH_PSEUC ||     \
1874         defined HAVE_PSEUG && defined WITH_PSEUG
1875         return Ftruncate(wrong_type_argument(Qcomparablep, number));
1876 #else  /* !HAVE_MPC */
1877         return Ftruncate(wrong_type_argument(Qnumberp, number));
1878 #endif  /* HAVE_MPC */
1879 }
1880
1881 DEFUN("almost=", Falmost_eq, 2, 3, 0,   /*
1882 Return t if NUMBER1 is almost equal to NUMBER2.
1883
1884 Optional argument THRES can be used to specify the threshold,
1885 float-epsilon by default.
1886 */
1887       (number1, number2, thres))
1888 {
1889 #if defined HAVE_FPFLOAT
1890         if (NILP(thres)) {
1891                 thres = Vfloat_epsilon;
1892         }
1893         CHECK_FLOAT(thres);
1894
1895         if (FLOATP(number1) && FLOATP(number2)) {
1896                 fpfloat n1 = XFLOAT_DATA(number1);
1897                 fpfloat n2 = XFLOAT_DATA(number2);
1898                 fpfloat thr = XFLOAT_DATA(thres);
1899                 fpfloat d;
1900                 if (n1 >= n2) {
1901                         d = n1 - n2;
1902                 } else {
1903                         d = n2 - n1;
1904                 }
1905                 return d < thr ? Qt : Qnil;
1906         }
1907 #endif  /* HAVE_FPFLOAT */
1908         return ent_binrel(ASE_BINARY_REL_EQUALP, number1, number2) ? Qt : Qnil;
1909 }
1910
1911 DEFUN("almost/=", Falmost_neq, 2, 3, 0, /*
1912 Return t if NUMBER1 is clearly different from NUMBER2.
1913
1914 Optional argument THRES can be used to specify the threshold,
1915 float-epsilon by default.
1916 */
1917       (number1, number2, thres))
1918 {
1919 #if defined HAVE_FPFLOAT
1920         if (NILP(thres)) {
1921                 thres = Vfloat_epsilon;
1922         }
1923         CHECK_FLOAT(thres);
1924
1925         if (FLOATP(number1) && FLOATP(number2)) {
1926                 fpfloat n1 = XFLOAT_DATA(number1);
1927                 fpfloat n2 = XFLOAT_DATA(number2);
1928                 fpfloat thr = XFLOAT_DATA(thres);
1929                 fpfloat d;
1930                 if (n1 >= n2) {
1931                         d = n1 - n2;
1932                 } else {
1933                         d = n2 - n1;
1934                 }
1935                 return d < thr ? Qnil : Qt;
1936         }
1937 #endif  /* HAVE_FPFLOAT */
1938         return ent_binrel(ASE_BINARY_REL_NEQP, number1, number2) ? Qt : Qnil;
1939 }
1940
1941 \f
1942 /* misc complex functions */
1943 DEFUN("conjugate", Fconjugate, 1, 1, 0, /*
1944 Return the \(canonical\) conjugate of NUMBER.
1945 If NUMBER is a comparable, just return NUMBER.
1946 */
1947       (number))
1948 {
1949         if (COMPARABLEP(number)) {
1950                 return number;
1951 #if defined HAVE_PSEUG && defined WITH_PSEUG
1952         } else if (BIGGP(number)) {
1953                 bigg_conj(ent_scratch_bigg, XBIGG_DATA(number));
1954                 return make_bigg_bg(ent_scratch_bigg);
1955 #endif
1956 #if defined HAVE_MPC && defined WITH_MPC ||     \
1957         defined HAVE_PSEUC && defined WITH_PSEUC
1958         } else if (BIGCP(number)) {
1959                 bigc_set_prec(ent_scratch_bigc, XBIGC_GET_PREC(number));
1960                 bigc_conj(ent_scratch_bigc, XBIGC_DATA(number));
1961                 return make_bigc_bc(ent_scratch_bigc);
1962 #endif
1963 #if defined HAVE_QUATERN && defined WITH_QUATERN
1964         } else if (QUATERNP(number)) {
1965                 quatern_conj(ent_scratch_quatern, XQUATERN_DATA(number));
1966                 return make_quatern_qu(ent_scratch_quatern);
1967 #endif
1968         } else if (INDEFP(number)) {
1969                 return number;
1970         }
1971
1972         /* what should the rest do? */
1973         return Fconjugate(wrong_type_argument(Qnumberp, number));
1974 }
1975
1976 DEFUN("canonical-norm", Fcanonical_norm, 1, 1, 0,       /*
1977 Return the canonical norm of NUMBER.
1978 */
1979       (number))
1980 {
1981         if (INDEFP(number)) {
1982                 if (INFINITYP(number))
1983                         return make_indef(POS_INFINITY);
1984                 else
1985                         return make_indef(NOT_A_NUMBER);
1986         } else if (COMPARABLEP(number)) {
1987                 return Fabs(number);
1988 #if defined HAVE_PSEUG && defined WITH_PSEUG
1989         } else if (BIGGP(number)) {
1990                 bigg_norm(ent_scratch_bigz, XBIGG_DATA(number));
1991                 return make_bigz_bz(ent_scratch_bigz);
1992 #endif
1993 #if defined HAVE_MPC && defined WITH_MPC ||     \
1994         defined HAVE_PSEUC && defined WITH_PSEUC
1995         } else if (BIGCP(number)) {
1996                 bigfr_set_prec(ent_scratch_bigfr, XBIGC_GET_PREC(number));
1997                 bigc_norm(ent_scratch_bigfr, XBIGC_DATA(number));
1998                 return make_bigfr_bfr(ent_scratch_bigfr);
1999 #endif
2000 #if defined HAVE_QUATERN && defined WITH_QUATERN
2001         } else if (QUATERNP(number)) {
2002                 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(number));
2003                 return make_bigz_bz(ent_scratch_bigz);
2004 #endif
2005         }
2006
2007         /* what should the rest do? */
2008         return Fcanonical_norm(wrong_type_argument(Qnumberp, number));
2009 }
2010
2011 DEFUN("real-part", Freal_part, 1, 1, 0, /*
2012 Return the real part of NUMBER.
2013 */
2014       (number))
2015 {
2016         if (INDEFP(number)) {
2017                 if (COMPARABLE_INDEF_P(number))
2018                         return number;
2019                 else if (INFINITYP(number))
2020                         return make_indef(POS_INFINITY);
2021                 else
2022                         return make_indef(NOT_A_NUMBER);
2023         } else if (COMPARABLEP(number)) {
2024                 return number;
2025 #if defined HAVE_PSEUG && defined WITH_PSEUG
2026         } else if (BIGGP(number)) {
2027                 return make_bigz_bz(bigg_re(XBIGG_DATA(number)));
2028 #endif
2029 #if defined HAVE_MPC && defined WITH_MPC ||     \
2030         defined HAVE_PSEUC && defined WITH_PSEUC
2031         } else if (BIGCP(number)) {
2032                 return make_bigfr_bfr(bigc_re(XBIGC_DATA(number)));
2033 #endif
2034         }
2035
2036         /* what should the rest do? */
2037         return Freal_part(wrong_type_argument(Qnumberp, number));
2038 }
2039
2040 DEFUN("imaginary-part", Fimaginary_part, 1, 1, 0,       /*
2041 Return the imaginary part of NUMBER.
2042 If NUMBER is a comparable, 0 is returned.
2043 */
2044       (number))
2045 {
2046         if (INDEFP(number)) {
2047                 if (COMPARABLE_INDEF_P(number))
2048                         return Qzero;
2049                 else if (INFINITYP(number))
2050                         return make_indef(POS_INFINITY);
2051                 else
2052                         return make_indef(NOT_A_NUMBER);
2053         } else if (RATIONALP(number)) {
2054                 return make_int(0);
2055 #if defined HAVE_MPFR && defined WITH_MPFR
2056         } else if (REALP(number)) {
2057                 return make_bigfr(0.0, 0UL);
2058 #endif
2059 #if defined HAVE_PSEUG && defined WITH_PSEUG
2060         } else if (BIGGP(number)) {
2061                 return make_bigz_bz(bigg_im(XBIGG_DATA(number)));
2062 #endif
2063 #if defined HAVE_MPC && defined WITH_MPC ||     \
2064         defined HAVE_PSEUC && defined WITH_PSEUC
2065         } else if (BIGCP(number)) {
2066                 return make_bigfr_bfr(bigc_im(XBIGC_DATA(number)));
2067 #endif
2068         }
2069
2070         /* what should the rest do? */
2071         return Fimaginary_part(wrong_type_argument(Qnumberp, number));
2072 }
2073
2074 \f
2075 /* Float-rounding functions. */
2076 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR || \
2077         defined(HAVE_MPF) && defined WITH_GMP
2078
2079 DEFUN("fceiling", Ffceiling, 1, 1, 0,   /*
2080 Return the smallest integer no less than NUMBER, as a float.
2081 \(Round toward +inf.\)
2082 */
2083       (number))
2084 {
2085 #if defined HAVE_MPF && defined WITH_GMP
2086         if (BIGFP(number)) {
2087                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2088
2089                 bigf_ceil(ent_scratch_bigf, XBIGF_DATA(number));
2090                 return make_bigf_bf(ent_scratch_bigf);
2091         }
2092 #endif  /* HAVE_MPF */
2093
2094 #if defined HAVE_MPFR && defined WITH_MPFR
2095         if (BIGFRP(number)) {
2096                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2097
2098                 bigfr_ceil(ent_scratch_bigfr, XBIGFR_DATA(number));
2099                 return make_bigfr_bfr(ent_scratch_bigfr);
2100         }
2101 #endif  /* HAVE_MPFR */
2102
2103         if (INDEFP(number))
2104                 return number;
2105
2106         number = ent_lift(number, FLOAT_T, NULL);
2107
2108         if (FLOATP(number))
2109                 return make_float(ceil(XFLOAT_DATA(number)));
2110         else
2111                 return number;
2112 }
2113
2114 DEFUN("ffloor", Fffloor, 1, 1, 0,       /*
2115 Return the largest integer no greater than NUMBER, as a float.
2116 \(Round towards -inf.\)
2117 */
2118       (number))
2119 {
2120 #if defined HAVE_MPF && defined WITH_GMP
2121         if (BIGFP(number)) {
2122                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2123
2124                 bigf_floor(ent_scratch_bigf, XBIGF_DATA(number));
2125                 return make_bigf_bf(ent_scratch_bigf);
2126         }
2127 #endif  /* HAVE_MPF */
2128
2129 #if defined HAVE_MPFR && defined WITH_MPFR
2130         if (BIGFRP(number)) {
2131                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2132
2133                 bigfr_floor(ent_scratch_bigfr, XBIGFR_DATA(number));
2134                 return make_bigfr_bfr(ent_scratch_bigfr);
2135         }
2136 #endif  /* HAVE_MPFR */
2137
2138         if (INDEFP(number))
2139                 return number;
2140
2141         number = ent_lift(number, FLOAT_T, NULL);
2142
2143         if (FLOATP(number))
2144                 return make_float(floor(XFLOAT_DATA(number)));
2145         else
2146                 return number;
2147 }
2148
2149 DEFUN("fround", Ffround, 1, 1, 0,       /*
2150 Return the nearest integer to NUMBER, as a float.
2151 */
2152       (number))
2153 {
2154 #if defined HAVE_MPF && defined WITH_GMP
2155         if (BIGFP(number)) {
2156                 warn_when_safe(Qbigf, Qnotice,
2157                                "rounding number of type 'bigf (mpf-floats)"
2158                                "not yet implemented");
2159                 return number;
2160         }
2161 #endif  /* HAVE_MPF */
2162
2163 #if defined HAVE_MPFR && defined WITH_MPFR
2164         if (BIGFRP(number)) {
2165                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2166
2167                 bigfr_rint(ent_scratch_bigfr, XBIGFR_DATA(number));
2168                 return make_bigfr_bfr(ent_scratch_bigfr);
2169         }
2170 #endif  /* HAVE_MPFR */
2171
2172         if (INDEFP(number))
2173                 return number;
2174
2175         number = ent_lift(number, FLOAT_T, NULL);
2176
2177         if (FLOATP(number))
2178                 return make_float(emacs_rint(XFLOAT_DATA(number)));
2179         else
2180                 return number;
2181 }
2182
2183 DEFUN("ftruncate", Fftruncate, 1, 1, 0, /*
2184 Truncate a floating point number to an integral float value.
2185 Rounds the value toward zero.
2186 */
2187       (number))
2188 {
2189         fpfloat d;
2190 #if defined HAVE_MPF && defined WITH_GMP
2191         if (BIGFP(number)) {
2192                 bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(number));
2193
2194                 bigf_trunc(ent_scratch_bigf, XBIGF_DATA(number));
2195                 return make_bigf_bf(ent_scratch_bigf);
2196         }
2197 #endif  /* HAVE_MPF */
2198
2199 #if defined HAVE_MPFR && defined WITH_MPFR
2200         if (BIGFRP(number)) {
2201                 bigfr_set_prec(ent_scratch_bigfr, XBIGFR_GET_PREC(number));
2202
2203                 bigfr_trunc(ent_scratch_bigfr, XBIGFR_DATA(number));
2204                 return make_bigfr_bfr(ent_scratch_bigfr);
2205         }
2206 #endif  /* HAVE_MPFR */
2207
2208         if (INDEFP(number))
2209                 return number;
2210
2211         number = ent_lift(number, FLOAT_T, NULL);
2212
2213         if (FLOATP(number)) {
2214                 d = XFLOAT_DATA(number);
2215                 if (d >= 0.0)
2216                         d = floor(d);
2217                 else
2218                         d = ceil(d);
2219                 return make_float(d);
2220         } else {
2221                 return number;
2222         }
2223 }
2224 #endif  /* HAVE_MPF(R) || HAVE_FPFLOAT (float-rounding functions) */
2225
2226 \f
2227 #ifdef HAVE_FPFLOAT
2228 #ifdef FLOAT_CATCH_SIGILL
2229 static SIGTYPE float_error(int signo)
2230 {
2231         if (!in_float)
2232                 fatal_error_signal(signo);
2233
2234         EMACS_REESTABLISH_SIGNAL(signo, arith_error);
2235         EMACS_UNBLOCK_SIGNAL(signo);
2236
2237         in_float = 0;
2238
2239         /* Was Fsignal(), but it just doesn't make sense for an error
2240            occurring inside a signal handler to be restartable, considering
2241            that anything could happen when the error is signaled and trapped
2242            and considering the asynchronous nature of signal handlers. */
2243         signal_error(Qarith_error, list1(float_error_arg));
2244 }
2245
2246 /* Another idea was to replace the library function `infnan'
2247    where SIGILL is signaled.  */
2248
2249 #endif                          /* FLOAT_CATCH_SIGILL */
2250
2251 /* In C++, it is impossible to determine what type matherr expects
2252    without some more configure magic.
2253    We shouldn't be using matherr anyways - it's a non-standard SYSVism. */
2254 #if defined (HAVE_MATHERR) && !defined(__cplusplus)
2255 int matherr(struct exception *x)
2256 {
2257         Lisp_Object args;
2258         if (!in_float)
2259                 /* Not called from emacs-lisp float routines; do the default thing. */
2260                 return 0;
2261
2262         /* if (!strcmp (x->name, "pow")) x->name = "expt"; */
2263
2264         args = Fcons(build_string(x->name),
2265                      Fcons(make_float(x->arg1), ((in_float == 2)
2266                                                  ? Fcons(make_float(x->arg2),
2267                                                          Qnil)
2268                                                  : Qnil)));
2269         switch (x->type) {
2270         case DOMAIN:
2271                 Fsignal(Qdomain_error, args);
2272                 break;
2273         case SING:
2274                 Fsignal(Qsingularity_error, args);
2275                 break;
2276         case OVERFLOW:
2277                 Fsignal(Qoverflow_error, args);
2278                 break;
2279         case UNDERFLOW:
2280                 Fsignal(Qunderflow_error, args);
2281                 break;
2282         default:
2283                 Fsignal(Qarith_error, args);
2284                 break;
2285         }
2286         return 1;               /* don't set errno or print a message */
2287 }
2288 #endif                          /* HAVE_MATHERR */
2289 #endif                          /* HAVE_FPFLOAT */
2290 \f
2291 void init_floatfns_very_early(void)
2292 {
2293 #ifdef HAVE_FPFLOAT
2294 # ifdef FLOAT_CATCH_SIGILL
2295         signal(SIGILL, float_error);
2296 # endif
2297         in_float = 0;
2298 #endif                          /* HAVE_FPFLOAT */
2299 }
2300
2301 void syms_of_floatfns(void)
2302 {
2303
2304         /* Trig functions.  */
2305
2306 #if defined(HAVE_FPFLOAT) || defined HAVE_MPFR && defined WITH_MPFR
2307         DEFSUBR(Facos);
2308         DEFSUBR(Fasin);
2309         DEFSUBR(Fatan);
2310         DEFSUBR(Fcos);
2311         DEFSUBR(Fsin);
2312         DEFSUBR(Ftan);
2313 #endif  /* HAVE_FPFLOAT || HAVE_MPFR*/
2314 #if defined HAVE_MPFR && defined WITH_MPFR
2315         DEFSUBR(Fsec);
2316         DEFSUBR(Fcsc);
2317         DEFSUBR(Fcot);
2318 #endif
2319
2320         /* Bessel functions */
2321
2322 #if 0
2323         DEFSUBR(Fbessel_y0);
2324         DEFSUBR(Fbessel_y1);
2325         DEFSUBR(Fbessel_yn);
2326         DEFSUBR(Fbessel_j0);
2327         DEFSUBR(Fbessel_j1);
2328         DEFSUBR(Fbessel_jn);
2329 #endif                          /* 0 */
2330
2331         /* Error functions. */
2332
2333 #if 1
2334 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2335         DEFSUBR(Ferf);
2336         DEFSUBR(Ferfc);
2337         DEFSUBR(Flog_gamma);
2338 #endif
2339 #endif                          /* 0 */
2340
2341         /* Root and Log functions. */
2342
2343 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2344         DEFSUBR(Fexp);
2345 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
2346         DEFSUBR(Fexp2);
2347         DEFSUBR(Fexp10);
2348 #if 0
2349         DEFSUBR(Fexpt);
2350 #endif
2351 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2352         DEFSUBR(Flog);
2353         DEFSUBR(Flog2);
2354         DEFSUBR(Flog10);
2355         DEFSUBR(Fsqrt);
2356         DEFSUBR(Fcube_root);
2357 #if defined HAVE_MPFR && defined WITH_MPFR
2358         DEFSUBR(Froot);
2359 #endif
2360 #endif  /* HAVE_FPFLOAT || HAVE_MPFR*/
2361
2362         /* Inverse trig functions. */
2363
2364 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPFR) && defined WITH_MPFR
2365         DEFSUBR(Facosh);
2366         DEFSUBR(Fasinh);
2367         DEFSUBR(Fatanh);
2368         DEFSUBR(Fcosh);
2369         DEFSUBR(Fsinh);
2370         DEFSUBR(Ftanh);
2371 #endif  /* HAVE_FPFLOAT || HAVE_MPFR */
2372 #if defined HAVE_MPFR && defined WITH_MPFR
2373         DEFSUBR(Fsech);
2374         DEFSUBR(Fcsch);
2375         DEFSUBR(Fcoth);
2376 #endif  /* HAVE_MPFR */
2377
2378         /* Rounding functions */
2379
2380         DEFSUBR(Fabs);
2381 #ifdef HAVE_FPFLOAT
2382         DEFSUBR(Ffloat);
2383         DEFSUBR(Flogb);
2384 #endif                          /* HAVE_FPFLOAT */
2385         DEFSUBR(Fceiling);
2386         DEFSUBR(Ffloor);
2387         DEFSUBR(Fround);
2388         DEFSUBR(Ftruncate);
2389         DEFSUBR(Falmost_eq);
2390         DEFSUBR(Falmost_neq);
2391
2392         /* misc complex functions */
2393         DEFSUBR(Fconjugate);
2394         DEFSUBR(Fcanonical_norm);
2395         DEFSUBR(Freal_part);
2396         DEFSUBR(Fimaginary_part);
2397
2398         /* Float-rounding functions. */
2399
2400 #if defined(HAVE_FPFLOAT) || defined(HAVE_MPF) && defined WITH_GMP ||   \
2401         defined(HAVE_MPFR) && defined WITH_MPFR
2402         DEFSUBR(Ffceiling);
2403         DEFSUBR(Fffloor);
2404         DEFSUBR(Ffround);
2405         DEFSUBR(Fftruncate);
2406 #endif  /* HAVE_FPFLOAT || HAVE_MPF(R) */
2407 }
2408
2409 void vars_of_floatfns(void)
2410 {
2411 }