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