Build Fix -- compatibility issue with newer autoconf
[sxemacs] / src / ent / ent-gmp.c
1 /*
2   ent-gmp.c -- Numeric types for SXEmacs
3   Copyright (C) 2004 Jerry James
4   Copyright (C) 2004, 2005, 2006 Sebastian Freundt
5
6   Author:  Jerry James
7   Backport:  Sebastian Freundt
8
9 This file is part of SXEmacs
10
11 SXEmacs is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 SXEmacs is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
23
24
25 #include <config.h>
26 #include <limits.h>
27 #include <math.h>
28 #include "lisp.h"
29 #include "sysproc.h"    /* For qxe_getpid */
30
31 #include "ent.h"
32
33 static mpf_t float_print_min, float_print_max;
34 gmp_randstate_t random_state;
35
36 bigz ent_scratch_bigz;
37 bigq ent_scratch_bigq;
38 bigf ent_scratch_bigf;
39
40 static ase_nullary_operation_f Qent_mpz_zero, Qent_mpz_one;
41 static ase_nullary_operation_f Qent_mpq_zero, Qent_mpq_one;
42 static ase_nullary_operation_f Qent_mpf_zero, Qent_mpf_one;
43
44 \f
45 #define yrealloc_array(ptr, type, len)          \
46         ((void)(ptr = (type*)yrealloc(ptr, (len) * sizeof(type))))
47
48
49 \f
50 /************************* Big Rational Integers ****************************/
51 static void
52 bigz_print (Lisp_Object obj, Lisp_Object printcharfun, int SXE_UNUSED(escapeflag))
53 {
54         Bufbyte *bstr;
55
56         bstr = (Bufbyte*)bigz_to_string(XBIGZ_DATA(obj), 10);
57         write_c_string((char*)bstr, printcharfun);
58         xfree(bstr);
59         bstr = (Bufbyte *)NULL;
60 }
61
62 static int
63 bigz_equal (Lisp_Object obj1, Lisp_Object obj2, int SXE_UNUSED(depth))
64 {
65         return bigz_eql(XBIGZ_DATA(obj1), XBIGZ_DATA(obj2));
66 }
67
68 static unsigned long
69 bigz_hash (Lisp_Object obj, int SXE_UNUSED(depth))
70 {
71         return (unsigned long)bigz_hashcode(XBIGZ_DATA(obj));
72 }
73
74 static const struct lrecord_description bigz_description[] = {
75         { XD_OPAQUE_DATA_PTR, offsetof(Lisp_Bigz, data) },
76         { XD_END }
77 };
78
79 DEFINE_BASIC_LRECORD_IMPLEMENTATION("bigz", bigz,
80                                     NULL, bigz_print, NULL,
81                                     bigz_equal, bigz_hash,
82                                     bigz_description, Lisp_Bigz);
83
84 \f
85 /************************** Rational Integer Fractions **********************/
86 static void
87 bigq_print (Lisp_Object obj, Lisp_Object printcharfun, int SXE_UNUSED(escapeflag))
88 {
89         Bufbyte *rstr;
90
91         rstr = (Bufbyte*)bigq_to_string(XBIGQ_DATA(obj), 10);
92         write_c_string((char *)rstr, printcharfun);
93         xfree(rstr);
94         rstr = (Bufbyte *)NULL;
95         return;
96 }
97
98 static int
99 bigq_equal (Lisp_Object obj1, Lisp_Object obj2, int SXE_UNUSED(depth))
100 {
101         return bigq_eql(XBIGQ_DATA(obj1), XBIGQ_DATA(obj2));
102 }
103
104 static unsigned long
105 bigq_hash (Lisp_Object obj, int SXE_UNUSED(depth))
106 {
107         return bigq_hashcode(XBIGQ_DATA(obj));
108 }
109
110 static const struct lrecord_description bigq_description[] = {
111         { XD_OPAQUE_DATA_PTR, offsetof (Lisp_Bigq, data) },
112         { XD_END }
113 };
114
115 DEFINE_BASIC_LRECORD_IMPLEMENTATION("bigq", bigq,
116                                     NULL, bigq_print, NULL,
117                                     bigq_equal, bigq_hash,
118                                     bigq_description, Lisp_Bigq);
119
120 \f
121 /********************************** Bigfs ***********************************/
122 static void
123 bigf_print(Lisp_Object obj, Lisp_Object printcharfun, int SXE_UNUSED(escapeflag))
124 {
125         Bufbyte *fstr = bigf_to_string(XBIGF_DATA(obj), 10);
126         write_c_string((char*)fstr, printcharfun);
127         xfree(fstr);
128         fstr = (Bufbyte *)NULL;
129         return;
130 }
131
132 static int
133 bigf_equal(Lisp_Object obj1, Lisp_Object obj2, int SXE_UNUSED(depth))
134 {
135         return bigf_eq(XBIGF_DATA(obj1), XBIGF_DATA(obj2));
136 }
137
138 static unsigned long
139 bigf_hash(Lisp_Object obj, int SXE_UNUSED(depth))
140 {
141         return bigf_hashcode(XBIGF_DATA(obj));
142 }
143
144 static const struct lrecord_description bigf_description[] = {
145         { XD_OPAQUE_DATA_PTR, offsetof(Lisp_Bigf, data) },
146         { XD_END }
147 };
148
149 DEFINE_BASIC_LRECORD_IMPLEMENTATION("bigf", bigf,
150                                     NULL, bigf_print, NULL,
151                                     bigf_equal, bigf_hash,
152                                     bigf_description, Lisp_Bigf);
153
154 DEFUN("bigf-get-precision", Fbigf_get_precision, 1, 1, 0, /*
155 Return the precision of bigf F as an integer.
156 */
157        (f))
158 {
159         CHECK_BIGF(f);
160         return make_integer((signed long)XBIGF_GET_PREC(f));
161 }
162
163 DEFUN("bigf-set-precision", Fbigf_set_precision, 2, 2, 0, /*
164 Set the precision of F, a bigf, to PRECISION, a nonnegative integer.
165 The new precision of F is returned.  Note that the return value may differ
166 from PRECISION if the underlying library is unable to support exactly
167 PRECISION bits of precision.
168 */
169        (f, precision))
170 {
171         unsigned long prec;
172
173         CHECK_BIGF(f);
174         if (INTP(precision)) {
175                 prec = (XINT(precision) <= 0)
176                         ? 1UL : (unsigned long)XINT(precision);
177         }
178 #ifdef HAVE_MPZ
179         else if (BIGZP(precision)) {
180                 prec = bigz_fits_ulong_p(XBIGZ_DATA(precision))
181                         ? bigz_to_ulong(XBIGZ_DATA(precision))
182                         : UINT_MAX;
183         }
184 #endif  /* HAVE_MPZ */
185         else {
186                 dead_wrong_type_argument(Qintegerp, f);
187                 return Qnil;
188         }
189
190         XBIGF_SET_PREC(f, prec);
191         return Fbigf_get_precision(f);
192 }
193
194
195 \f
196 Bufbyte *
197 bigf_to_string(mpf_t f, int base)
198 {
199         mp_exp_t expt;
200         Bufbyte *str = (Bufbyte*)mpf_get_str(NULL, &expt, base, 0, f);
201         const int sign = mpf_sgn(f);
202         const int neg = (sign < 0) ? 1 : 0;
203         int len = strlen((char *)str) + 1;  /* Count the null terminator */
204
205         /* Move digits down to insert a radix point */
206         if (expt <= 0) {
207                 /* We need room for a radix point and leading zeroes */
208                 const int space = -expt + 2;
209                 xrealloc_array(str, Bufbyte, len + space);
210                 memmove(&str[space + neg], &str[neg], len - neg);
211                 memset(&str[neg], '0', space);
212                 str[neg + 1] = '.';
213                 len += space;
214         } else if (expt < len) {
215                 /* We just need room for a radix point */
216                 xrealloc_array(str, Bufbyte, len + 1);
217                 memmove(&str[expt + neg + 1],
218                         &str[expt + neg],
219                         len - (expt + neg));
220                 str[expt + neg] = '.';
221                 len++;
222         } else {
223                 /* We need room for trailing zeroes */
224                 xrealloc_array(str, Bufbyte, expt + 1);
225                 memset(&str[len-1], '0', expt+2-len);
226                 str[expt] = '\0';
227                 len = expt + 1;
228         }
229         return str;
230 }
231
232 \f
233 /* reader funs */
234
235 Lisp_Object
236 read_bigz_string(const char *cp, int base)
237 {
238         Lisp_Object result;
239         bigz bz;
240
241         bigz_init(bz);
242
243         /* MPZ bigz_set_string has no effect
244          * with initial + sign */
245         if (*cp == '+') {
246                 cp++;
247         }
248
249         bigz_set_string(bz, (const char*)cp, base);
250         result = make_bigz_bz(bz);
251
252         bigz_fini(bz);
253         return result;
254 }
255
256
257 Lisp_Object read_bigq_string(char *cp)
258 {
259         bigq bq;
260         Lisp_Object result;
261
262         bigq_init(bq);
263
264         /* The GMP version of bigq_set_string (mpq_set_str) has the following
265            limitations:
266            - If p starts with a '+' sign, it does nothing; i.e., it leaves its
267            ratio argument untouched.
268            - If p has a '+' sign after the '/' (e.g., 300/+400), it sets the
269            numerator from the string, but *leaves the denominator unchanged*.
270            - If p has trailing nonnumeric characters, it sets the numerator from
271            the string, but leaves the denominator unchanged.
272            - If p has more than one '/', (e.g., 1/2/3), then it sets the
273            numerator from the string, but leaves the denominator unchanged.
274
275            Therefore, move p past any leading '+' signs, temporarily drop a null
276            after the numeric characters we are trying to convert, and then put
277            the nulled character back afterward.  I am not going to fix problem
278            #2; just don't write ratios that look like that. */
279         if (*cp == '+') {
280                 cp++;
281         }
282
283         bigq_set_string(bq, cp, 0);
284         bigq_canonicalize(bq);
285
286         result = ent_mpq_downgrade_maybe(bq);
287
288         bigq_fini(bq);
289         return result;
290 }
291
292 Lisp_Object read_bigf_string(char *cp)
293 {
294         bigf bf;
295         Lisp_Object result;
296
297         bigf_init_prec(bf, internal_get_precision(Qnil));
298
299         /* The GMP version of bigf_set_string (mpf_set_str)
300            has the following limitation: if p starts with a '+'
301            sign, it does nothing; i.e., it leaves its bigfloat
302            argument untouched.
303            Therefore, move p past any leading '+' signs. */
304         if (*cp == '+') {
305                 cp++;
306         }
307
308         bigf_set_string(bf, cp, 0);
309         result = make_bigf_bf(bf);
310
311         bigf_fini(bf);
312         return result;
313 }
314
315 /* bigz ops */
316 static inline int
317 _ent_mpz_zerop(bigz n)
318 {
319         return (bigz_sign(n) == 0);
320 }
321
322 static int
323 ent_mpz_zerop(Lisp_Object l)
324 {
325         return _ent_mpz_zerop(XBIGZ_DATA(l));
326 }
327
328 static inline int
329 _ent_mpz_onep(bigz n)
330 {
331         return (bigz_fits_long_p(n) && bigz_to_long(n) == 1L);
332 }
333
334 static int
335 ent_mpz_onep(Lisp_Object l)
336 {
337         return _ent_mpz_onep(XBIGZ_DATA(l));
338 }
339
340 static inline int
341 _ent_mpz_unitp(bigz n)
342 {
343         return (bigz_fits_long_p(n) &&
344                 (bigz_to_long(n) == 1L || bigz_to_long(n) == -1L));
345 }
346
347 static int
348 ent_mpz_unitp(Lisp_Object l)
349 {
350         return _ent_mpz_unitp(XBIGZ_DATA(l));
351 }
352
353 static Lisp_Object
354 ent_sum_BIGZ_T(Lisp_Object l, Lisp_Object r)
355 {
356         bigz_add(ent_scratch_bigz, XBIGZ_DATA(l), XBIGZ_DATA(r));
357         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
358 }
359 static Lisp_Object
360 ent_sum_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
361 {
362         bigz_set_long(ent_scratch_bigz, ent_int(r));
363         bigz_add(ent_scratch_bigz, XBIGZ_DATA(l), ent_scratch_bigz);
364         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
365 }
366 static Lisp_Object
367 ent_sum_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
368 {
369         return ent_sum_BIGZ_T_INT_T(r, l);
370 }
371 #ifdef HAVE_FPFLOAT
372 static Lisp_Object
373 ent_sum_BIGZ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
374 {
375         return __ent_binop_lift_1(
376                 ASE_BINARY_OP_SUM, BIGZ_T, l, FLOAT_T, r, NULL);
377 }
378 static Lisp_Object
379 ent_sum_FLOAT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
380 {
381         return __ent_binop_lift_2(
382                 ASE_BINARY_OP_SUM, FLOAT_T, l, BIGZ_T, r, NULL);
383 }
384 #endif
385
386 static Lisp_Object
387 ent_diff_BIGZ_T(Lisp_Object l, Lisp_Object r)
388 {
389         bigz_sub(ent_scratch_bigz, XBIGZ_DATA(l), XBIGZ_DATA(r));
390         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
391 }
392 static Lisp_Object
393 ent_diff_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
394 {
395         bigz_set_long(ent_scratch_bigz, ent_int(r));
396         bigz_sub(ent_scratch_bigz, XBIGZ_DATA(l), ent_scratch_bigz);
397         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
398 }
399 static Lisp_Object
400 ent_diff_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
401 {
402         bigz_set_long(ent_scratch_bigz, ent_int(l));
403         bigz_sub(ent_scratch_bigz, ent_scratch_bigz, XBIGZ_DATA(r));
404         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
405 }
406 #ifdef HAVE_FPFLOAT
407 static Lisp_Object
408 ent_diff_BIGZ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
409 {
410         return __ent_binop_lift_1(
411                 ASE_BINARY_OP_DIFF, BIGZ_T, l, FLOAT_T, r, NULL);
412 }
413 static Lisp_Object
414 ent_diff_FLOAT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
415 {
416         return __ent_binop_lift_2(
417                 ASE_BINARY_OP_DIFF, FLOAT_T, l, BIGZ_T, r, NULL);
418 }
419 #endif
420
421 static Lisp_Object
422 ent_neg_BIGZ_T(Lisp_Object l)
423 {
424         bigz_neg(ent_scratch_bigz, XBIGZ_DATA(l));
425         return make_bigz_bz(ent_scratch_bigz);
426 }
427
428 static Lisp_Object
429 ent_prod_BIGZ_T(Lisp_Object l, Lisp_Object r)
430 {
431         bigz_mul(ent_scratch_bigz, XBIGZ_DATA(l), XBIGZ_DATA(r));
432         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
433 }
434 static Lisp_Object
435 ent_prod_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
436 {
437         bigz_set_long(ent_scratch_bigz, ent_int(r));
438         bigz_mul(ent_scratch_bigz, XBIGZ_DATA(l), ent_scratch_bigz);
439         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
440 }
441 static Lisp_Object
442 ent_prod_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
443 {
444         return ent_prod_BIGZ_T_INT_T(r, l);
445 }
446 #ifdef HAVE_FPFLOAT
447 static Lisp_Object
448 ent_prod_BIGZ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
449 {
450         return __ent_binop_lift_1(
451                 ASE_BINARY_OP_PROD, BIGZ_T, l, FLOAT_T, r, NULL);
452 }
453 static Lisp_Object
454 ent_prod_FLOAT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
455 {
456         return __ent_binop_lift_2(
457                 ASE_BINARY_OP_PROD, FLOAT_T, l, BIGZ_T, r, NULL);
458 }
459 #endif
460
461 static Lisp_Object
462 ent_div_BIGZ_T(Lisp_Object l, Lisp_Object r)
463 {
464         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
465                 int lsgn = bigz_sign(XBIGZ_DATA(l));
466                 if (lsgn > 0)
467                         return make_indef(POS_INFINITY);
468                 else if (lsgn < 0)
469                         return make_indef(NEG_INFINITY);
470                 else
471                         return make_indef(NOT_A_NUMBER);
472         }
473         bigz_div(ent_scratch_bigz, XBIGZ_DATA(l), XBIGZ_DATA(r));
474         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
475 }
476 static Lisp_Object
477 ent_div_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
478 {
479         if (ent_int(r) == 0) {
480                 int lsgn = bigz_sign(XBIGZ_DATA(l));
481                 if (lsgn > 0)
482                         return make_indef(POS_INFINITY);
483                 else if (lsgn < 0)
484                         return make_indef(NEG_INFINITY);
485                 else
486                         return make_indef(NOT_A_NUMBER);
487         }
488
489         bigz_set_long(ent_scratch_bigz, ent_int(r));
490         bigz_div(ent_scratch_bigz, XBIGZ_DATA(l), ent_scratch_bigz);
491         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
492 }
493 static Lisp_Object
494 ent_div_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
495 {
496         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
497                 EMACS_INT rl = ent_int(l);
498                 if (rl > 0)
499                         return make_indef(POS_INFINITY);
500                 else if (rl < 0)
501                         return make_indef(NEG_INFINITY);
502                 else
503                         return make_indef(NOT_A_NUMBER);
504         }
505
506         bigz_set_long(ent_scratch_bigz, ent_int(l));
507         bigz_div(ent_scratch_bigz, ent_scratch_bigz, XBIGZ_DATA(r));
508         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
509 }
510 #ifdef HAVE_FPFLOAT
511 static Lisp_Object
512 ent_div_BIGZ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
513 {
514         return __ent_binop_lift_1(
515                 ASE_BINARY_OP_DIV, BIGZ_T, l, FLOAT_T, r, NULL);
516 }
517 static Lisp_Object
518 ent_div_FLOAT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
519 {
520         return __ent_binop_lift_2(
521                 ASE_BINARY_OP_DIV, FLOAT_T, l, BIGZ_T, r, NULL);
522 }
523 #endif
524
525 static Lisp_Object
526 ent_quo_BIGZ_T(Lisp_Object l, Lisp_Object r)
527 {
528         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
529                 int lsgn = bigz_sign(XBIGZ_DATA(l));
530                 if (lsgn > 0)
531                         return make_indef(POS_INFINITY);
532                 else if (lsgn < 0)
533                         return make_indef(NEG_INFINITY);
534                 else
535                         return make_indef(NOT_A_NUMBER);
536         }
537
538         bigq_set_bigz_bigz(ent_scratch_bigq,
539                            XBIGZ_DATA(l), XBIGZ_DATA(r));
540         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
541 }
542 static Lisp_Object
543 ent_quo_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
544 {
545         EMACS_INT rr = ent_int(r);
546         if (rr == 0) {
547                 int lsgn = bigz_sign(XBIGZ_DATA(l));
548                 if (lsgn > 0)
549                         return make_indef(POS_INFINITY);
550                 else if (lsgn < 0)
551                         return make_indef(NEG_INFINITY);
552                 else
553                         return make_indef(NOT_A_NUMBER);
554         }
555
556         bigz_set_long(ent_scratch_bigz, rr);
557         return make_bigq_bz(XBIGZ_DATA(l), ent_scratch_bigz);
558 }
559 static Lisp_Object
560 ent_quo_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
561 {
562         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
563                 EMACS_INT rl = ent_int(l);
564                 if (rl > 0)
565                         return make_indef(POS_INFINITY);
566                 else if (rl < 0)
567                         return make_indef(NEG_INFINITY);
568                 else
569                         return make_indef(NOT_A_NUMBER);
570         }
571
572         bigz_set_long(ent_scratch_bigz, ent_int(l));
573         return make_bigq_bz(ent_scratch_bigz, XBIGZ_DATA(r));
574 }
575
576 static Lisp_Object
577 ent_inv_BIGZ_T(Lisp_Object r)
578 {
579         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
580                 return make_indef(POS_INFINITY);
581         } else if (ent_mpz_unitp(r)) {
582                 return r;
583         } else {
584                 return make_bigq_bz(XBIGZ_DATA(Qent_mpz_one), XBIGZ_DATA(r));
585         }
586         return Qnil;
587 }
588 static Lisp_Object
589 ent_rem_BIGZ_T(Lisp_Object l, Lisp_Object r)
590 {
591         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
592                 return Qzero;
593         }
594         bigz_mod(ent_scratch_bigz, XBIGZ_DATA(l), XBIGZ_DATA(r));
595         return make_bigz_bz(ent_scratch_bigz);
596 }
597 static Lisp_Object
598 ent_rem_BIGZ_T_INT_T(Lisp_Object l, Lisp_Object r)
599 {
600         EMACS_INT rr = ent_int(r);
601         if (rr == 0) {
602                 return Qzero;
603         }
604         bigz_set_long(ent_scratch_bigz, rr);
605         bigz_mod(ent_scratch_bigz, XBIGZ_DATA(l), ent_scratch_bigz);
606         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
607 }
608 static Lisp_Object
609 ent_rem_INT_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
610 {
611         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
612                 return Qzero;
613         }
614         bigz_set_long(ent_scratch_bigz, ent_int(l));
615         bigz_mod(ent_scratch_bigz,  ent_scratch_bigz, XBIGZ_DATA(r));
616         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
617 }
618
619 static Lisp_Object
620 ent_pow_BIGZ_T_integer_trivial(Lisp_Object l, Lisp_Object r)
621 {
622         if (!bigz_fits_long_p(XBIGZ_DATA(l)))
623                 return Qnull_pointer;
624
625         if (bigz_to_long(XBIGZ_DATA(l)) == 1L) {
626                 return l;
627         } else if (bigz_to_long(XBIGZ_DATA(l)) == -1L) {
628                 if (!NILP(Fevenp(r)))
629                         return Qent_mpz_one;
630                 else
631                         return l;
632         } else if (ent_mpz_zerop(l)) {
633                 /* actually only idiots want to compute 0-powers
634                  * think I put a sleep(10) here to pretend that we're
635                  * working rilly hard to solve that problem */
636                 if (ent_unrel_zerop(r))
637                         return Qent_mpz_one;
638                 else
639                         return Qent_mpz_zero;
640         }
641         return Qnull_pointer;
642 }
643
644 static Lisp_Object
645 ent_pow_INT_T_integer_trivial(Lisp_Object l, Lisp_Object r)
646 {
647         if (XINT(l) == 1L) {
648                 return l;
649         } else if (XINT(l) == -1L) {
650                 if (!NILP(Fevenp(r)))
651                         return Qone;
652                 else
653                         return l;
654         } else if (XINT(l) == 0L) {
655                 /* actually only idiots want to compute 0-powers
656                  * think I put a sleep(10) here to pretend that we're
657                  * working rilly hard to solve that problem */
658                 if (ent_unrel_zerop(r))
659                         return Qone;
660                 else
661                         return Qzero;
662         }
663         return Qnull_pointer;
664 }
665
666 static Lisp_Object
667 ent_pow_integer_integer(Lisp_Object l, Lisp_Object r)
668 {
669         EMACS_INT expo = 0;
670         Lisp_Object result;
671
672         /* trivial cases */
673         if (INTP(l) && (result = ent_pow_INT_T_integer_trivial(l, r)))
674                 return result;
675         else if (BIGZP(l) && (result = ent_pow_BIGZ_T_integer_trivial(l, r)))
676                 return result;
677
678         if (NILP(Fnonnegativep(r))) {
679                 /* l can't be inverted in Z, we return 0 or the inverse in Q
680                  * depending on `common_lisp_slash' */
681                 if (!common_lisp_slash)
682                         return Qent_mpz_zero;
683                 else
684                         return ent_unop_inv(
685                                 ent_pow_integer_integer(l, ent_unop_neg(r)));
686         }
687
688         if (INTP(r)) {
689                 expo = XINT(r);
690         } else if (BIGZP(r)) {
691                 if (bigz_fits_long_p(XBIGZ_DATA(r)))
692                         expo = bigz_to_long(XBIGZ_DATA(r));
693                 else
694                         Fsignal(Qrange_error, list1(r));
695         } else {
696                 Fsignal(Qoperation_error, list1(r));
697                 return Qnil;
698         }
699
700         if (INTP(l)) {
701                 bigz_set_long(ent_scratch_bigz, XINT(l));
702         } else if (BIGZP(l)) {
703                 bigz_set(ent_scratch_bigz, XBIGZ_DATA(l));
704         } else {
705                 Fsignal(Qoperation_error, list1(l));
706                 return Qnil;
707         }
708
709         bigz_pow(ent_scratch_bigz, ent_scratch_bigz, expo);
710         return ent_mpz_downgrade_maybe(ent_scratch_bigz);
711 }
712
713 /* relations */
714 static int
715 ent_lt_bigz(Lisp_Object l, Lisp_Object r)
716 {
717         return (bigz_lt(XBIGZ_DATA(l), XBIGZ_DATA(r)));
718 }
719 static int
720 ent_lt_bigz_int(Lisp_Object l, Lisp_Object r)
721 {
722         bigz_set_long(ent_scratch_bigz, ent_int(r));
723         return (bigz_lt(XBIGZ_DATA(l), ent_scratch_bigz));
724 }
725 static int
726 ent_lt_int_bigz(Lisp_Object l, Lisp_Object r)
727 {
728         bigz_set_long(ent_scratch_bigz, ent_int(l));
729         return (bigz_lt(ent_scratch_bigz, XBIGZ_DATA(r)));
730 }
731
732 static int
733 ent_gt_bigz(Lisp_Object l, Lisp_Object r)
734 {
735         return (bigz_gt(XBIGZ_DATA(l), XBIGZ_DATA(r)));
736 }
737 static int
738 ent_gt_bigz_int(Lisp_Object l, Lisp_Object r)
739 {
740         bigz_set_long(ent_scratch_bigz, ent_int(r));
741         return (bigz_gt(XBIGZ_DATA(l), ent_scratch_bigz));
742 }
743 static int
744 ent_gt_int_bigz(Lisp_Object l, Lisp_Object r)
745 {
746         bigz_set_long(ent_scratch_bigz, ent_int(l));
747         return (bigz_gt(ent_scratch_bigz, XBIGZ_DATA(r)));
748 }
749
750 static int
751 ent_eq_bigz(Lisp_Object l, Lisp_Object r)
752 {
753         return (bigz_eql(XBIGZ_DATA(l), XBIGZ_DATA(r)));
754 }
755 static int
756 ent_eq_bigz_int(Lisp_Object l, Lisp_Object r)
757 {
758         bigz_set_long(ent_scratch_bigz, ent_int(r));
759         return (bigz_eql(XBIGZ_DATA(l), ent_scratch_bigz));
760 }
761 static int
762 ent_eq_int_bigz(Lisp_Object l, Lisp_Object r)
763 {
764         return ent_eq_bigz_int(r, l);
765 }
766
767 static int
768 ent_ne_bigz(Lisp_Object l, Lisp_Object r)
769 {
770         return !ent_eq_bigz(l, r);
771 }
772 static int
773 ent_ne_bigz_int(Lisp_Object l, Lisp_Object r)
774 {
775         return !ent_eq_bigz_int(l, r);
776 }
777 static int
778 ent_ne_int_bigz(Lisp_Object l, Lisp_Object r)
779 {
780         return ent_ne_bigz_int(r, l);
781 }
782
783 #ifdef HAVE_FPFLOAT
784 static int
785 ent_lt_bigzq_float(Lisp_Object l, Lisp_Object r)
786 {
787         return ent_binrel_lift_1(ASE_BINARY_REL_LESSP, l, r, NULL);
788 }
789 static int
790 ent_lt_float_bigzq(Lisp_Object l, Lisp_Object r)
791 {
792         return ent_binrel_lift_2(ASE_BINARY_REL_LESSP, l, r, NULL);
793 }
794 static int
795 ent_gt_bigzq_float(Lisp_Object l, Lisp_Object r)
796 {
797         return ent_binrel_lift_1(ASE_BINARY_REL_GREATERP, l, r, NULL);
798 }
799 static int
800 ent_gt_float_bigzq(Lisp_Object l, Lisp_Object r)
801 {
802         return ent_binrel_lift_2(ASE_BINARY_REL_GREATERP, l, r, NULL);
803 }
804 static int
805 ent_eq_bigzq_float(Lisp_Object l, Lisp_Object r)
806 {
807         return ent_binrel_lift_1(ASE_BINARY_REL_EQUALP, l, r, NULL);
808 }
809 static int
810 ent_eq_float_bigzq(Lisp_Object l, Lisp_Object r)
811 {
812         return ent_binrel_lift_2(ASE_BINARY_REL_EQUALP, l, r, NULL);
813 }
814 static int
815 ent_ne_bigzq_float(Lisp_Object l, Lisp_Object r)
816 {
817         return ent_binrel_lift_1(ASE_BINARY_REL_NEQP, l, r, NULL);
818 }
819 static int
820 ent_ne_float_bigzq(Lisp_Object l, Lisp_Object r)
821 {
822         return ent_binrel_lift_2(ASE_BINARY_REL_NEQP, l, r, NULL);
823 }
824 #endif
825
826 \f
827 static Lisp_Object
828 _ent_lift_INT_T_BIGZ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
829 {
830         return make_bigz(ent_int(number));
831 }
832
833 static Lisp_Object
834 _ent_lift_BIGZ_T_INT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
835 {
836         return make_int(bigz_to_long(XBIGZ_DATA(number)));
837 }
838
839 #ifdef HAVE_FPFLOAT
840 static Lisp_Object
841 _ent_lift_FLOAT_T_BIGZ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
842 {
843         bigz_set_fpfloat(ent_scratch_bigz, XFLOAT_DATA(number));
844         return make_bigz_bz(ent_scratch_bigz);
845 }
846
847 static Lisp_Object
848 _ent_lift_BIGZ_T_FLOAT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
849 {
850         /* can result in an indef object */
851         return make_float(bigz_to_fpfloat(XBIGZ_DATA(number)));
852 }
853 #endif
854
855 \f
856 /* bigq ops */
857 static int
858 ent_mpq_zerop(Lisp_Object l)
859 {
860         return (bigq_sign(XBIGQ_DATA(l)) == 0);
861 }
862
863 static int
864 ent_mpq_onep(Lisp_Object l)
865 {
866 #define num     bigq_numerator(XBIGQ_DATA(l))
867 #define den     bigq_denominator(XBIGQ_DATA(l))
868         return (bigz_fits_long_p(num) &&
869                 bigz_to_long(num) == 1L &&
870                 bigz_fits_long_p(den) &&
871                 bigz_to_long(den) == 1L);
872 #undef num
873 #undef den
874 }
875
876 static int
877 ent_mpq_unitp(Lisp_Object unused)
878 {
879         return 1;
880 }
881
882 static Lisp_Object
883 ent_sum_BIGQ_T(Lisp_Object l, Lisp_Object r)
884 {
885         bigq_add(ent_scratch_bigq, XBIGQ_DATA(l), XBIGQ_DATA(r));
886         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
887 }
888 static Lisp_Object
889 ent_sum_BIGQ_T_scratch(Lisp_Object l)
890 {
891         bigq_add(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
892         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
893 }
894 static Lisp_Object
895 ent_sum_BIGQ_T_INT_T(Lisp_Object l, Lisp_Object r)
896 {
897         bigq_set_long(ent_scratch_bigq, ent_int(r));
898         return ent_sum_BIGQ_T_scratch(l);
899 }
900 static Lisp_Object
901 ent_sum_INT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
902 {
903         bigq_set_long(ent_scratch_bigq, ent_int(l));
904         return ent_sum_BIGQ_T_scratch(r);
905 }
906 static Lisp_Object
907 ent_sum_BIGQ_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
908 {
909         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
910         return ent_sum_BIGQ_T_scratch(l);
911 }
912 static Lisp_Object
913 ent_sum_BIGZ_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
914 {
915         return ent_sum_BIGQ_T_BIGZ_T(r, l);
916 }
917 #ifdef HAVE_FPFLOAT
918 static Lisp_Object
919 ent_sum_BIGQ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
920 {
921         return __ent_binop_lift_1(
922                 ASE_BINARY_OP_SUM, BIGQ_T, l, FLOAT_T, r, NULL);
923 }
924 static Lisp_Object
925 ent_sum_FLOAT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
926 {
927         return __ent_binop_lift_2(
928                 ASE_BINARY_OP_SUM, FLOAT_T, l, BIGQ_T, r, NULL);
929 }
930 #endif
931
932 static Lisp_Object
933 ent_diff_BIGQ_T(Lisp_Object l, Lisp_Object r)
934 {
935         bigq_sub(ent_scratch_bigq, XBIGQ_DATA(l), XBIGQ_DATA(r));
936         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
937 }
938 static Lisp_Object
939 ent_diff_BIGQ_T_INT_T(Lisp_Object l, Lisp_Object r)
940 {
941         bigq_set_long(ent_scratch_bigq, ent_int(r));
942         bigq_sub(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
943         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
944 }
945 static Lisp_Object
946 ent_diff_INT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
947 {
948         bigq_set_long(ent_scratch_bigq, ent_int(l));
949         bigq_sub(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
950         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
951 }
952 static Lisp_Object
953 ent_diff_BIGQ_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
954 {
955         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
956         bigq_sub(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
957         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
958 }
959 static Lisp_Object
960 ent_diff_BIGZ_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
961 {
962         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
963         bigq_sub(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
964         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
965 }
966 #ifdef HAVE_FPFLOAT
967 static Lisp_Object
968 ent_diff_BIGQ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
969 {
970         return __ent_binop_lift_1(
971                 ASE_BINARY_OP_DIFF, BIGQ_T, l, FLOAT_T, r, NULL);
972 }
973 static Lisp_Object
974 ent_diff_FLOAT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
975 {
976         return __ent_binop_lift_2(
977                 ASE_BINARY_OP_SUM, FLOAT_T, l, BIGQ_T, r, NULL);
978 }
979 #endif
980
981 static Lisp_Object
982 ent_neg_BIGQ_T(Lisp_Object l)
983 {
984         bigq_neg(ent_scratch_bigq, XBIGQ_DATA(l));
985         return make_bigq_bq(ent_scratch_bigq);
986 }
987
988 static Lisp_Object
989 ent_prod_BIGQ_T(Lisp_Object l, Lisp_Object r)
990 {
991         bigq_mul(ent_scratch_bigq, XBIGQ_DATA(l), XBIGQ_DATA(r));
992         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
993 }
994 static Lisp_Object
995 ent_prod_BIGQ_T_INT_T(Lisp_Object l, Lisp_Object r)
996 {
997         bigq_set_long(ent_scratch_bigq, ent_int(r));
998         bigq_mul(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
999         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1000 }
1001 static Lisp_Object
1002 ent_prod_INT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1003 {
1004         return ent_prod_BIGQ_T_INT_T(r, l);
1005 }
1006 static Lisp_Object
1007 ent_prod_BIGQ_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1008 {
1009         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1010         bigq_mul(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
1011         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1012 }
1013 static Lisp_Object
1014 ent_prod_BIGZ_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1015 {
1016         return ent_prod_BIGQ_T_BIGZ_T(r, l);
1017 }
1018 #ifdef HAVE_FPFLOAT
1019 static Lisp_Object
1020 ent_prod_BIGQ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1021 {
1022         return __ent_binop_lift_1(
1023                 ASE_BINARY_OP_PROD, BIGQ_T, l, FLOAT_T, r, NULL);
1024 }
1025 static Lisp_Object
1026 ent_prod_FLOAT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1027 {
1028         return __ent_binop_lift_2(
1029                 ASE_BINARY_OP_PROD, FLOAT_T, l, BIGQ_T, r, NULL);
1030 }
1031 #endif
1032
1033 static Lisp_Object
1034 ent_div_BIGQ_T(Lisp_Object l, Lisp_Object r)
1035 {
1036         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1037                 int lsgn = bigq_sign(XBIGQ_DATA(l));
1038                 if (lsgn > 0)
1039                         return make_indef(POS_INFINITY);
1040                 else if (lsgn < 0)
1041                         return make_indef(NEG_INFINITY);
1042                 else
1043                         return make_indef(NOT_A_NUMBER);
1044         }
1045         bigq_div(ent_scratch_bigq, XBIGQ_DATA(l), XBIGQ_DATA(r));
1046         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1047 }
1048 static Lisp_Object
1049 ent_div_BIGQ_T_INT_T(Lisp_Object l, Lisp_Object r)
1050 {
1051         EMACS_INT rr = ent_int(r);
1052         if (rr == 0) {
1053                 int lsgn = bigq_sign(XBIGQ_DATA(l));
1054                 if (lsgn > 0)
1055                         return make_indef(POS_INFINITY);
1056                 else if (lsgn < 0)
1057                         return make_indef(NEG_INFINITY);
1058                 else
1059                         return make_indef(NOT_A_NUMBER);
1060         }
1061
1062         bigq_set_long(ent_scratch_bigq, rr);
1063         bigq_div(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
1064         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1065 }
1066 static Lisp_Object
1067 ent_div_INT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1068 {
1069         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1070                 EMACS_INT rl = ent_int(l);
1071                 if (rl > 0)
1072                         return make_indef(POS_INFINITY);
1073                 else if (rl < 0)
1074                         return make_indef(NEG_INFINITY);
1075                 else
1076                         return make_indef(NOT_A_NUMBER);
1077         }
1078
1079         bigq_set_long(ent_scratch_bigq, ent_int(l));
1080         bigq_div(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
1081         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1082 }
1083 static Lisp_Object
1084 ent_div_BIGQ_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1085 {
1086         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
1087                 int lsgn = bigq_sign(XBIGQ_DATA(l));
1088                 if (lsgn > 0)
1089                         return make_indef(POS_INFINITY);
1090                 else if (lsgn < 0)
1091                         return make_indef(NEG_INFINITY);
1092                 else
1093                         return make_indef(NOT_A_NUMBER);
1094         }
1095
1096         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1097         bigq_div(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
1098         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1099 }
1100 static Lisp_Object
1101 ent_div_BIGZ_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1102 {
1103         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1104                 int lsgn = bigz_sign(XBIGZ_DATA(l));
1105                 if (lsgn > 0)
1106                         return make_indef(POS_INFINITY);
1107                 else if (lsgn < 0)
1108                         return make_indef(NEG_INFINITY);
1109                 else
1110                         return make_indef(NOT_A_NUMBER);
1111         }
1112
1113         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
1114         bigq_div(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
1115         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1116 }
1117 #ifdef HAVE_FPFLOAT
1118 static Lisp_Object
1119 ent_div_BIGQ_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1120 {
1121         return __ent_binop_lift_1(
1122                 ASE_BINARY_OP_DIV, BIGQ_T, l, FLOAT_T, r, NULL);
1123 }
1124 static Lisp_Object
1125 ent_div_FLOAT_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1126 {
1127         return __ent_binop_lift_2(
1128                 ASE_BINARY_OP_DIV, FLOAT_T, l, BIGQ_T, r, NULL);
1129 }
1130 #endif
1131
1132 static Lisp_Object
1133 ent_quo_INT_T(Lisp_Object l, Lisp_Object r)
1134 {
1135         if (ent_int(r) == 0) {
1136                 if (ent_int(l) > 0)
1137                         return make_indef(POS_INFINITY);
1138                 else if (ent_int(l) < 0)
1139                         return make_indef(NEG_INFINITY);
1140                 else
1141                         return make_indef(NOT_A_NUMBER);
1142         }
1143
1144         if (ent_int(r) < 0) {
1145                 bigq_set_long_ulong(ent_scratch_bigq,
1146                                     -ent_int(l), (unsigned long)-ent_int(r));
1147                 return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1148         } else {
1149                 bigq_set_long_ulong(ent_scratch_bigq,
1150                                     ent_int(l), (unsigned long)ent_int(r));
1151                 return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1152         }
1153 }
1154
1155 static Lisp_Object
1156 ent_inv_BIGQ_T(Lisp_Object r)
1157 {
1158         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1159                 return make_indef(POS_INFINITY);
1160         }
1161         bigq_set_long(ent_scratch_bigq, 1L);
1162         bigq_div(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
1163         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1164 }
1165
1166 static Lisp_Object
1167 ent_inv_INT_T(Lisp_Object l)
1168 {
1169         if (ent_int(l) == 0) {
1170                 return make_indef(POS_INFINITY);
1171         }
1172         return make_bigq(1L, ent_int(l));
1173 }
1174
1175 static Lisp_Object
1176 ent_rem_BIGQ_T(Lisp_Object unused, Lisp_Object r)
1177 {
1178         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1179                 return Qzero;
1180         }
1181         /* actually the zero constructor should be called */
1182         return Qent_mpq_zero;
1183 }
1184 static Lisp_Object
1185 ent_mod_BIGQ_T(Lisp_Object l, Lisp_Object r)
1186 {
1187         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1188                 return Qzero;
1189         }
1190         bigq_div(ent_scratch_bigq, XBIGQ_DATA(l), XBIGQ_DATA(r));
1191         bigz_div(ent_scratch_bigz,
1192                  bigq_numerator(ent_scratch_bigq),
1193                  bigq_denominator(ent_scratch_bigq));
1194
1195         bigq_set_bigz(ent_scratch_bigq, ent_scratch_bigz);
1196         bigq_mul(ent_scratch_bigq, ent_scratch_bigq, XBIGQ_DATA(r));
1197         bigq_sub(ent_scratch_bigq, XBIGQ_DATA(l), ent_scratch_bigq);
1198         return ent_mpq_downgrade_maybe(ent_scratch_bigq);
1199 }
1200
1201 static Lisp_Object
1202 ent_pow_BIGQ_T_integer_trivial(Lisp_Object l, Lisp_Object r)
1203 {
1204         if (!_ent_mpz_onep(XBIGQ_DENOMINATOR(l)) ||
1205             !bigz_fits_long_p(XBIGQ_NUMERATOR(l)))
1206                 return Qnull_pointer;
1207
1208         if (bigz_to_long(XBIGQ_NUMERATOR(l)) == 1L) {
1209                 return l;
1210         } else if (bigz_to_long(XBIGQ_NUMERATOR(l)) == -1L) {
1211                 if (!NILP(Fevenp(r)))
1212                         return Qent_mpq_one;
1213                 else
1214                         return l;
1215         } else if (ent_mpq_zerop(l)) {
1216                 /* actually only idiots want to compute 0-powers
1217                  * think I put a sleep(10) here to pretend that we're
1218                  * working rilly hard to solve that problem */
1219                 if (ent_unrel_zerop(r))
1220                         return Qent_mpq_one;
1221                 else
1222                         return Qent_mpq_zero;
1223         }
1224         return Qnull_pointer;
1225 }
1226
1227 static Lisp_Object
1228 ent_pow_BIGQ_T_integer(Lisp_Object l, Lisp_Object r)
1229 {
1230         Lisp_Object num, den, result;
1231
1232         /* trivial cases */
1233         if ((result = ent_pow_BIGQ_T_integer_trivial(l, r)))
1234                 return result;
1235
1236         if (NILP(Fnonnegativep(r))) {
1237                 return ent_unop_inv(
1238                         ent_pow_BIGQ_T_integer(l, ent_unop_neg(r)));
1239         }
1240
1241         num = ent_binop(ASE_BINARY_OP_POW,
1242                         make_bigz_bz(XBIGQ_NUMERATOR(l)), r);
1243         den = ent_binop(ASE_BINARY_OP_POW,
1244                         make_bigz_bz(XBIGQ_DENOMINATOR(l)), r);
1245
1246         if (!INTEGERP(num) || !INTEGERP(den)) {
1247                 Fsignal(Qdomain_error, list2(num, den));
1248                 return Qnil;
1249         }
1250
1251         if (BIGZP(num) && BIGZP(den))
1252                 return make_bigq_bz(XBIGZ_DATA(num), XBIGZ_DATA(den));
1253         else if (INTP(num) && INTP(den))
1254                 return make_bigq(ent_int(num), ent_int(den));
1255         else {
1256                 num = ent_lift(num, BIGZ_T, NULL);
1257                 den = ent_lift(den, BIGZ_T, NULL);
1258                 return make_bigq_bz(XBIGZ_DATA(num), XBIGZ_DATA(den));
1259         }
1260
1261         return Qzero;
1262 }
1263
1264 /* relations */
1265 static int
1266 ent_lt_bigq(Lisp_Object l, Lisp_Object r)
1267 {
1268         return (bigq_lt(XBIGQ_DATA(l), XBIGQ_DATA(r)));
1269 }
1270 static int
1271 ent_lt_bigq_int(Lisp_Object l, Lisp_Object r)
1272 {
1273         bigq_set_long(ent_scratch_bigq, ent_int(r));
1274         return (bigq_lt(XBIGQ_DATA(l), ent_scratch_bigq));
1275 }
1276 static int
1277 ent_lt_int_bigq(Lisp_Object l, Lisp_Object r)
1278 {
1279         bigq_set_long(ent_scratch_bigq, ent_int(l));
1280         return (bigq_lt(ent_scratch_bigq, XBIGQ_DATA(r)));
1281 }
1282 static int
1283 ent_lt_bigq_bigz(Lisp_Object l, Lisp_Object r)
1284 {
1285         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1286         return (bigq_lt(XBIGQ_DATA(l), ent_scratch_bigq));
1287 }
1288 static int
1289 ent_lt_bigz_bigq(Lisp_Object l, Lisp_Object r)
1290 {
1291         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
1292         return (bigq_lt(ent_scratch_bigq, XBIGQ_DATA(r)));
1293 }
1294
1295 static int
1296 ent_gt_bigq(Lisp_Object l, Lisp_Object r)
1297 {
1298         return (bigq_gt(XBIGQ_DATA(l), XBIGQ_DATA(r)));
1299 }
1300 static int
1301 ent_gt_bigq_int(Lisp_Object l, Lisp_Object r)
1302 {
1303         bigq_set_long(ent_scratch_bigq, ent_int(r));
1304         return (bigq_gt(XBIGQ_DATA(l), ent_scratch_bigq));
1305 }
1306 static int
1307 ent_gt_int_bigq(Lisp_Object l, Lisp_Object r)
1308 {
1309         bigq_set_long(ent_scratch_bigq, ent_int(l));
1310         return (bigq_gt(ent_scratch_bigq, XBIGQ_DATA(r)));
1311 }
1312 static int
1313 ent_gt_bigq_bigz(Lisp_Object l, Lisp_Object r)
1314 {
1315         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1316         return (bigq_gt(XBIGQ_DATA(l), ent_scratch_bigq));
1317 }
1318 static int
1319 ent_gt_bigz_bigq(Lisp_Object l, Lisp_Object r)
1320 {
1321         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
1322         return (bigq_gt(ent_scratch_bigq, XBIGQ_DATA(r)));
1323 }
1324
1325 static int
1326 ent_eq_bigq(Lisp_Object l, Lisp_Object r)
1327 {
1328         return (bigq_eql(XBIGQ_DATA(l), XBIGQ_DATA(r)));
1329 }
1330 static int
1331 ent_eq_bigq_int(Lisp_Object l, Lisp_Object r)
1332 {
1333         bigq_set_long(ent_scratch_bigq, ent_int(r));
1334         return (bigq_eql(XBIGQ_DATA(l), ent_scratch_bigq));
1335 }
1336 static int
1337 ent_eq_int_bigq(Lisp_Object l, Lisp_Object r)
1338 {
1339         bigq_set_long(ent_scratch_bigq, ent_int(l));
1340         return (bigq_eql(ent_scratch_bigq, XBIGQ_DATA(r)));
1341 }
1342 static int
1343 ent_eq_bigq_bigz(Lisp_Object l, Lisp_Object r)
1344 {
1345         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1346         return (bigq_eql(XBIGQ_DATA(l), ent_scratch_bigq));
1347 }
1348 static int
1349 ent_eq_bigz_bigq(Lisp_Object l, Lisp_Object r)
1350 {
1351         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
1352         return (bigq_eql(ent_scratch_bigq, XBIGQ_DATA(r)));
1353 }
1354
1355 static int
1356 ent_ne_bigq(Lisp_Object l, Lisp_Object r)
1357 {
1358         return !(bigq_eql(XBIGQ_DATA(l), XBIGQ_DATA(r)));
1359 }
1360 static int
1361 ent_ne_bigq_int(Lisp_Object l, Lisp_Object r)
1362 {
1363         bigq_set_long(ent_scratch_bigq, ent_int(r));
1364         return !(bigq_eql(XBIGQ_DATA(l), ent_scratch_bigq));
1365 }
1366 static int
1367 ent_ne_int_bigq(Lisp_Object l, Lisp_Object r)
1368 {
1369         bigq_set_long(ent_scratch_bigq, ent_int(l));
1370         return !(bigq_eql(ent_scratch_bigq, XBIGQ_DATA(r)));
1371 }
1372 static int
1373 ent_ne_bigq_bigz(Lisp_Object l, Lisp_Object r)
1374 {
1375         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(r));
1376         return !(bigq_eql(XBIGQ_DATA(l), ent_scratch_bigq));
1377 }
1378 static int
1379 ent_ne_bigz_bigq(Lisp_Object l, Lisp_Object r)
1380 {
1381         bigq_set_bigz(ent_scratch_bigq, XBIGZ_DATA(l));
1382         return !(bigq_eql(ent_scratch_bigq, XBIGQ_DATA(r)));
1383 }
1384
1385 \f
1386 static inline Lisp_Object
1387 _ent_lift_INT_T_BIGQ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1388 {
1389         return make_bigq(ent_int(number), 1UL);
1390 }
1391
1392 static inline Lisp_Object
1393 _ent_lift_BIGQ_T_INT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1394 {
1395         bigz_div(ent_scratch_bigz,
1396                  XBIGQ_NUMERATOR(number),
1397                  XBIGQ_DENOMINATOR(number));
1398         return make_int(bigz_to_long(ent_scratch_bigz));
1399 }
1400
1401 static inline Lisp_Object
1402 _ent_lift_BIGZ_T_BIGQ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1403 {
1404         bigz_set_long(ent_scratch_bigz, 1L);
1405         return make_bigq_bz(XBIGZ_DATA(number), ent_scratch_bigz);
1406 }
1407
1408 static inline Lisp_Object
1409 _ent_lift_BIGQ_T_BIGZ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1410 {
1411         bigz_div(ent_scratch_bigz,
1412                  XBIGQ_NUMERATOR(number),
1413                  XBIGQ_DENOMINATOR(number));
1414         return make_bigz_bz(ent_scratch_bigz);
1415 }
1416
1417 #ifdef HAVE_FPFLOAT
1418 static inline Lisp_Object
1419 _ent_lift_FLOAT_T_BIGQ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1420 {
1421         bigq_set_fpfloat(ent_scratch_bigq, XFLOAT_DATA(number));
1422         return make_bigq_bq(ent_scratch_bigq);
1423 }
1424
1425 static inline Lisp_Object
1426 _ent_lift_BIGQ_T_FLOAT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1427 {
1428         /* can result in an indef object */
1429         return make_float(bigq_to_fpfloat(XBIGQ_DATA(number)));
1430 }
1431 #endif
1432
1433 \f
1434 /* bigf ops */
1435 static int
1436 ent_mpf_zerop(Lisp_Object l)
1437 {
1438         return (bigf_sign(XBIGF_DATA(l)) == 0);
1439 }
1440
1441 static int
1442 ent_mpf_onep(Lisp_Object l)
1443 {
1444         return (bigf_to_fpfloat(XBIGF_DATA(l)) == 1.0f);
1445 }
1446
1447 static int
1448 ent_mpf_unitp(Lisp_Object unused)
1449 {
1450         return 1;
1451 }
1452
1453 static Lisp_Object
1454 ent_sum_BIGF_T(Lisp_Object l, Lisp_Object r)
1455 {
1456         bigf_set_prec(ent_scratch_bigf,
1457                       max(XBIGF_GET_PREC(l), XBIGF_GET_PREC(r)));
1458         bigf_add(ent_scratch_bigf, XBIGF_DATA(l), XBIGF_DATA(r));
1459         return make_bigf_bf(ent_scratch_bigf);
1460 }
1461 static Lisp_Object
1462 ent_sum_BIGF_T_INT_T(Lisp_Object l, Lisp_Object r)
1463 {
1464         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1465         bigf_set_long(ent_scratch_bigf, ent_int(r));
1466         bigf_add(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1467         return make_bigf_bf(ent_scratch_bigf);
1468 }
1469 static Lisp_Object
1470 ent_sum_INT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1471 {
1472         return ent_sum_BIGF_T_INT_T(r, l);
1473 }
1474 static Lisp_Object
1475 ent_sum_BIGF_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1476 {
1477         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1478         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1479         bigf_add(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1480         return make_bigf_bf(ent_scratch_bigf);
1481 }
1482 static Lisp_Object
1483 ent_sum_BIGZ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1484 {
1485         return ent_sum_BIGF_T_BIGZ_T(r, l);
1486 }
1487 static Lisp_Object
1488 ent_sum_BIGF_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1489 {
1490         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1491         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
1492         bigf_add(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1493         return make_bigf_bf(ent_scratch_bigf);
1494 }
1495 static Lisp_Object
1496 ent_sum_BIGQ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1497 {
1498         return ent_sum_BIGF_T_BIGQ_T(r, l);
1499 }
1500 #ifdef HAVE_FPFLOAT
1501 static Lisp_Object
1502 ent_sum_BIGF_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1503 {
1504         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1505         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
1506         bigf_add(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1507         return make_bigf_bf(ent_scratch_bigf);
1508 }
1509 static Lisp_Object
1510 ent_sum_FLOAT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1511 {
1512         return ent_sum_BIGF_T_FLOAT_T(r, l);
1513 }
1514 #endif
1515
1516 static Lisp_Object
1517 ent_diff_BIGF_T(Lisp_Object l, Lisp_Object r)
1518 {
1519         bigf_set_prec(ent_scratch_bigf,
1520                       max(XBIGF_GET_PREC(l), XBIGF_GET_PREC(r)));
1521         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), XBIGF_DATA(r));
1522         return make_bigf_bf(ent_scratch_bigf);
1523 }
1524 static Lisp_Object
1525 ent_diff_BIGF_T_INT_T(Lisp_Object l, Lisp_Object r)
1526 {
1527         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1528         bigf_set_long(ent_scratch_bigf, ent_int(r));
1529         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1530         return make_bigf_bf(ent_scratch_bigf);
1531 }
1532 static Lisp_Object
1533 ent_diff_INT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1534 {
1535         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1536         bigf_set_long(ent_scratch_bigf, ent_int(l));
1537         bigf_sub(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1538         return make_bigf_bf(ent_scratch_bigf);
1539 }
1540 static Lisp_Object
1541 ent_diff_BIGF_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1542 {
1543         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1544         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1545         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1546         return make_bigf_bf(ent_scratch_bigf);
1547 }
1548 static Lisp_Object
1549 ent_diff_BIGZ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1550 {
1551         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1552         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(l));
1553         bigf_sub(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1554         return make_bigf_bf(ent_scratch_bigf);
1555 }
1556 static Lisp_Object
1557 ent_diff_BIGF_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1558 {
1559         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1560         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
1561         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1562         return make_bigf_bf(ent_scratch_bigf);
1563 }
1564 static Lisp_Object
1565 ent_diff_BIGQ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1566 {
1567         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1568         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(l));
1569         bigf_sub(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1570         return make_bigf_bf(ent_scratch_bigf);
1571 }
1572 #ifdef HAVE_FPFLOAT
1573 static Lisp_Object
1574 ent_diff_BIGF_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1575 {
1576         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1577         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
1578         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1579         return make_bigf_bf(ent_scratch_bigf);
1580 }
1581 static Lisp_Object
1582 ent_diff_FLOAT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1583 {
1584         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1585         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
1586         bigf_sub(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1587         return make_bigf_bf(ent_scratch_bigf);
1588 }
1589 #endif
1590
1591 static Lisp_Object
1592 ent_neg_BIGF_T(Lisp_Object l)
1593 {
1594         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1595         bigf_neg(ent_scratch_bigf, XBIGF_DATA(l));
1596         return make_bigf_bf(ent_scratch_bigf);
1597 }
1598
1599 static Lisp_Object
1600 ent_prod_BIGF_T(Lisp_Object l, Lisp_Object r)
1601 {
1602         bigf_set_prec(ent_scratch_bigf,
1603                       max(XBIGF_GET_PREC(l), XBIGF_GET_PREC(r)));
1604         bigf_mul(ent_scratch_bigf, XBIGF_DATA(l), XBIGF_DATA(r));
1605         return make_bigf_bf(ent_scratch_bigf);
1606 }
1607 static Lisp_Object
1608 ent_prod_BIGF_T_INT_T(Lisp_Object l, Lisp_Object r)
1609 {
1610         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1611         bigf_set_long(ent_scratch_bigf, ent_int(r));
1612         bigf_mul(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1613         return make_bigf_bf(ent_scratch_bigf);
1614 }
1615 static Lisp_Object
1616 ent_prod_INT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1617 {
1618         return ent_prod_BIGF_T_INT_T(r, l);
1619 }
1620 static Lisp_Object
1621 ent_prod_BIGF_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1622 {
1623         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1624         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1625         bigf_mul(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1626         return make_bigf_bf(ent_scratch_bigf);
1627 }
1628 static Lisp_Object
1629 ent_prod_BIGZ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1630 {
1631         return ent_prod_BIGF_T_BIGZ_T(r, l);
1632 }
1633 static Lisp_Object
1634 ent_prod_BIGF_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1635 {
1636         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1637         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
1638         bigf_mul(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1639         return make_bigf_bf(ent_scratch_bigf);
1640 }
1641 static Lisp_Object
1642 ent_prod_BIGQ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1643 {
1644         return ent_prod_BIGF_T_BIGQ_T(r, l);
1645 }
1646 #ifdef HAVE_FPFLOAT
1647 static Lisp_Object
1648 ent_prod_BIGF_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1649 {
1650         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1651         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
1652         bigf_mul(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1653         return make_bigf_bf(ent_scratch_bigf);
1654 }
1655 static Lisp_Object
1656 ent_prod_FLOAT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1657 {
1658         return ent_prod_BIGF_T_FLOAT_T(r, l);
1659 }
1660 #endif
1661
1662 static Lisp_Object
1663 ent_div_BIGF_T(Lisp_Object l, Lisp_Object r)
1664 {
1665         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1666                 int lsgn = bigf_sign(XBIGF_DATA(l));
1667                 if (lsgn > 0)
1668                         return make_indef(POS_INFINITY);
1669                 else if (lsgn < 0)
1670                         return make_indef(NEG_INFINITY);
1671                 else
1672                         return make_indef(NOT_A_NUMBER);
1673         }
1674         bigf_set_prec(ent_scratch_bigf,
1675                       max(XBIGF_GET_PREC(l), XBIGF_GET_PREC(r)));
1676         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), XBIGF_DATA(r));
1677         return make_bigf_bf(ent_scratch_bigf);
1678 }
1679 static Lisp_Object
1680 ent_div_BIGF_T_INT_T(Lisp_Object l, Lisp_Object r)
1681 {
1682         EMACS_INT rr = ent_int(r);
1683         if (rr == 0) {
1684                 int lsgn = bigf_sign(XBIGF_DATA(l));
1685                 if (lsgn > 0)
1686                         return make_indef(POS_INFINITY);
1687                 else if (lsgn < 0)
1688                         return make_indef(NEG_INFINITY);
1689                 else
1690                         return make_indef(NOT_A_NUMBER);
1691         }
1692
1693         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1694         bigf_set_long(ent_scratch_bigf, rr);
1695         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1696         return make_bigf_bf(ent_scratch_bigf);
1697 }
1698 static Lisp_Object
1699 ent_div_INT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1700 {
1701         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1702                 EMACS_INT rl = ent_int(l);
1703                 if (rl > 0)
1704                         return make_indef(POS_INFINITY);
1705                 else if (rl < 0)
1706                         return make_indef(NEG_INFINITY);
1707                 else
1708                         return make_indef(NOT_A_NUMBER);
1709         }
1710
1711         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1712         bigf_set_long(ent_scratch_bigf, ent_int(l));
1713         bigf_div(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1714         return make_bigf_bf(ent_scratch_bigf);
1715 }
1716 static Lisp_Object
1717 ent_div_BIGF_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
1718 {
1719         if (bigz_sign(XBIGZ_DATA(r)) == 0) {
1720                 int lsgn = bigf_sign(XBIGF_DATA(l));
1721                 if (lsgn > 0)
1722                         return make_indef(POS_INFINITY);
1723                 else if (lsgn < 0)
1724                         return make_indef(NEG_INFINITY);
1725                 else
1726                         return make_indef(NOT_A_NUMBER);
1727         }
1728
1729         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1730         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1731         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1732         return make_bigf_bf(ent_scratch_bigf);
1733 }
1734 static Lisp_Object
1735 ent_div_BIGZ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1736 {
1737         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1738                 int lsgn = bigz_sign(XBIGZ_DATA(l));
1739                 if (lsgn > 0)
1740                         return make_indef(POS_INFINITY);
1741                 else if (lsgn < 0)
1742                         return make_indef(NEG_INFINITY);
1743                 else
1744                         return make_indef(NOT_A_NUMBER);
1745         }
1746
1747         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1748         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(l));
1749         bigf_div(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1750         return make_bigf_bf(ent_scratch_bigf);
1751 }
1752 static Lisp_Object
1753 ent_div_BIGF_T_BIGQ_T(Lisp_Object l, Lisp_Object r)
1754 {
1755         if (bigq_sign(XBIGQ_DATA(r)) == 0) {
1756                 int lsgn = bigf_sign(XBIGF_DATA(l));
1757                 if (lsgn > 0)
1758                         return make_indef(POS_INFINITY);
1759                 else if (lsgn < 0)
1760                         return make_indef(NEG_INFINITY);
1761                 else
1762                         return make_indef(NOT_A_NUMBER);
1763         }
1764
1765         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1766         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
1767         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1768         return make_bigf_bf(ent_scratch_bigf);
1769 }
1770 static Lisp_Object
1771 ent_div_BIGQ_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1772 {
1773         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1774                 int lsgn = bigq_sign(XBIGQ_DATA(l));
1775                 if (lsgn > 0)
1776                         return make_indef(POS_INFINITY);
1777                 else if (lsgn < 0)
1778                         return make_indef(NEG_INFINITY);
1779                 else
1780                         return make_indef(NOT_A_NUMBER);
1781         }
1782
1783         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1784         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(l));
1785         bigf_div(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1786         return make_bigf_bf(ent_scratch_bigf);
1787 }
1788 #ifdef HAVE_FPFLOAT
1789 static Lisp_Object
1790 ent_div_BIGF_T_FLOAT_T(Lisp_Object l, Lisp_Object r)
1791 {
1792         if (XFLOAT_DATA(r) == 0.0f) {
1793                 int lsgn = bigf_sign(XBIGF_DATA(l));
1794                 if (lsgn > 0)
1795                         return make_indef(POS_INFINITY);
1796                 else if (lsgn < 0)
1797                         return make_indef(NEG_INFINITY);
1798                 else
1799                         return make_indef(NOT_A_NUMBER);
1800         }
1801
1802         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1803         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
1804         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1805         return make_bigf_bf(ent_scratch_bigf);
1806 }
1807 static Lisp_Object
1808 ent_div_FLOAT_T_BIGF_T(Lisp_Object l, Lisp_Object r)
1809 {
1810         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1811                 if (XFLOAT_DATA(l) > 0.0f)
1812                         return make_indef(POS_INFINITY);
1813                 else if (XFLOAT_DATA(l) < 0.0f)
1814                         return make_indef(NEG_INFINITY);
1815                 else
1816                         return make_indef(NOT_A_NUMBER);
1817         }
1818
1819         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1820         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
1821         bigf_div(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1822         return make_bigf_bf(ent_scratch_bigf);
1823 }
1824 #endif
1825
1826 static Lisp_Object
1827 ent_inv_BIGF_T(Lisp_Object r)
1828 {
1829         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1830                 return make_indef(POS_INFINITY);
1831         }
1832         bigf_set_long(ent_scratch_bigf, 1L);
1833         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(r));
1834         bigf_div(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1835         return make_bigf_bf(ent_scratch_bigf);
1836 }
1837
1838 static Lisp_Object
1839 ent_rem_BIGF_T(Lisp_Object unused, Lisp_Object r)
1840 {
1841         return Qent_mpf_zero;;
1842 }
1843
1844 static Lisp_Object
1845 ent_mod_BIGF_T(Lisp_Object l, Lisp_Object r)
1846 {
1847         if (bigf_sign(XBIGF_DATA(r)) == 0) {
1848                 return Qent_mpf_zero;;
1849         }
1850         bigf_set_prec(ent_scratch_bigf,
1851                       max(XBIGF_GET_PREC(l), XBIGF_GET_PREC(r)));
1852         bigf_div(ent_scratch_bigf, XBIGF_DATA(l), XBIGF_DATA(r));
1853         bigf_trunc(ent_scratch_bigf, ent_scratch_bigf);
1854         bigf_mul(ent_scratch_bigf, ent_scratch_bigf, XBIGF_DATA(r));
1855         bigf_sub(ent_scratch_bigf, XBIGF_DATA(l), ent_scratch_bigf);
1856         return make_bigf_bf(ent_scratch_bigf);
1857 }
1858 #if defined(bigf_pow)
1859 static Lisp_Object
1860 ent_pow_BIGF_T_integer_trivial(Lisp_Object l, Lisp_Object r)
1861 {
1862         if (bigf_to_fpfloat(XBIGF_DATA(l)) == 1.0f) {
1863                 return l;
1864         } else if (bigf_to_fpfloat(XBIGF_DATA(l)) == -1.0f) {
1865                 if (!NILP(Fevenp(r)))
1866                         return Qent_mpf_one;
1867                 else
1868                         return l;
1869         } else if (ent_mpf_zerop(l)) {
1870                 /* actually only idiots want to compute 0-powers
1871                  * think I put a sleep(10) here to pretend that we're
1872                  * working rilly hard to solve that problem */
1873                 if (ent_unrel_zerop(r))
1874                         return Qent_mpf_one;
1875                 else
1876                         return Qent_mpf_zero;
1877         }
1878         return Qnull_pointer;
1879 }
1880
1881 static Lisp_Object
1882 ent_pow_BIGF_T_integer(Lisp_Object l, Lisp_Object r)
1883 {
1884         unsigned long expo = 0;
1885         Lisp_Object result;
1886
1887         /* trivial cases */
1888         if ((result = ent_pow_BIGF_T_integer_trivial(l, r)))
1889                 return result;
1890
1891         if (NILP(Fnonnegativep(r))) {
1892                 return ent_unop_inv(
1893                         ent_pow_BIGF_T_integer(l, ent_unop_neg(r)));
1894         }
1895
1896         if (INTP(r)) {
1897                 expo = XINT(r);
1898         } else if (BIGZP(r)) {
1899                 if (bigz_fits_ulong_p(XBIGZ_DATA(r)))
1900                         expo = bigz_to_ulong(XBIGZ_DATA(r));
1901                 else
1902                         Fsignal(Qrange_error, list1(r));
1903         } else {
1904                 Fsignal(Qoperation_error, list1(r));
1905                 return Qnil;
1906         }
1907
1908         bigf_set_prec(ent_scratch_bigf, XBIGF_GET_PREC(l));
1909         bigf_pow(ent_scratch_bigf, XBIGF_DATA(l), expo);
1910         return make_bigf_bf(ent_scratch_bigf);
1911 }
1912 #endif
1913
1914 /* relations */
1915 static int
1916 ent_lt_bigf(Lisp_Object l, Lisp_Object r)
1917 {
1918         return (bigf_lt(XBIGF_DATA(l), XBIGF_DATA(r)));
1919 }
1920 static int
1921 ent_lt_bigf_int(Lisp_Object l, Lisp_Object r)
1922 {
1923         bigf_set_long(ent_scratch_bigf, ent_int(r));
1924         return (bigf_lt(XBIGF_DATA(l), ent_scratch_bigf));
1925 }
1926 static int
1927 ent_lt_int_bigf(Lisp_Object l, Lisp_Object r)
1928 {
1929         bigf_set_long(ent_scratch_bigf, ent_int(l));
1930         return (bigf_lt(ent_scratch_bigf, XBIGF_DATA(r)));
1931 }
1932 static int
1933 ent_lt_bigf_bigz(Lisp_Object l, Lisp_Object r)
1934 {
1935         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1936         return (bigf_lt(XBIGF_DATA(l), ent_scratch_bigf));
1937 }
1938 static int
1939 ent_lt_bigz_bigf(Lisp_Object l, Lisp_Object r)
1940 {
1941         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(l));
1942         return (bigf_lt(ent_scratch_bigf, XBIGF_DATA(r)));
1943 }
1944 static int
1945 ent_lt_bigf_bigq(Lisp_Object l, Lisp_Object r)
1946 {
1947         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
1948         return (bigf_lt(XBIGF_DATA(l), ent_scratch_bigf));
1949 }
1950 static int
1951 ent_lt_bigq_bigf(Lisp_Object l, Lisp_Object r)
1952 {
1953         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(l));
1954         return (bigf_lt(ent_scratch_bigf, XBIGF_DATA(r)));
1955 }
1956 #ifdef HAVE_FPFLOAT
1957 static int
1958 ent_lt_bigf_fpfloat(Lisp_Object l, Lisp_Object r)
1959 {
1960         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
1961         return (bigf_lt(XBIGF_DATA(l), ent_scratch_bigf));
1962 }
1963 static int
1964 ent_lt_fpfloat_bigf(Lisp_Object l, Lisp_Object r)
1965 {
1966         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
1967         return (bigf_lt(ent_scratch_bigf, XBIGF_DATA(r)));
1968 }
1969 #endif
1970
1971 static int
1972 ent_gt_bigf(Lisp_Object l, Lisp_Object r)
1973 {
1974         return (bigf_gt(XBIGF_DATA(l), XBIGF_DATA(r)));
1975 }
1976 static int
1977 ent_gt_bigf_int(Lisp_Object l, Lisp_Object r)
1978 {
1979         bigf_set_long(ent_scratch_bigf, ent_int(r));
1980         return (bigf_gt(XBIGF_DATA(l), ent_scratch_bigf));
1981 }
1982 static int
1983 ent_gt_int_bigf(Lisp_Object l, Lisp_Object r)
1984 {
1985         bigf_set_long(ent_scratch_bigf, ent_int(l));
1986         return (bigf_gt(ent_scratch_bigf, XBIGF_DATA(r)));
1987 }
1988 static int
1989 ent_gt_bigf_bigz(Lisp_Object l, Lisp_Object r)
1990 {
1991         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
1992         return (bigf_gt(XBIGF_DATA(l), ent_scratch_bigf));
1993 }
1994 static int
1995 ent_gt_bigz_bigf(Lisp_Object l, Lisp_Object r)
1996 {
1997         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(l));
1998         return (bigf_gt(ent_scratch_bigf, XBIGF_DATA(r)));
1999 }
2000 static int
2001 ent_gt_bigf_bigq(Lisp_Object l, Lisp_Object r)
2002 {
2003         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
2004         return (bigf_gt(XBIGF_DATA(l), ent_scratch_bigf));
2005 }
2006 static int
2007 ent_gt_bigq_bigf(Lisp_Object l, Lisp_Object r)
2008 {
2009         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(l));
2010         return (bigf_gt(ent_scratch_bigf, XBIGF_DATA(r)));
2011 }
2012 #ifdef HAVE_FPFLOAT
2013 static int
2014 ent_gt_bigf_fpfloat(Lisp_Object l, Lisp_Object r)
2015 {
2016         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
2017         return (bigf_gt(XBIGF_DATA(l), ent_scratch_bigf));
2018 }
2019 static int
2020 ent_gt_fpfloat_bigf(Lisp_Object l, Lisp_Object r)
2021 {
2022         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
2023         return (bigf_gt(ent_scratch_bigf, XBIGF_DATA(r)));
2024 }
2025 #endif
2026
2027 static int
2028 ent_eq_bigf(Lisp_Object l, Lisp_Object r)
2029 {
2030         return (bigf_eq(XBIGF_DATA(l), XBIGF_DATA(r)));
2031 }
2032 static int
2033 ent_eq_bigf_int(Lisp_Object l, Lisp_Object r)
2034 {
2035         bigf_set_long(ent_scratch_bigf, ent_int(r));
2036         return (bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2037 }
2038 static int
2039 ent_eq_int_bigf(Lisp_Object l, Lisp_Object r)
2040 {
2041         return ent_eq_bigf_int(r, l);
2042 }
2043 static int
2044 ent_eq_bigf_bigz(Lisp_Object l, Lisp_Object r)
2045 {
2046         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
2047         return (bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2048 }
2049 static int
2050 ent_eq_bigz_bigf(Lisp_Object l, Lisp_Object r)
2051 {
2052         return ent_eq_bigf_bigz(r, l);
2053 }
2054 static int
2055 ent_eq_bigf_bigq(Lisp_Object l, Lisp_Object r)
2056 {
2057         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
2058         return (bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2059 }
2060 static int
2061 ent_eq_bigq_bigf(Lisp_Object l, Lisp_Object r)
2062 {
2063         return ent_eq_bigf_bigq(r, l);
2064 }
2065 #ifdef HAVE_FPFLOAT
2066 static int
2067 ent_eq_bigf_fpfloat(Lisp_Object l, Lisp_Object r)
2068 {
2069         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
2070         return (bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2071 }
2072 static int
2073 ent_eq_fpfloat_bigf(Lisp_Object l, Lisp_Object r)
2074 {
2075         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
2076         return (bigf_eq(ent_scratch_bigf, XBIGF_DATA(r)));
2077 }
2078 #endif
2079
2080 static int
2081 ent_ne_bigf(Lisp_Object l, Lisp_Object r)
2082 {
2083         return !(bigf_eq(XBIGF_DATA(l), XBIGF_DATA(r)));
2084 }
2085 static int
2086 ent_ne_bigf_int(Lisp_Object l, Lisp_Object r)
2087 {
2088         bigf_set_long(ent_scratch_bigf, ent_int(r));
2089         return !(bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2090 }
2091 static int
2092 ent_ne_int_bigf(Lisp_Object l, Lisp_Object r)
2093 {
2094         return ent_ne_bigf_int(r, l);
2095 }
2096 static int
2097 ent_ne_bigf_bigz(Lisp_Object l, Lisp_Object r)
2098 {
2099         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(r));
2100         return !(bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2101 }
2102 static int
2103 ent_ne_bigz_bigf(Lisp_Object l, Lisp_Object r)
2104 {
2105         return ent_ne_bigf_bigz(r, l);
2106 }
2107 static int
2108 ent_ne_bigf_bigq(Lisp_Object l, Lisp_Object r)
2109 {
2110         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(r));
2111         return !(bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2112 }
2113 static int
2114 ent_ne_bigq_bigf(Lisp_Object l, Lisp_Object r)
2115 {
2116         return ent_ne_bigf_bigq(r, l);
2117 }
2118 #ifdef HAVE_FPFLOAT
2119 static int
2120 ent_ne_bigf_fpfloat(Lisp_Object l, Lisp_Object r)
2121 {
2122         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(r));
2123         return !(bigf_eq(XBIGF_DATA(l), ent_scratch_bigf));
2124 }
2125 static int
2126 ent_ne_fpfloat_bigf(Lisp_Object l, Lisp_Object r)
2127 {
2128         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(l));
2129         return !(bigf_eq(ent_scratch_bigf, XBIGF_DATA(r)));
2130 }
2131 #endif
2132
2133 \f
2134 static Lisp_Object
2135 ent_lift_INT_T_BIGF_T(Lisp_Object number, ent_lift_args_t la)
2136 {
2137         unsigned long precision = la->precision;
2138
2139         return make_bigf(ent_int(number), precision);
2140 }
2141
2142 static Lisp_Object
2143 ent_lift_BIGF_T_INT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
2144 {
2145         return make_int(bigf_to_long(XBIGF_DATA(number)));
2146 }
2147
2148 static Lisp_Object
2149 ent_lift_BIGZ_T_BIGF_T(Lisp_Object number, ent_lift_args_t la)
2150 {
2151         unsigned long precision = la->precision;
2152
2153         bigf_set_prec(ent_scratch_bigf, precision);
2154         bigf_set_bigz(ent_scratch_bigf, XBIGZ_DATA(number));
2155         return make_bigf_bf(ent_scratch_bigf);
2156 }
2157
2158 static Lisp_Object
2159 ent_lift_BIGF_T_BIGZ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
2160 {
2161         bigz_set_bigf(ent_scratch_bigz, XBIGF_DATA(number));
2162         return make_bigz_bz(ent_scratch_bigz);
2163 }
2164
2165 static Lisp_Object
2166 ent_lift_BIGQ_T_BIGF_T(Lisp_Object number, ent_lift_args_t la)
2167 {
2168         unsigned long precision = la->precision;
2169
2170         bigf_set_prec(ent_scratch_bigf, precision);
2171         bigf_set_bigq(ent_scratch_bigf, XBIGQ_DATA(number));
2172         return make_bigf_bf(ent_scratch_bigf);
2173 }
2174
2175 static Lisp_Object
2176 ent_lift_BIGF_T_BIGQ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
2177 {
2178         bigq_set_bigf(ent_scratch_bigq, XBIGF_DATA(number));
2179         return make_bigq_bq(ent_scratch_bigq);
2180 }
2181
2182 #ifdef HAVE_FPFLOAT
2183 static Lisp_Object
2184 ent_lift_FLOAT_T_BIGF_T(Lisp_Object number, ent_lift_args_t la)
2185 {
2186         unsigned long precision = la->precision;
2187
2188         bigf_set_prec(ent_scratch_bigf, precision);
2189         bigf_set_fpfloat(ent_scratch_bigf, XFLOAT_DATA(number));
2190         return make_bigf_bf(ent_scratch_bigf);
2191 }
2192
2193 static Lisp_Object
2194 ent_lift_BIGF_T_FLOAT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
2195 {
2196         /* can result in an indef object */
2197         return make_float(bigf_to_fpfloat(XBIGF_DATA(number)));
2198 }
2199 #endif
2200
2201 static Lisp_Object
2202 ent_lift_BIGF_T_BIGF_T(Lisp_Object number, ent_lift_args_t la)
2203 {
2204         unsigned long precision = la->precision;
2205
2206         bigf_set_prec(ent_scratch_bigf, precision);
2207         bigf_set(ent_scratch_bigf, XBIGF_DATA(number));
2208         return make_bigf_bf(ent_scratch_bigf);
2209 }
2210
2211 \f
2212 static inline void
2213 ent_mpz_nullary_optable_init(void)
2214 {
2215         Qent_mpz_zero = make_bigz(0L);
2216         Qent_mpz_one = make_bigz(1L);
2217         staticpro(&Qent_mpz_zero);
2218         staticpro(&Qent_mpz_one);
2219
2220         ent_nullop_register(ASE_NULLARY_OP_ZERO, BIGZ_T, Qent_mpz_zero);
2221         ent_nullop_register(ASE_NULLARY_OP_ONE, BIGZ_T, Qent_mpz_one);
2222 }
2223
2224 static inline void
2225 ent_mpz_unary_optable_init(void)
2226 {
2227         ent_unop_register(ASE_UNARY_OP_NEG, BIGZ_T, ent_neg_BIGZ_T);
2228         ent_unop_register(ASE_UNARY_OP_INV, BIGZ_T, ent_inv_BIGZ_T);
2229 }
2230
2231 static inline void
2232 ent_mpz_binary_optable_init(void)
2233 {
2234         ent_binop_register(ASE_BINARY_OP_SUM,
2235                            BIGZ_T, BIGZ_T, ent_sum_BIGZ_T);
2236         ent_binop_register(ASE_BINARY_OP_SUM,
2237                            BIGZ_T, INT_T, ent_sum_BIGZ_T_INT_T);
2238         ent_binop_register(ASE_BINARY_OP_SUM,
2239                            INT_T, BIGZ_T, ent_sum_INT_T_BIGZ_T);
2240 #ifdef HAVE_FPFLOAT
2241         ent_binop_register(ASE_BINARY_OP_SUM,
2242                            FLOAT_T, BIGZ_T, ent_sum_FLOAT_T_BIGZ_T);
2243         ent_binop_register(ASE_BINARY_OP_SUM,
2244                            BIGZ_T, FLOAT_T, ent_sum_BIGZ_T_FLOAT_T);
2245 #endif
2246
2247         ent_binop_register(ASE_BINARY_OP_DIFF,
2248                            BIGZ_T, BIGZ_T, ent_diff_BIGZ_T);
2249         ent_binop_register(ASE_BINARY_OP_DIFF,
2250                            BIGZ_T, INT_T, ent_diff_BIGZ_T_INT_T);
2251         ent_binop_register(ASE_BINARY_OP_DIFF,
2252                            INT_T, BIGZ_T, ent_diff_INT_T_BIGZ_T);
2253 #ifdef HAVE_FPFLOAT
2254         ent_binop_register(ASE_BINARY_OP_DIFF,
2255                            FLOAT_T, BIGZ_T, ent_diff_FLOAT_T_BIGZ_T);
2256         ent_binop_register(ASE_BINARY_OP_DIFF,
2257                            BIGZ_T, FLOAT_T, ent_diff_BIGZ_T_FLOAT_T);
2258 #endif
2259
2260         ent_binop_register(ASE_BINARY_OP_PROD,
2261                            BIGZ_T, BIGZ_T, ent_prod_BIGZ_T);
2262         ent_binop_register(ASE_BINARY_OP_PROD,
2263                            BIGZ_T, INT_T, ent_prod_BIGZ_T_INT_T);
2264         ent_binop_register(ASE_BINARY_OP_PROD,
2265                            INT_T, BIGZ_T, ent_prod_INT_T_BIGZ_T);
2266 #ifdef HAVE_FPFLOAT
2267         ent_binop_register(ASE_BINARY_OP_PROD,
2268                            FLOAT_T, BIGZ_T, ent_prod_FLOAT_T_BIGZ_T);
2269         ent_binop_register(ASE_BINARY_OP_PROD,
2270                            BIGZ_T, FLOAT_T, ent_prod_BIGZ_T_FLOAT_T);
2271 #endif
2272
2273         ent_binop_register(ASE_BINARY_OP_DIV,
2274                            BIGZ_T, BIGZ_T, ent_div_BIGZ_T);
2275         ent_binop_register(ASE_BINARY_OP_DIV,
2276                            BIGZ_T, INT_T, ent_div_BIGZ_T_INT_T);
2277         ent_binop_register(ASE_BINARY_OP_DIV,
2278                            INT_T, BIGZ_T, ent_div_INT_T_BIGZ_T);
2279 #ifdef HAVE_FPFLOAT
2280         ent_binop_register(ASE_BINARY_OP_DIV,
2281                            FLOAT_T, BIGZ_T, ent_div_FLOAT_T_BIGZ_T);
2282         ent_binop_register(ASE_BINARY_OP_DIV,
2283                            BIGZ_T, FLOAT_T, ent_div_BIGZ_T_FLOAT_T);
2284 #endif
2285
2286         ent_binop_register(ASE_BINARY_OP_QUO,
2287                            BIGZ_T, BIGZ_T, ent_quo_BIGZ_T);
2288         ent_binop_register(ASE_BINARY_OP_QUO,
2289                            BIGZ_T, INT_T, ent_quo_BIGZ_T_INT_T);
2290         ent_binop_register(ASE_BINARY_OP_QUO,
2291                            INT_T, BIGZ_T, ent_quo_INT_T_BIGZ_T);
2292 #ifdef HAVE_FPFLOAT
2293         ent_binop_register(ASE_BINARY_OP_QUO,
2294                            FLOAT_T, BIGZ_T, ent_div_FLOAT_T_BIGZ_T);
2295         ent_binop_register(ASE_BINARY_OP_QUO,
2296                            BIGZ_T, FLOAT_T, ent_div_BIGZ_T_FLOAT_T);
2297 #endif
2298
2299         /* remainders */
2300         ent_binop_register(ASE_BINARY_OP_REM,
2301                            BIGZ_T, BIGZ_T, ent_rem_BIGZ_T);
2302         ent_binop_register(ASE_BINARY_OP_REM,
2303                            BIGZ_T, INT_T, ent_rem_BIGZ_T_INT_T);
2304         ent_binop_register(ASE_BINARY_OP_REM,
2305                            INT_T, BIGZ_T, ent_rem_INT_T_BIGZ_T);
2306         ent_binop_register(ASE_BINARY_OP_MOD,
2307                            BIGZ_T, BIGZ_T, ent_rem_BIGZ_T);
2308         ent_binop_register(ASE_BINARY_OP_MOD,
2309                            BIGZ_T, INT_T, ent_rem_BIGZ_T_INT_T);
2310         ent_binop_register(ASE_BINARY_OP_MOD,
2311                            INT_T, BIGZ_T, ent_rem_INT_T_BIGZ_T);
2312
2313         /* powers */
2314         ent_binop_register(ASE_BINARY_OP_POW,
2315                            INT_T, INT_T, ent_pow_integer_integer);
2316         ent_binop_register(ASE_BINARY_OP_POW,
2317                            INT_T, BIGZ_T, ent_pow_integer_integer);
2318         ent_binop_register(ASE_BINARY_OP_POW,
2319                            BIGZ_T, INT_T, ent_pow_integer_integer);
2320         ent_binop_register(ASE_BINARY_OP_POW,
2321                            BIGZ_T, BIGZ_T, ent_pow_integer_integer);
2322 }
2323
2324 static inline void
2325 ent_mpz_unary_reltable_init(void)
2326 {
2327         ent_unrel_register(ASE_UNARY_REL_ZEROP, BIGZ_T, ent_mpz_zerop);
2328         ent_unrel_register(ASE_UNARY_REL_ONEP, BIGZ_T, ent_mpz_onep);
2329         ent_unrel_register(ASE_UNARY_REL_UNITP, BIGZ_T, ent_mpz_unitp);
2330 }
2331
2332 static inline void
2333 ent_mpz_binary_reltable_init(void)
2334 {
2335         ent_binrel_register(ASE_BINARY_REL_LESSP,
2336                             BIGZ_T, BIGZ_T, ent_lt_bigz);
2337         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2338                             BIGZ_T, BIGZ_T, ent_gt_bigz);
2339         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2340                             BIGZ_T, BIGZ_T, ent_eq_bigz);
2341         ent_binrel_register(ASE_BINARY_REL_NEQP,
2342                             BIGZ_T, BIGZ_T, ent_ne_bigz);
2343
2344         ent_binrel_register(ASE_BINARY_REL_LESSP,
2345                             BIGZ_T, INT_T, ent_lt_bigz_int);
2346         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2347                             BIGZ_T, INT_T, ent_gt_bigz_int);
2348         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2349                             BIGZ_T, INT_T, ent_eq_bigz_int);
2350         ent_binrel_register(ASE_BINARY_REL_NEQP,
2351                             BIGZ_T, INT_T, ent_ne_bigz_int);
2352
2353         ent_binrel_register(ASE_BINARY_REL_LESSP,
2354                             INT_T, BIGZ_T, ent_lt_int_bigz);
2355         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2356                             INT_T, BIGZ_T, ent_gt_int_bigz);
2357         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2358                             INT_T, BIGZ_T, ent_eq_int_bigz);
2359         ent_binrel_register(ASE_BINARY_REL_NEQP,
2360                             INT_T, BIGZ_T, ent_ne_int_bigz);
2361
2362 #ifdef HAVE_FPFLOAT
2363         ent_binrel_register(ASE_BINARY_REL_LESSP,
2364                             BIGZ_T, FLOAT_T, ent_lt_bigzq_float);
2365         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2366                             BIGZ_T, FLOAT_T, ent_gt_bigzq_float);
2367         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2368                             BIGZ_T, FLOAT_T, ent_eq_bigzq_float);
2369         ent_binrel_register(ASE_BINARY_REL_NEQP,
2370                             BIGZ_T, FLOAT_T, ent_ne_bigzq_float);
2371
2372         ent_binrel_register(ASE_BINARY_REL_LESSP,
2373                             FLOAT_T, BIGZ_T, ent_lt_float_bigzq);
2374         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2375                             FLOAT_T, BIGZ_T, ent_gt_float_bigzq);
2376         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2377                             FLOAT_T, BIGZ_T, ent_eq_float_bigzq);
2378         ent_binrel_register(ASE_BINARY_REL_NEQP,
2379                             FLOAT_T, BIGZ_T, ent_ne_float_bigzq);
2380 #endif
2381 }
2382
2383 static inline void
2384 ent_mpz_lifttable_init(void)
2385 {
2386         ent_lift_register(BIGZ_T, INT_T, _ent_lift_BIGZ_T_INT_T);
2387         ent_lift_register(INT_T, BIGZ_T, _ent_lift_INT_T_BIGZ_T);
2388 #ifdef HAVE_FPFLOAT
2389         ent_lift_register(BIGZ_T, FLOAT_T, _ent_lift_BIGZ_T_FLOAT_T);
2390         ent_lift_register(FLOAT_T, BIGZ_T, _ent_lift_FLOAT_T_BIGZ_T);
2391 #endif
2392         ent_lift_register(INDEF_T, BIGZ_T, ent_lift_INDEF_T_COMPARABLE);
2393 }
2394
2395 void init_optables_BIGZ_T (void)
2396 {
2397         ent_mpz_nullary_optable_init();
2398         ent_mpz_unary_optable_init();
2399         ent_mpz_binary_optable_init();
2400         ent_mpz_unary_reltable_init();
2401         ent_mpz_binary_reltable_init();
2402         ent_mpz_lifttable_init();
2403 }
2404
2405 \f
2406 static inline void
2407 ent_mpq_nullary_optable_init(void)
2408 {
2409         Qent_mpq_zero = make_bigq(0L, 1L);
2410         Qent_mpq_one = make_bigq(1L, 1L);
2411         staticpro(&Qent_mpq_zero);
2412         staticpro(&Qent_mpq_one);
2413
2414         ent_nullop_register(ASE_NULLARY_OP_ZERO, BIGQ_T, Qent_mpq_zero);
2415         ent_nullop_register(ASE_NULLARY_OP_ONE, BIGQ_T, Qent_mpq_one);
2416 }
2417
2418 static inline void
2419 ent_mpq_unary_optable_init(void)
2420 {
2421         ent_unop_register(ASE_UNARY_OP_NEG, BIGQ_T, ent_neg_BIGQ_T);
2422         ent_unop_register(ASE_UNARY_OP_INV, BIGQ_T, ent_inv_BIGQ_T);
2423         ent_unop_register(ASE_UNARY_OP_INV, INT_T, ent_inv_INT_T);
2424 }
2425
2426 static inline void
2427 ent_mpq_binary_optable_init(void)
2428 {
2429         /* sums */
2430         ent_binop_register(ASE_BINARY_OP_SUM,
2431                            BIGQ_T, BIGQ_T, ent_sum_BIGQ_T);
2432         ent_binop_register(ASE_BINARY_OP_SUM,
2433                            BIGQ_T, INT_T, ent_sum_BIGQ_T_INT_T);
2434         ent_binop_register(ASE_BINARY_OP_SUM,
2435                            INT_T, BIGQ_T, ent_sum_INT_T_BIGQ_T);
2436         ent_binop_register(ASE_BINARY_OP_SUM,
2437                            BIGQ_T, BIGZ_T, ent_sum_BIGQ_T_BIGZ_T);
2438         ent_binop_register(ASE_BINARY_OP_SUM,
2439                            BIGZ_T, BIGQ_T, ent_sum_BIGZ_T_BIGQ_T);
2440 #ifdef HAVE_FPFLOAT
2441         ent_binop_register(ASE_BINARY_OP_SUM,
2442                            FLOAT_T, BIGQ_T, ent_sum_FLOAT_T_BIGQ_T);
2443         ent_binop_register(ASE_BINARY_OP_SUM,
2444                            BIGQ_T, FLOAT_T, ent_sum_BIGQ_T_FLOAT_T);
2445 #endif
2446
2447         ent_binop_register(ASE_BINARY_OP_DIFF,
2448                            BIGQ_T, BIGQ_T, ent_diff_BIGQ_T);
2449         ent_binop_register(ASE_BINARY_OP_DIFF,
2450                            BIGQ_T, INT_T, ent_diff_BIGQ_T_INT_T);
2451         ent_binop_register(ASE_BINARY_OP_DIFF,
2452                            INT_T, BIGQ_T, ent_diff_INT_T_BIGQ_T);
2453         ent_binop_register(ASE_BINARY_OP_DIFF,
2454                            BIGQ_T, BIGZ_T, ent_diff_BIGQ_T_BIGZ_T);
2455         ent_binop_register(ASE_BINARY_OP_DIFF,
2456                            BIGZ_T, BIGQ_T, ent_diff_BIGZ_T_BIGQ_T);
2457 #ifdef HAVE_FPFLOAT
2458         ent_binop_register(ASE_BINARY_OP_DIFF,
2459                            FLOAT_T, BIGQ_T, ent_diff_FLOAT_T_BIGQ_T);
2460         ent_binop_register(ASE_BINARY_OP_DIFF,
2461                            BIGQ_T, FLOAT_T, ent_diff_BIGQ_T_FLOAT_T);
2462 #endif
2463
2464         /* products */
2465         ent_binop_register(ASE_BINARY_OP_PROD,
2466                            BIGQ_T, BIGQ_T, ent_prod_BIGQ_T);
2467         ent_binop_register(ASE_BINARY_OP_PROD,
2468                            BIGQ_T, INT_T, ent_prod_BIGQ_T_INT_T);
2469         ent_binop_register(ASE_BINARY_OP_PROD,
2470                            INT_T, BIGQ_T, ent_prod_INT_T_BIGQ_T);
2471         ent_binop_register(ASE_BINARY_OP_PROD,
2472                            BIGQ_T, BIGZ_T, ent_prod_BIGQ_T_BIGZ_T);
2473         ent_binop_register(ASE_BINARY_OP_PROD,
2474                            BIGZ_T, BIGQ_T, ent_prod_BIGZ_T_BIGQ_T);
2475 #ifdef HAVE_FPFLOAT
2476         ent_binop_register(ASE_BINARY_OP_PROD,
2477                            FLOAT_T, BIGQ_T, ent_prod_FLOAT_T_BIGQ_T);
2478         ent_binop_register(ASE_BINARY_OP_PROD,
2479                            BIGQ_T, FLOAT_T, ent_prod_BIGQ_T_FLOAT_T);
2480 #endif
2481
2482         ent_binop_register(ASE_BINARY_OP_DIV,
2483                            BIGQ_T, BIGQ_T, ent_div_BIGQ_T);
2484         ent_binop_register(ASE_BINARY_OP_DIV,
2485                            BIGQ_T, INT_T, ent_div_BIGQ_T_INT_T);
2486         ent_binop_register(ASE_BINARY_OP_DIV,
2487                            INT_T, BIGQ_T, ent_div_INT_T_BIGQ_T);
2488         ent_binop_register(ASE_BINARY_OP_DIV,
2489                            BIGQ_T, BIGZ_T, ent_div_BIGQ_T_BIGZ_T);
2490         ent_binop_register(ASE_BINARY_OP_DIV,
2491                            BIGZ_T, BIGQ_T, ent_div_BIGZ_T_BIGQ_T);
2492 #ifdef HAVE_FPFLOAT
2493         ent_binop_register(ASE_BINARY_OP_DIV,
2494                            FLOAT_T, BIGQ_T, ent_div_FLOAT_T_BIGQ_T);
2495         ent_binop_register(ASE_BINARY_OP_DIV,
2496                            BIGQ_T, FLOAT_T, ent_div_BIGQ_T_FLOAT_T);
2497 #endif
2498
2499         ent_binop_register(ASE_BINARY_OP_QUO,
2500                            INT_T, INT_T, ent_quo_INT_T);
2501         ent_binop_register(ASE_BINARY_OP_QUO,
2502                            BIGQ_T, BIGQ_T, ent_div_BIGQ_T);
2503         ent_binop_register(ASE_BINARY_OP_QUO,
2504                            BIGQ_T, INT_T, ent_div_BIGQ_T_INT_T);
2505         ent_binop_register(ASE_BINARY_OP_QUO,
2506                            INT_T, BIGQ_T, ent_div_INT_T_BIGQ_T);
2507         ent_binop_register(ASE_BINARY_OP_QUO,
2508                            BIGQ_T, BIGZ_T, ent_div_BIGQ_T_BIGZ_T);
2509         ent_binop_register(ASE_BINARY_OP_QUO,
2510                            BIGZ_T, BIGQ_T, ent_div_BIGZ_T_BIGQ_T);
2511 #ifdef HAVE_FPFLOAT
2512         ent_binop_register(ASE_BINARY_OP_QUO,
2513                            FLOAT_T, BIGQ_T, ent_div_FLOAT_T_BIGQ_T);
2514         ent_binop_register(ASE_BINARY_OP_QUO,
2515                            BIGQ_T, FLOAT_T, ent_div_BIGQ_T_FLOAT_T);
2516 #endif
2517
2518         /* remainders */
2519         ent_binop_register(ASE_BINARY_OP_REM,
2520                            BIGQ_T, BIGQ_T, ent_rem_BIGQ_T);
2521         ent_binop_register(ASE_BINARY_OP_MOD,
2522                            BIGQ_T, BIGQ_T, ent_mod_BIGQ_T);
2523         ent_binop_register(ASE_BINARY_OP_POW,
2524                            BIGQ_T, INT_T, ent_pow_BIGQ_T_integer);
2525         ent_binop_register(ASE_BINARY_OP_POW,
2526                            BIGQ_T, BIGZ_T, ent_pow_BIGQ_T_integer);
2527 }
2528
2529 static inline void
2530 ent_mpq_unary_reltable_init(void)
2531 {
2532         ent_unrel_register(ASE_UNARY_REL_ZEROP, BIGQ_T, ent_mpq_zerop);
2533         ent_unrel_register(ASE_UNARY_REL_ONEP, BIGQ_T, ent_mpq_onep);
2534         ent_unrel_register(ASE_UNARY_REL_UNITP, BIGQ_T, ent_mpq_unitp);
2535 }
2536
2537 static inline void
2538 ent_mpq_binary_reltable_init(void)
2539 {
2540         ent_binrel_register(ASE_BINARY_REL_LESSP,
2541                             BIGQ_T, BIGQ_T, ent_lt_bigq);
2542         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2543                             BIGQ_T, BIGQ_T, ent_gt_bigq);
2544         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2545                             BIGQ_T, BIGQ_T, ent_eq_bigq);
2546         ent_binrel_register(ASE_BINARY_REL_NEQP,
2547                             BIGQ_T, BIGQ_T, ent_ne_bigq);
2548
2549         ent_binrel_register(ASE_BINARY_REL_LESSP,
2550                             BIGQ_T, INT_T, ent_lt_bigq_int);
2551         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2552                             BIGQ_T, INT_T, ent_gt_bigq_int);
2553         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2554                             BIGQ_T, INT_T, ent_eq_bigq_int);
2555         ent_binrel_register(ASE_BINARY_REL_NEQP,
2556                             BIGQ_T, INT_T, ent_ne_bigq_int);
2557
2558         ent_binrel_register(ASE_BINARY_REL_LESSP,
2559                             INT_T, BIGQ_T, ent_lt_int_bigq);
2560         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2561                             INT_T, BIGQ_T, ent_gt_int_bigq);
2562         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2563                             INT_T, BIGQ_T, ent_eq_int_bigq);
2564         ent_binrel_register(ASE_BINARY_REL_NEQP,
2565                             INT_T, BIGQ_T, ent_ne_int_bigq);
2566
2567         ent_binrel_register(ASE_BINARY_REL_LESSP,
2568                             BIGQ_T, BIGZ_T, ent_lt_bigq_bigz);
2569         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2570                             BIGQ_T, BIGZ_T, ent_gt_bigq_bigz);
2571         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2572                             BIGQ_T, BIGZ_T, ent_eq_bigq_bigz);
2573         ent_binrel_register(ASE_BINARY_REL_NEQP,
2574                             BIGQ_T, BIGZ_T, ent_ne_bigq_bigz);
2575
2576         ent_binrel_register(ASE_BINARY_REL_LESSP,
2577                             BIGZ_T, BIGQ_T, ent_lt_bigz_bigq);
2578         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2579                             BIGZ_T, BIGQ_T, ent_gt_bigz_bigq);
2580         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2581                             BIGZ_T, BIGQ_T, ent_eq_bigz_bigq);
2582         ent_binrel_register(ASE_BINARY_REL_NEQP,
2583                             BIGZ_T, BIGQ_T, ent_ne_bigz_bigq);
2584
2585 #ifdef HAVE_FPFLOAT
2586         ent_binrel_register(ASE_BINARY_REL_LESSP,
2587                             BIGQ_T, FLOAT_T, ent_lt_bigzq_float);
2588         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2589                             BIGQ_T, FLOAT_T, ent_gt_bigzq_float);
2590         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2591                             BIGQ_T, FLOAT_T, ent_eq_bigzq_float);
2592         ent_binrel_register(ASE_BINARY_REL_NEQP,
2593                             BIGQ_T, FLOAT_T, ent_ne_bigzq_float);
2594
2595         ent_binrel_register(ASE_BINARY_REL_LESSP,
2596                             FLOAT_T, BIGQ_T, ent_lt_float_bigzq);
2597         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2598                             FLOAT_T, BIGQ_T, ent_gt_float_bigzq);
2599         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2600                             FLOAT_T, BIGQ_T, ent_eq_float_bigzq);
2601         ent_binrel_register(ASE_BINARY_REL_NEQP,
2602                             FLOAT_T, BIGQ_T, ent_ne_float_bigzq);
2603 #endif
2604 }
2605
2606 static inline void
2607 ent_mpq_lifttable_init(void)
2608 {
2609         ent_lift_register(BIGQ_T, INT_T, _ent_lift_BIGQ_T_INT_T);
2610         ent_lift_register(INT_T, BIGQ_T, _ent_lift_INT_T_BIGQ_T);
2611         ent_lift_register(BIGQ_T, BIGZ_T, _ent_lift_BIGQ_T_BIGZ_T);
2612         ent_lift_register(BIGZ_T, BIGQ_T, _ent_lift_BIGZ_T_BIGQ_T);
2613 #ifdef HAVE_FPFLOAT
2614         ent_lift_register(BIGQ_T, FLOAT_T, _ent_lift_BIGQ_T_FLOAT_T);
2615         ent_lift_register(FLOAT_T, BIGQ_T, _ent_lift_FLOAT_T_BIGQ_T);
2616 #endif
2617         ent_lift_register(INDEF_T, BIGQ_T, ent_lift_INDEF_T_COMPARABLE);
2618 }
2619
2620 void init_optables_BIGQ_T (void)
2621 {
2622         ent_mpq_nullary_optable_init();
2623         ent_mpq_unary_optable_init();
2624         ent_mpq_binary_optable_init();
2625         ent_mpq_unary_reltable_init();
2626         ent_mpq_binary_reltable_init();
2627         ent_mpq_lifttable_init();
2628 }
2629
2630 \f
2631 static inline void
2632 ent_mpf_nullary_optable_init(void)
2633 {
2634         Qent_mpf_zero = make_bigf(0.0f, internal_get_precision(Qnil));
2635         Qent_mpf_one = make_bigf(1.0f, internal_get_precision(Qnil));
2636         staticpro(&Qent_mpf_zero);
2637         staticpro(&Qent_mpf_one);
2638
2639         ent_nullop_register(ASE_NULLARY_OP_ZERO, BIGF_T, Qent_mpf_zero);
2640         ent_nullop_register(ASE_NULLARY_OP_ONE, BIGF_T, Qent_mpf_one);
2641 }
2642
2643 static inline void
2644 ent_mpf_unary_optable_init(void)
2645 {
2646         ent_unop_register(ASE_UNARY_OP_NEG, BIGF_T, ent_neg_BIGF_T);
2647         ent_unop_register(ASE_UNARY_OP_INV, BIGF_T, ent_inv_BIGF_T);
2648 }
2649
2650 static inline void
2651 ent_mpf_binary_optable_init(void)
2652 {
2653         /* sums */
2654         ent_binop_register(ASE_BINARY_OP_SUM,
2655                            BIGF_T, BIGF_T, ent_sum_BIGF_T);
2656         ent_binop_register(ASE_BINARY_OP_SUM,
2657                            BIGF_T, INT_T, ent_sum_BIGF_T_INT_T);
2658         ent_binop_register(ASE_BINARY_OP_SUM,
2659                            INT_T, BIGF_T, ent_sum_INT_T_BIGF_T);
2660         ent_binop_register(ASE_BINARY_OP_SUM,
2661                            BIGF_T, BIGZ_T, ent_sum_BIGF_T_BIGZ_T);
2662         ent_binop_register(ASE_BINARY_OP_SUM,
2663                            BIGZ_T, BIGF_T, ent_sum_BIGZ_T_BIGF_T);
2664         ent_binop_register(ASE_BINARY_OP_SUM,
2665                            BIGF_T, BIGQ_T, ent_sum_BIGF_T_BIGQ_T);
2666         ent_binop_register(ASE_BINARY_OP_SUM,
2667                            BIGQ_T, BIGF_T, ent_sum_BIGQ_T_BIGF_T);
2668 #ifdef HAVE_FPFLOAT
2669         ent_binop_register(ASE_BINARY_OP_SUM,
2670                            BIGF_T, FLOAT_T, ent_sum_BIGF_T_FLOAT_T);
2671         ent_binop_register(ASE_BINARY_OP_SUM,
2672                            FLOAT_T, BIGF_T, ent_sum_FLOAT_T_BIGF_T);
2673 #endif
2674         /* diffs */
2675         ent_binop_register(ASE_BINARY_OP_DIFF,
2676                            BIGF_T, BIGF_T, ent_diff_BIGF_T);
2677         ent_binop_register(ASE_BINARY_OP_DIFF,
2678                            BIGF_T, INT_T, ent_diff_BIGF_T_INT_T);
2679         ent_binop_register(ASE_BINARY_OP_DIFF,
2680                            INT_T, BIGF_T, ent_diff_INT_T_BIGF_T);
2681         ent_binop_register(ASE_BINARY_OP_DIFF,
2682                            BIGF_T, BIGZ_T, ent_diff_BIGF_T_BIGZ_T);
2683         ent_binop_register(ASE_BINARY_OP_DIFF,
2684                            BIGZ_T, BIGF_T, ent_diff_BIGZ_T_BIGF_T);
2685         ent_binop_register(ASE_BINARY_OP_DIFF,
2686                            BIGF_T, BIGQ_T, ent_diff_BIGF_T_BIGQ_T);
2687         ent_binop_register(ASE_BINARY_OP_DIFF,
2688                            BIGQ_T, BIGF_T, ent_diff_BIGQ_T_BIGF_T);
2689 #ifdef HAVE_FPFLOAT
2690         ent_binop_register(ASE_BINARY_OP_DIFF,
2691                            BIGF_T, FLOAT_T, ent_diff_BIGF_T_FLOAT_T);
2692         ent_binop_register(ASE_BINARY_OP_DIFF,
2693                            FLOAT_T, BIGF_T, ent_diff_FLOAT_T_BIGF_T);
2694 #endif
2695         /* prods */
2696         ent_binop_register(ASE_BINARY_OP_PROD,
2697                            BIGF_T, BIGF_T, ent_prod_BIGF_T);
2698         ent_binop_register(ASE_BINARY_OP_PROD,
2699                            BIGF_T, INT_T, ent_prod_BIGF_T_INT_T);
2700         ent_binop_register(ASE_BINARY_OP_PROD,
2701                            INT_T, BIGF_T, ent_prod_INT_T_BIGF_T);
2702         ent_binop_register(ASE_BINARY_OP_PROD,
2703                            BIGF_T, BIGZ_T, ent_prod_BIGF_T_BIGZ_T);
2704         ent_binop_register(ASE_BINARY_OP_PROD,
2705                            BIGZ_T, BIGF_T, ent_prod_BIGZ_T_BIGF_T);
2706         ent_binop_register(ASE_BINARY_OP_PROD,
2707                            BIGF_T, BIGQ_T, ent_prod_BIGF_T_BIGQ_T);
2708         ent_binop_register(ASE_BINARY_OP_PROD,
2709                            BIGQ_T, BIGF_T, ent_prod_BIGQ_T_BIGF_T);
2710 #ifdef HAVE_FPFLOAT
2711         ent_binop_register(ASE_BINARY_OP_PROD,
2712                            BIGF_T, FLOAT_T, ent_prod_BIGF_T_FLOAT_T);
2713         ent_binop_register(ASE_BINARY_OP_PROD,
2714                            FLOAT_T, BIGF_T, ent_prod_FLOAT_T_BIGF_T);
2715 #endif
2716
2717         /* divisions and quotients */
2718         ent_binop_register(ASE_BINARY_OP_DIV,
2719                            BIGF_T, BIGF_T, ent_div_BIGF_T);
2720         ent_binop_register(ASE_BINARY_OP_DIV,
2721                            BIGF_T, INT_T, ent_div_BIGF_T_INT_T);
2722         ent_binop_register(ASE_BINARY_OP_DIV,
2723                            INT_T, BIGF_T, ent_div_INT_T_BIGF_T);
2724         ent_binop_register(ASE_BINARY_OP_DIV,
2725                            BIGF_T, BIGZ_T, ent_div_BIGF_T_BIGZ_T);
2726         ent_binop_register(ASE_BINARY_OP_DIV,
2727                            BIGZ_T, BIGF_T, ent_div_BIGZ_T_BIGF_T);
2728         ent_binop_register(ASE_BINARY_OP_DIV,
2729                            BIGF_T, BIGQ_T, ent_div_BIGF_T_BIGQ_T);
2730         ent_binop_register(ASE_BINARY_OP_DIV,
2731                            BIGQ_T, BIGF_T, ent_div_BIGQ_T_BIGF_T);
2732 #ifdef HAVE_FPFLOAT
2733         ent_binop_register(ASE_BINARY_OP_DIV,
2734                            BIGF_T, FLOAT_T, ent_div_BIGF_T_FLOAT_T);
2735         ent_binop_register(ASE_BINARY_OP_DIV,
2736                            FLOAT_T, BIGF_T, ent_div_FLOAT_T_BIGF_T);
2737 #endif
2738         ent_binop_register(ASE_BINARY_OP_QUO,
2739                            BIGF_T, BIGF_T, ent_div_BIGF_T);
2740         ent_binop_register(ASE_BINARY_OP_QUO,
2741                            BIGF_T, INT_T, ent_div_BIGF_T_INT_T);
2742         ent_binop_register(ASE_BINARY_OP_QUO,
2743                            INT_T, BIGF_T, ent_div_INT_T_BIGF_T);
2744         ent_binop_register(ASE_BINARY_OP_QUO,
2745                            BIGF_T, BIGZ_T, ent_div_BIGF_T_BIGZ_T);
2746         ent_binop_register(ASE_BINARY_OP_QUO,
2747                            BIGZ_T, BIGF_T, ent_div_BIGZ_T_BIGF_T);
2748         ent_binop_register(ASE_BINARY_OP_QUO,
2749                            BIGF_T, BIGQ_T, ent_div_BIGF_T_BIGQ_T);
2750         ent_binop_register(ASE_BINARY_OP_QUO,
2751                            BIGQ_T, BIGF_T, ent_div_BIGQ_T_BIGF_T);
2752 #ifdef HAVE_FPFLOAT
2753         ent_binop_register(ASE_BINARY_OP_QUO,
2754                            BIGF_T, FLOAT_T, ent_div_BIGF_T_FLOAT_T);
2755         ent_binop_register(ASE_BINARY_OP_QUO,
2756                            FLOAT_T, BIGF_T, ent_div_FLOAT_T_BIGF_T);
2757 #endif
2758         /* remainders */
2759         ent_binop_register(ASE_BINARY_OP_REM,
2760                            BIGF_T, BIGF_T, ent_rem_BIGF_T);
2761         ent_binop_register(ASE_BINARY_OP_MOD,
2762                            BIGF_T, BIGF_T, ent_mod_BIGF_T);
2763 #ifdef bigf_pow
2764         ent_binop_register(ASE_BINARY_OP_POW,
2765                            BIGF_T, INT_T, ent_pow_BIGF_T_integer);
2766         ent_binop_register(ASE_BINARY_OP_POW,
2767                            BIGF_T, BIGZ_T, ent_pow_BIGF_T_integer);
2768 #endif
2769 }
2770
2771 static inline void
2772 ent_mpf_unary_reltable_init(void)
2773 {
2774         ent_unrel_register(ASE_UNARY_REL_ZEROP, BIGF_T, ent_mpf_zerop);
2775         ent_unrel_register(ASE_UNARY_REL_ONEP, BIGF_T, ent_mpf_onep);
2776         ent_unrel_register(ASE_UNARY_REL_UNITP, BIGF_T, ent_mpf_unitp);
2777 }
2778
2779 static inline void
2780 ent_mpf_binary_reltable_init(void)
2781 {
2782         ent_binrel_register(ASE_BINARY_REL_LESSP,
2783                             BIGF_T, BIGF_T, ent_lt_bigf);
2784         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2785                             BIGF_T, BIGF_T, ent_gt_bigf);
2786         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2787                             BIGF_T, BIGF_T, ent_eq_bigf);
2788         ent_binrel_register(ASE_BINARY_REL_NEQP,
2789                             BIGF_T, BIGF_T, ent_ne_bigf);
2790
2791         ent_binrel_register(ASE_BINARY_REL_LESSP,
2792                             BIGF_T, INT_T, ent_lt_bigf_int);
2793         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2794                             BIGF_T, INT_T, ent_gt_bigf_int);
2795         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2796                             BIGF_T, INT_T, ent_eq_bigf_int);
2797         ent_binrel_register(ASE_BINARY_REL_NEQP,
2798                             BIGF_T, INT_T, ent_ne_bigf_int);
2799
2800         ent_binrel_register(ASE_BINARY_REL_LESSP,
2801                             INT_T, BIGF_T, ent_lt_int_bigf);
2802         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2803                             INT_T, BIGF_T, ent_gt_int_bigf);
2804         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2805                             INT_T, BIGF_T, ent_eq_int_bigf);
2806         ent_binrel_register(ASE_BINARY_REL_NEQP,
2807                             INT_T, BIGF_T, ent_ne_int_bigf);
2808
2809         ent_binrel_register(ASE_BINARY_REL_LESSP,
2810                             BIGF_T, BIGZ_T, ent_lt_bigf_bigz);
2811         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2812                             BIGF_T, BIGZ_T, ent_gt_bigf_bigz);
2813         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2814                             BIGF_T, BIGZ_T, ent_eq_bigf_bigz);
2815         ent_binrel_register(ASE_BINARY_REL_NEQP,
2816                             BIGF_T, BIGZ_T, ent_ne_bigf_bigz);
2817
2818         ent_binrel_register(ASE_BINARY_REL_LESSP,
2819                             BIGZ_T, BIGF_T, ent_lt_bigz_bigf);
2820         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2821                             BIGZ_T, BIGF_T, ent_gt_bigz_bigf);
2822         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2823                             BIGZ_T, BIGF_T, ent_eq_bigz_bigf);
2824         ent_binrel_register(ASE_BINARY_REL_NEQP,
2825                             BIGZ_T, BIGF_T, ent_ne_bigz_bigf);
2826
2827         ent_binrel_register(ASE_BINARY_REL_LESSP,
2828                             BIGF_T, BIGQ_T, ent_lt_bigf_bigq);
2829         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2830                             BIGF_T, BIGQ_T, ent_gt_bigf_bigq);
2831         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2832                             BIGF_T, BIGQ_T, ent_eq_bigf_bigq);
2833         ent_binrel_register(ASE_BINARY_REL_NEQP,
2834                             BIGF_T, BIGQ_T, ent_ne_bigf_bigq);
2835
2836         ent_binrel_register(ASE_BINARY_REL_LESSP,
2837                             BIGQ_T, BIGF_T, ent_lt_bigq_bigf);
2838         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2839                             BIGQ_T, BIGF_T, ent_gt_bigq_bigf);
2840         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2841                             BIGQ_T, BIGF_T, ent_eq_bigq_bigf);
2842         ent_binrel_register(ASE_BINARY_REL_NEQP,
2843                             BIGQ_T, BIGF_T, ent_ne_bigq_bigf);
2844
2845 #ifdef HAVE_FPFLOAT
2846         ent_binrel_register(ASE_BINARY_REL_LESSP,
2847                             BIGF_T, FLOAT_T, ent_lt_bigf_fpfloat);
2848         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2849                             BIGF_T, FLOAT_T, ent_gt_bigf_fpfloat);
2850         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2851                             BIGF_T, FLOAT_T, ent_eq_bigf_fpfloat);
2852         ent_binrel_register(ASE_BINARY_REL_NEQP,
2853                             BIGF_T, FLOAT_T, ent_ne_bigf_fpfloat);
2854
2855         ent_binrel_register(ASE_BINARY_REL_LESSP,
2856                             FLOAT_T, BIGF_T, ent_lt_fpfloat_bigf);
2857         ent_binrel_register(ASE_BINARY_REL_GREATERP,
2858                             FLOAT_T, BIGF_T, ent_gt_fpfloat_bigf);
2859         ent_binrel_register(ASE_BINARY_REL_EQUALP,
2860                             FLOAT_T, BIGF_T, ent_eq_fpfloat_bigf);
2861         ent_binrel_register(ASE_BINARY_REL_NEQP,
2862                             FLOAT_T, BIGF_T, ent_ne_fpfloat_bigf);
2863 #endif
2864 }
2865
2866 static inline void
2867 ent_mpf_lifttable_init(void)
2868 {
2869         ent_lift_register(INT_T, BIGF_T, ent_lift_INT_T_BIGF_T);
2870         ent_lift_register(BIGF_T, INT_T, ent_lift_BIGF_T_INT_T);
2871         ent_lift_register(BIGZ_T, BIGF_T, ent_lift_BIGZ_T_BIGF_T);
2872         ent_lift_register(BIGF_T, BIGZ_T, ent_lift_BIGF_T_BIGZ_T);
2873         ent_lift_register(BIGQ_T, BIGF_T, ent_lift_BIGQ_T_BIGF_T);
2874         ent_lift_register(BIGF_T, BIGQ_T, ent_lift_BIGF_T_BIGQ_T);
2875 #ifdef HAVE_FPFLOAT
2876         ent_lift_register(FLOAT_T, BIGF_T, ent_lift_FLOAT_T_BIGF_T);
2877         ent_lift_register(BIGF_T, FLOAT_T, ent_lift_BIGF_T_FLOAT_T);
2878 #endif
2879         ent_lift_register(BIGF_T, BIGF_T, ent_lift_BIGF_T_BIGF_T);
2880         ent_lift_register(INDEF_T, BIGF_T, ent_lift_INDEF_T_COMPARABLE);
2881 }
2882
2883 void init_optables_BIGF_T (void)
2884 {
2885         ent_mpf_nullary_optable_init();
2886         ent_mpf_unary_optable_init();
2887         ent_mpf_binary_optable_init();
2888         ent_mpf_unary_reltable_init();
2889         ent_mpf_binary_reltable_init();
2890         ent_mpf_lifttable_init();
2891 }
2892
2893 void init_ent_mpz()
2894 {
2895         /* Prepare the bignum/bigfloat random number generator */
2896         gmp_randinit_default(random_state);
2897         gmp_randseed_ui(random_state, getpid() + time (NULL));
2898
2899         bigz_init(ent_scratch_bigz);
2900 }
2901
2902 void init_ent_mpq(void)
2903 {
2904         bigq_init(ent_scratch_bigq);
2905 }
2906
2907 void init_ent_mpf()
2908 {
2909         /* The smallest number that is printed without exponents */
2910         mpf_init_set_d(float_print_min, 0.001);
2911
2912         /* The largest number that is printed without exponents */
2913         mpf_init_set_ui(float_print_max, 10000000UL);
2914
2915         bigf_init(ent_scratch_bigf);
2916 }
2917
2918 void syms_of_ent_mpz(void)
2919 {
2920         INIT_LRECORD_IMPLEMENTATION(bigz);
2921 }
2922
2923 void syms_of_ent_mpq(void)
2924 {
2925         INIT_LRECORD_IMPLEMENTATION(bigq);
2926 }
2927
2928 void syms_of_ent_mpf(void)
2929 {
2930         INIT_LRECORD_IMPLEMENTATION(bigf);
2931
2932         DEFSUBR(Fbigf_get_precision);
2933         DEFSUBR(Fbigf_set_precision);
2934 }
2935
2936 void vars_of_ent_mpz(void)
2937 {
2938         Fprovide(intern("bignum")); /* for XE compatibility */
2939         Fprovide(intern("bigz"));
2940 }
2941
2942 void vars_of_ent_mpq(void)
2943 {
2944         Fprovide(intern("ratio")); /* for XE compatibility */
2945         Fprovide(intern("bigq"));
2946 }
2947
2948 void vars_of_ent_mpf(void)
2949 {
2950         bigf_set_default_prec(128UL);
2951
2952         Fprovide(intern("bigfloat")); /* for XE compatibility */
2953         Fprovide(intern("bigf"));
2954 }