1 /*** ase-resclass.c -- Residue Class Rings for SXEmacs
3 * Copyright (C) 2006 - 2008 Sebastian Freundt
5 * Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 /* Synched up with: Not in FSF. */
43 #include "ase-resclass.h"
45 #define EMOD_ASE_DEBUG_RESC(args...) EMOD_ASE_DEBUG("[RESC]: " args)
47 PROVIDE(ase_resclass);
48 REQUIRE(ase_resclass, "ase");
50 Lisp_Object Qase_resclass;
51 Lisp_Object Qase_resc_rng, Qase_resc_rng_p, Qase_resc_elm, Qase_resc_elm_p;
52 static int sane_small;
55 static ase_nullary_operation_f Qase_resclass_zero, Qase_resclass_one;
60 _resc_rng_buffer_size(ase_resc_rng_t a)
62 /* returns a sane size for buffer allocation */
63 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
64 if (ase_resc_rng_smallp(a))
67 return (mpz_sizeinbase(ase_resc_rng_ring(a), 10) + 7) & -3;
74 _ase_resc_rng_to_string(char *buf, int len, ase_resc_rng_t a)
76 if (ase_resc_rng_smallp(a)) {
77 int sz = snprintf(buf, len, "%ld", a->small_ring);
78 assert(sz >= 0 && sz < len);
80 resc_rng_to_string(buf, len, ase_resc_rng_ring(a));
85 _ase_resc_rng_prnt(ase_resc_rng_t a, Lisp_Object pcf)
87 int sane_sz = sizeof(char)*_resc_rng_buffer_size(a);
88 char *fstr = alloca(sane_sz);
89 _ase_resc_rng_to_string(fstr, sane_sz, a);
90 write_c_string("Z/", pcf);
91 write_c_string(fstr, pcf);
92 write_c_string("Z", pcf);
97 ase_resc_rng_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
99 EMOD_ASE_DEBUG_RESC("i:0x%016lx@0x%016lx (rc:%d)\n",
100 (long unsigned int)(XASE_RESC_RNG(obj)),
101 (long unsigned int)obj, 1);
102 write_c_string("#<", pcf);
103 print_internal(XDYNACAT_TYPE(obj), pcf, unused);
104 write_c_string(" ", pcf);
105 _ase_resc_rng_prnt(XASE_RESC_RNG(obj), pcf);
106 if (XASE_RESC_RNG_SMALLP(obj))
107 write_c_string(", small", pcf);
108 write_c_string(">", pcf);
112 _resc_elm_buffer_size(ase_resc_elm_t a)
114 /* returns a sane size for buffer allocation */
115 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
116 if (ase_resc_rng_smallp(a))
119 return (mpz_sizeinbase(ase_resc_elm_data(a), 10) + 7) & -3;
126 _ase_resc_elm_to_string(char *buf, int len, ase_resc_elm_t a)
128 if (ase_resc_elm_smallp(a)) {
129 int sz = snprintf(buf, len, "%ld", a->small_data);
130 assert(sz>=0 && sz < len);
132 resc_elm_to_string(buf, len, ase_resc_elm_data(a));
137 _ase_resc_elm_prnt(ase_resc_elm_t a, Lisp_Object pcf)
139 int sane_sz_rng = sizeof(char)*_resc_rng_buffer_size(
140 XASE_RESC_RNG(ase_resc_elm_ring(a)));
141 int sane_sz_elm = sizeof(char)*_resc_elm_buffer_size(a);
142 char *rng_str = alloca(sane_sz_rng);
143 char *elm_str = alloca(sane_sz_elm);
145 _ase_resc_rng_to_string(rng_str, sane_sz_rng,
146 XASE_RESC_RNG(ase_resc_elm_ring(a)));
147 _ase_resc_elm_to_string(elm_str, sane_sz_elm, a);
149 write_c_string(elm_str, pcf);
150 write_c_string("+", pcf);
151 write_c_string(rng_str, pcf);
152 write_c_string("Z", pcf);
157 ase_resc_elm_prnt(Lisp_Object obj, Lisp_Object pcf, int unused)
159 EMOD_ASE_DEBUG_RESC("i:0x%016lx@0x%016lx (rc:%d)\n",
160 (long unsigned int)(XASE_RESC_ELM(obj)),
161 (long unsigned int)obj, 1);
162 write_c_string("#<", pcf);
163 print_internal(XDYNACAT_TYPE(obj), pcf, unused);
164 write_c_string(" ", pcf);
165 _ase_resc_elm_prnt(XASE_RESC_ELM(obj), pcf);
166 if (XASE_RESC_ELM_SMALLP(obj))
167 write_c_string(", small", pcf);
168 write_c_string(">", pcf);
171 /* stuff for the dynacat, markers */
173 _ase_resc_rng_mark(ase_resc_rng_t a)
181 ase_resc_rng_mark(Lisp_Object obj)
183 EMOD_ASE_DEBUG_RESC("i:0x%016lx@0x%016lx (rc:%d) shall be marked...\n",
184 (long unsigned int)(XASE_RESC_RNG(obj)),
185 (long unsigned int)obj, 1);
186 _ase_resc_rng_mark(XASE_RESC_RNG(obj));
191 _ase_resc_elm_mark(ase_resc_elm_t a)
193 mark_object(ase_resc_elm_ring(a));
197 ase_resc_elm_mark(Lisp_Object obj)
199 EMOD_ASE_DEBUG_RESC("i:0x%016lx@0x%016lx (rc:%d) shall be marked...\n",
200 (long unsigned int)(XASE_RESC_ELM(obj)),
201 (long unsigned int)obj, 1);
202 _ase_resc_elm_mark(XASE_RESC_ELM(obj));
206 /* stuff for the dynacat, finalisers */
208 _ase_resc_rng_fini(ase_resc_rng_t a)
210 if (!ase_resc_rng_smallp(a))
211 resc_rng_fini(ase_resc_rng_ring(a));
216 ase_resc_rng_fini(Lisp_Object obj, int unused)
218 ase_resc_rng_t a = XASE_RESC_RNG(obj);
220 EMOD_ASE_DEBUG_GC("i:0x%016lx@0x%016lx (rc:%d) shall be freed...\n",
221 (long unsigned int)(a), obj, 1);
223 _ase_resc_rng_fini(a);
229 _ase_resc_elm_fini(ase_resc_elm_t a)
231 if (!ase_resc_elm_smallp(a))
232 resc_elm_fini(ase_resc_elm_data(a));
237 ase_resc_elm_fini(Lisp_Object obj, int unused)
239 ase_resc_elm_t a = XASE_RESC_ELM(obj);
241 EMOD_ASE_DEBUG_GC("i:0x%016lx@0x%016lx (rc:%d) shall be freed...\n",
242 (long unsigned int)(a), obj, 1);
244 _ase_resc_elm_fini(a);
250 static inline Lisp_Object
251 _ase_wrap_resc_rng(ase_resc_rng_t a)
255 result = make_dynacat(a);
256 XDYNACAT(result)->type = Qase_resc_rng;
260 ase_interval_incref(a);
263 set_dynacat_printer(result, ase_resc_rng_prnt);
264 set_dynacat_marker(result, ase_resc_rng_mark);
265 set_dynacat_finaliser(result, ase_resc_rng_fini);
266 set_dynacat_intprinter(
267 result, (dynacat_intprinter_f)_ase_resc_rng_prnt);
269 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:%d) "
270 "shall be wrapped to 0x%016lx...\n",
271 (long unsigned int)a, 1,
272 (long unsigned int)result);
278 _ase_make_resc_rng(Lisp_Object modulus)
280 ase_resc_rng_t a = xnew(struct ase_resc_rng_s);
284 a->small_ring = XINT(modulus);
285 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
286 } else if (BIGZP(modulus)) {
288 resc_rng_init(ase_resc_rng_ring(a));
289 resc_rng_set_bigz(ase_resc_rng_ring(a), XBIGZ_DATA(modulus));
293 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:0) shall be created...\n",
294 (long unsigned int)a);
298 /* specialised versions for the lisp reader */
299 static inline ase_resc_rng_t
300 __ase_make_resc_rng_eint(EMACS_INT modulus)
302 ase_resc_rng_t a = xnew(struct ase_resc_rng_s);
305 a->small_ring = modulus;
306 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:0) shall be created...\n",
307 (long unsigned int)a);
310 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
311 static inline ase_resc_rng_t
312 __ase_make_resc_rng_bigz(resc_rng modulus)
314 ase_resc_rng_t a = xnew(struct ase_resc_rng_s);
318 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:0) shall be created...\n",
319 (long unsigned int)a);
325 ase_make_resc_rng(Lisp_Object modulus)
327 ase_resc_rng_t a = NULL;
328 Lisp_Object result = Qnil;
330 a = _ase_make_resc_rng(modulus);
331 XSETASE_RESC_RNG(result, a);
337 _ase_wrap_resc_elm(ase_resc_elm_t a)
341 result = make_dynacat(a);
342 XDYNACAT(result)->type = Qase_resc_elm;
346 ase_interval_incref(a);
349 set_dynacat_printer(result, ase_resc_elm_prnt);
350 set_dynacat_marker(result, ase_resc_elm_mark);
351 set_dynacat_finaliser(result, ase_resc_elm_fini);
352 set_dynacat_intprinter(
353 result, (dynacat_intprinter_f)_ase_resc_elm_prnt);
355 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:%d) "
356 "shall be wrapped to 0x%016lx...\n",
357 (long unsigned int)a, 1,
358 (long unsigned int)result);
364 _ase_resc_elm_canonicalise_small(ase_resc_elm_t a)
366 if ((a->small_data = a->small_data %
367 XASE_RESC_RNG(ase_resc_elm_ring(a))->small_ring) < 0)
369 XASE_RESC_RNG(ase_resc_elm_ring(a))->small_ring;
372 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
374 _ase_resc_elm_canonicalise_big(ase_resc_elm_t a)
376 bigz_mod(ase_resc_elm_data(a), ase_resc_elm_data(a),
377 XASE_RESC_RNG_RING(ase_resc_elm_ring(a)));
382 _ase_resc_elm_canonicalise(ase_resc_elm_t a)
384 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
385 if (LIKELY(ase_resc_elm_smallp(a))) {
386 _ase_resc_elm_canonicalise_small(a);
388 _ase_resc_elm_canonicalise_big(a);
391 ase_resc_elm_sdata(a) =
392 ase_resc_elm_sdata(a) %
393 XASE_RESC_RNG_SRING(ase_resc_elm_ring(a));
399 _ase_make_resc_elm(Lisp_Object class, Lisp_Object ring)
401 ase_resc_elm_t a = xnew(struct ase_resc_elm_s);
403 ase_resc_elm_ring(a) = ring;
405 if (!(a->smallp = XASE_RESC_RNG(ring)->smallp)) {
406 resc_elm_init(ase_resc_elm_data(a));
409 EMOD_ASE_DEBUG_RESC("i:0x%016lx (rc:0) shall be created...\n",
410 (long unsigned int)a);
412 if (INTP(class) && a->smallp) {
413 a->small_data = XINT(class);
414 } else if (INTP(class)) {
415 resc_elm_set_eint(ase_resc_elm_data(a), XINT(class));
416 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
417 } else if (BIGZP(class) && a->smallp) {
418 Lisp_Object newcl = _ent_binop(
421 INT_T, make_int(XASE_RESC_RNG(ring)->small_ring));
422 a->small_data = XINT(newcl);
424 } else if (BIGZP(class)) {
425 resc_elm_set_bigz(ase_resc_elm_data(a),
430 _ase_resc_elm_canonicalise(a);
434 /* specialised versions for the lisp reader */
435 static ase_resc_elm_t
436 __ase_make_resc_elm_eint(EMACS_INT class)
438 ase_resc_elm_t a = xnew(struct ase_resc_elm_s);
441 a->small_data = class;
442 EMOD_ASE_DEBUG_RESC("i:%p (rc:0) shall be created...\n", a);
445 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
446 static ase_resc_elm_t
447 __ase_make_resc_elm_bigz(resc_elm class)
449 ase_resc_elm_t a = xnew(struct ase_resc_elm_s);
453 EMOD_ASE_DEBUG_RESC("i:%p (rc:0) shall be created...\n", a);
459 ase_make_resc_elm(Lisp_Object class, Lisp_Object ring)
461 ase_resc_elm_t a = NULL;
462 Lisp_Object result = Qnil;
464 a = _ase_make_resc_elm(class, ring);
465 XSETASE_RESC_ELM(result, a);
471 /* basic functions */
472 /* read a resclass off the wire */
473 /* the next 4 funs are hooked in the lisp reader (lread.c) */
475 ase_resc_rng_from_string(char *cp)
477 ase_resc_rng_t r = NULL;
480 EMACS_INT small_ring;
489 while ((*cp >= '0' && *cp <= '9'))
492 /* MPZ cannot read numbers with characters after them.
493 * See limitations of GMP-MPZ strings
498 small_ring = strtol(start, &tail, 10);
500 r = __ase_make_resc_rng_eint(small_ring);
501 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
502 } else if (errno == ERANGE) {
505 resc_rng_set_string(ring, start);
506 r = __ase_make_resc_rng_bigz(ring);
513 /* generate and return the ring */
514 return _ase_wrap_resc_rng(r);
518 ase_resc_elm_from_string(char *cp)
520 ase_resc_elm_t e = NULL;
521 ase_resc_rng_t r = NULL;
524 EMACS_INT small_ring;
527 /* MPZ bigz_set_string has no effect
528 * with initial + sign */
535 /* jump over a leading minus */
539 while ((*cp >= '0' && *cp <= '9'))
542 /* MPZ cannot read numbers with characters after them.
543 * See limitations of GMP-MPZ strings
548 small_elm = strtol(start, &tail, 10);
550 e = __ase_make_resc_elm_eint(small_elm);
551 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
552 } else if (errno == ERANGE) {
555 resc_elm_set_string(elm, start);
556 e = __ase_make_resc_elm_bigz(elm);
563 /* read the modulus */
567 while ((*cp >= '0' && *cp <= '9'))
572 small_ring = strtol(start, &tail, 10);
574 r = __ase_make_resc_rng_eint(small_ring);
575 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
576 } else if (errno == ERANGE) {
579 resc_rng_set_string(ring, start);
580 r = __ase_make_resc_rng_bigz(ring);
587 /* now we have 4 possibilites: */
588 if (e->smallp && r->smallp) {
589 e->ring = _ase_wrap_resc_rng(r);
590 _ase_resc_elm_canonicalise_small(e);
591 return _ase_wrap_resc_elm(e);
592 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
593 } else if (e->smallp) {
594 /* the class is small, the ring is not,
595 * thus we have to promote the class now */
596 resc_elm_init(ase_resc_elm_data(e));
597 resc_elm_set_eint(ase_resc_elm_data(e), e->small_data);
599 e->ring = _ase_wrap_resc_rng(r);
600 _ase_resc_elm_canonicalise_big(e);
601 return _ase_wrap_resc_elm(e);
602 } else if (r->smallp) {
603 /* we're in deep shit, the class is bigz, the ring is small
604 * and to make it worse, we can't use the ENT mod table */
605 bigz_set_long(ent_scratch_bigz, r->small_ring);
606 bigz_mod(ent_scratch_bigz,
607 ase_resc_elm_data(e), ent_scratch_bigz);
608 /* now ent_scratch_bigz should fit into a long */
609 e->small_data = bigz_to_long(ent_scratch_bigz);
611 /* finish the temporarily assigned big data slot */
612 resc_elm_fini(ase_resc_elm_data(e));
613 e->ring = _ase_wrap_resc_rng(r);
614 /* no need to canonicalise */
615 return _ase_wrap_resc_elm(e);
617 /* phew, finally an easy case */
618 e->ring = _ase_wrap_resc_rng(r);
619 _ase_resc_elm_canonicalise_big(e);
620 return _ase_wrap_resc_elm(e);
631 /* for complex numbers */
632 #define INTERMEDIATE_UNARY_SYMBOL 32
634 #define DOT_CHAR2 128
635 #define TRAIL_INT2 256
637 #define EXP_INT2 1024
643 ase_resc_rng_string_p(const char *cp)
646 const Bufbyte *ucp = (const Bufbyte *)cp;
649 /* parse the residue class */
651 if (*ucp++ == 'Z' && *ucp++ == '/')
654 /* check if we had a int number until here */
655 if (!(state == (LEAD_Z)))
658 /* now look for the modulus */
660 if (*ucp >= '1' && *ucp <= '9') {
662 while (*ucp >= '0' && *ucp <= '9')
669 return (((*ucp == 0) || (*ucp == ' ') || (*ucp == '\t') ||
670 (*ucp == '\n') || (*ucp == '\r') || (*ucp == '\f')) &&
671 (state == (LEAD_INT2 | Z_CHAR)));
675 ase_resc_elm_string_p(const char *cp)
678 const Bufbyte *ucp = (const Bufbyte *)cp;
681 /* parse the residue class */
683 if (*ucp == '+' || *ucp == '-')
686 if (*ucp >= '0' && *ucp <= '9') {
688 while (*ucp >= '0' && *ucp <= '9')
692 /* check if we had a int number until here */
693 if (!(state == (LEAD_INT)))
696 /* now look for the residue class ring */
699 state |= INTERMEDIATE_UNARY_SYMBOL;
703 if (*ucp >= '1' && *ucp <= '9') {
705 while (*ucp >= '0' && *ucp <= '9')
712 return (((*ucp == 0) || (*ucp == ' ') || (*ucp == '\t') ||
713 (*ucp == '\n') || (*ucp == '\r') || (*ucp == '\f')) &&
714 (state == (INTERMEDIATE_UNARY_SYMBOL | LEAD_INT2 | Z_CHAR)));
720 ent_intersection_factor_module(Lisp_Object *l, Lisp_Object *r)
722 Lisp_Object result_ring;
724 /* return a resulting ring by intersection of the rings in l and r and
725 * coerce l and r to that ring.
728 if (!bigz_eql(XRESC_RNG_DATA(XRESC_ELM_RING(*l)),
729 XRESC_RNG_DATA(XRESC_ELM_RING(*r)))) {
731 /* find a ring by intersection */
732 bigz_lcm(ent_scratch_bigz,
733 XRESC_RNG_DATA(XRESC_ELM_RING(*l)),
734 XRESC_RNG_DATA(XRESC_ELM_RING(*r)));
735 result_ring = make_resc_rng_bz(ent_scratch_bigz);
737 /* coerce the left ring element to the lcm-ring */
738 bigz_div(ent_scratch_bigz,
739 XRESC_RNG_DATA(result_ring),
740 XRESC_RNG_DATA(XRESC_ELM_RING(*l)));
741 bigz_mul(ent_scratch_bigz,
744 *l = make_resc_elm_bz(ent_scratch_bigz, result_ring);
746 /* coerce the right ring element to the lcm-ring */
747 bigz_div(ent_scratch_bigz,
748 XRESC_RNG_DATA(result_ring),
749 XRESC_RNG_DATA(XRESC_ELM_RING(*r)));
750 bigz_mul(ent_scratch_bigz,
753 *r = make_resc_elm_bz(ent_scratch_bigz, result_ring);
756 result_ring = XRESC_ELM_RING(*l);
763 ase_resclass_check_rings(Lisp_Object l, Lisp_Object r)
765 if (XASE_RESC_ELM_SMALLP(l) ^ XASE_RESC_ELM_SMALLP(r)) {
767 Fsignal(Qdomain_error, list2(
768 XASE_RESC_ELM_RING(l), XASE_RESC_ELM_RING(r)));
770 } else if (XASE_RESC_ELM_SMALLP(l) &&
771 XASE_RESC_RNG_SRING(XASE_RESC_ELM_RING(l)) ==
772 XASE_RESC_RNG_SRING(XASE_RESC_ELM_RING(r))) {
774 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
775 } else if (!XASE_RESC_ELM_SMALLP(l) &&
776 bigz_eql(XASE_RESC_RNG_RING(XASE_RESC_ELM_RING(l)),
777 XASE_RESC_RNG_RING(XASE_RESC_ELM_RING(r)))) {
785 static inline Lisp_Object
786 ase_resclass_sum_small(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
789 XASE_RESC_ELM(l)->small_data + XASE_RESC_ELM(r)->small_data;
790 return ase_make_resc_elm(make_int(sum), result_ring);
793 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
794 static inline Lisp_Object
795 ase_resclass_sum_big(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
797 ase_resc_elm_t e = NULL;
798 bigz_add(ent_scratch_bigz,
799 XASE_RESC_ELM_DATA(l), XASE_RESC_ELM_DATA(r));
800 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
802 e->ring = result_ring;
803 _ase_resc_elm_canonicalise_big(e);
804 return _ase_wrap_resc_elm(e);
809 ase_resclass_sum(Lisp_Object l, Lisp_Object r)
811 ase_resclass_check_rings(l, r);
814 result_ring = ent_intersection_factor_module(&l, &r);
817 if (XASE_RESC_ELM_SMALLP(l) && XASE_RESC_ELM_SMALLP(r)) {
818 return ase_resclass_sum_small(l, r, XASE_RESC_ELM_RING(l));
820 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
821 return ase_resclass_sum_big(l, r, XASE_RESC_ELM_RING(l));
828 static inline Lisp_Object
829 ase_resclass_sum_intg_small(
830 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
834 XASE_RESC_ELM(l)->small_data + XINT(intg);
835 return ase_make_resc_elm(make_int(sum), result_ring);
836 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
837 } else if (BIGZP(intg)) {
839 bigz_set_long(ent_scratch_bigz,
840 XASE_RESC_RNG(XASE_RESC_ELM_RING(l))->small_ring);
841 bigz_mod(ent_scratch_bigz, XBIGZ_DATA(intg), ent_scratch_bigz);
842 sum = XASE_RESC_ELM(l)->small_data +
843 bigz_to_long(ent_scratch_bigz);
844 return ase_make_resc_elm(make_int(sum), result_ring);
850 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
851 static inline Lisp_Object
852 ase_resclass_sum_intg_big(
853 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
856 ase_resc_elm_t e = NULL;
857 bigz_set_long(ent_scratch_bigz, XINT(intg));
858 bigz_add(ent_scratch_bigz,
859 XASE_RESC_ELM_DATA(l), ent_scratch_bigz);
860 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
862 e->ring = result_ring;
863 _ase_resc_elm_canonicalise_big(e);
864 return _ase_wrap_resc_elm(e);
865 } else if (BIGZP(intg)) {
866 ase_resc_elm_t e = NULL;
867 bigz_add(ent_scratch_bigz,
868 XASE_RESC_ELM_DATA(l), XBIGZ_DATA(intg));
869 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
871 e->ring = result_ring;
872 _ase_resc_elm_canonicalise_big(e);
873 return _ase_wrap_resc_elm(e);
880 ase_resclass_sum_intg(Lisp_Object l, Lisp_Object r)
882 if (INTEGERP(l) && XASE_RESC_ELM_SMALLP(r)) {
883 return ase_resclass_sum_intg_small(
884 r, l, XASE_RESC_ELM_RING(r));
885 } else if (INTEGERP(r) && XASE_RESC_ELM_SMALLP(l)) {
886 return ase_resclass_sum_intg_small(
887 l, r, XASE_RESC_ELM_RING(l));
888 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
889 } else if (INTEGERP(l)) {
890 return ase_resclass_sum_intg_big(
891 r, l, XASE_RESC_ELM_RING(r));
892 } else if (INTEGERP(r)) {
893 return ase_resclass_sum_intg_big(
894 l, r, XASE_RESC_ELM_RING(l));
901 static inline Lisp_Object
902 ase_resclass_diff_small(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
905 XASE_RESC_ELM(l)->small_data - XASE_RESC_ELM(r)->small_data;
906 return ase_make_resc_elm(make_int(diff), result_ring);
909 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
910 static inline Lisp_Object
911 ase_resclass_diff_big(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
913 ase_resc_elm_t e = NULL;
914 bigz_sub(ent_scratch_bigz,
915 XASE_RESC_ELM_DATA(l), XASE_RESC_ELM_DATA(r));
916 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
918 e->ring = result_ring;
919 _ase_resc_elm_canonicalise_big(e);
920 return _ase_wrap_resc_elm(e);
925 ase_resclass_diff(Lisp_Object l, Lisp_Object r)
927 ase_resclass_check_rings(l, r);
930 result_ring = ent_intersection_factor_module(&l, &r);
933 if (XASE_RESC_ELM_SMALLP(l) && XASE_RESC_ELM_SMALLP(r)) {
934 return ase_resclass_diff_small(l, r, XASE_RESC_ELM_RING(l));
936 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
937 return ase_resclass_diff_big(l, r, XASE_RESC_ELM_RING(l));
944 static inline Lisp_Object
945 ase_resclass_diff_intg_small(
946 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
950 XASE_RESC_ELM(l)->small_data - XINT(intg);
951 return ase_make_resc_elm(make_int(diff), result_ring);
952 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
953 } else if (BIGZP(intg)) {
955 bigz_set_long(ent_scratch_bigz,
956 XASE_RESC_RNG(XASE_RESC_ELM_RING(l))->small_ring);
957 bigz_mod(ent_scratch_bigz, XBIGZ_DATA(intg), ent_scratch_bigz);
958 diff = XASE_RESC_ELM(l)->small_data -
959 bigz_to_long(ent_scratch_bigz);
960 return ase_make_resc_elm(make_int(diff), result_ring);
966 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
967 static inline Lisp_Object
968 ase_resclass_diff_intg_big(
969 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
972 ase_resc_elm_t e = NULL;
973 bigz_set_long(ent_scratch_bigz, XINT(intg));
974 bigz_sub(ent_scratch_bigz,
975 XASE_RESC_ELM_DATA(l), ent_scratch_bigz);
976 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
978 e->ring = result_ring;
979 _ase_resc_elm_canonicalise_big(e);
980 return _ase_wrap_resc_elm(e);
981 } else if (BIGZP(intg)) {
982 ase_resc_elm_t e = NULL;
983 bigz_sub(ent_scratch_bigz,
984 XASE_RESC_ELM_DATA(l), XBIGZ_DATA(intg));
985 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
987 e->ring = result_ring;
988 _ase_resc_elm_canonicalise_big(e);
989 return _ase_wrap_resc_elm(e);
996 ase_resclass_diff_intg(Lisp_Object l, Lisp_Object r)
998 if (XASE_RESC_ELM_SMALLP(l)) {
999 return ase_resclass_diff_intg_small(
1000 l, r, XASE_RESC_ELM_RING(l));
1001 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1003 return ase_resclass_diff_intg_big(
1004 l, r, XASE_RESC_ELM_RING(l));
1011 static inline Lisp_Object
1012 ase_resclass_prod_small(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
1015 XASE_RESC_ELM(l)->small_data * XASE_RESC_ELM(r)->small_data;
1016 return ase_make_resc_elm(make_int(prod), result_ring);
1019 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1020 static inline Lisp_Object
1021 ase_resclass_prod_big(Lisp_Object l, Lisp_Object r, Lisp_Object result_ring)
1023 ase_resc_elm_t e = NULL;
1024 bigz_mul(ent_scratch_bigz,
1025 XASE_RESC_ELM_DATA(l), XASE_RESC_ELM_DATA(r));
1026 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1028 e->ring = result_ring;
1029 _ase_resc_elm_canonicalise_big(e);
1030 return _ase_wrap_resc_elm(e);
1035 ase_resclass_prod(Lisp_Object l, Lisp_Object r)
1037 ase_resclass_check_rings(l, r);
1040 result_ring = ent_intersection_factor_module(&l, &r);
1043 if (XASE_RESC_ELM_SMALLP(l) && XASE_RESC_ELM_SMALLP(r)) {
1044 return ase_resclass_prod_small(l, r, XASE_RESC_ELM_RING(l));
1046 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1047 return ase_resclass_prod_big(l, r, XASE_RESC_ELM_RING(l));
1053 static inline Lisp_Object
1054 ase_resclass_prod_intg_small(
1055 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
1059 XASE_RESC_ELM(l)->small_data * XINT(intg);
1060 return ase_make_resc_elm(make_int(prod), result_ring);
1061 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1062 } else if (BIGZP(intg)) {
1064 bigz_set_long(ent_scratch_bigz,
1065 XASE_RESC_RNG(XASE_RESC_ELM_RING(l))->small_ring);
1066 bigz_mod(ent_scratch_bigz, XBIGZ_DATA(intg), ent_scratch_bigz);
1067 prod = XASE_RESC_ELM(l)->small_data *
1068 bigz_to_long(ent_scratch_bigz);
1069 return ase_make_resc_elm(make_int(prod), result_ring);
1075 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1076 static inline Lisp_Object
1077 ase_resclass_prod_intg_big(
1078 Lisp_Object l, Lisp_Object intg, Lisp_Object result_ring)
1081 ase_resc_elm_t e = NULL;
1082 bigz_set_long(ent_scratch_bigz, XINT(intg));
1083 bigz_mul(ent_scratch_bigz,
1084 XASE_RESC_ELM_DATA(l), ent_scratch_bigz);
1085 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1087 e->ring = result_ring;
1088 _ase_resc_elm_canonicalise_big(e);
1089 return _ase_wrap_resc_elm(e);
1090 } else if (BIGZP(intg)) {
1091 ase_resc_elm_t e = NULL;
1092 bigz_mul(ent_scratch_bigz,
1093 XASE_RESC_ELM_DATA(l), XBIGZ_DATA(intg));
1094 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1096 e->ring = result_ring;
1097 _ase_resc_elm_canonicalise_big(e);
1098 return _ase_wrap_resc_elm(e);
1105 ase_resclass_prod_intg(Lisp_Object l, Lisp_Object r)
1107 if (INTEGERP(l) && XASE_RESC_ELM_SMALLP(r)) {
1108 return ase_resclass_prod_intg_small(
1109 r, l, XASE_RESC_ELM_RING(r));
1110 } else if (INTEGERP(r) && XASE_RESC_ELM_SMALLP(l)) {
1111 return ase_resclass_prod_intg_small(
1112 l, r, XASE_RESC_ELM_RING(l));
1113 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1114 } else if (INTEGERP(l)) {
1115 return ase_resclass_prod_intg_big(
1116 r, l, XASE_RESC_ELM_RING(r));
1117 } else if (INTEGERP(r)) {
1118 return ase_resclass_prod_intg_big(
1119 l, r, XASE_RESC_ELM_RING(l));
1127 ase_resclass_div(Lisp_Object l, Lisp_Object r)
1129 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1130 Lisp_Object inv = _ent_unop(ASE_UNARY_OP_INV, idx, r);
1131 Lisp_Object mul = _ent_binop(ASE_BINARY_OP_PROD, idx, l, idx, inv);
1136 ase_resclass_div_INT_T(Lisp_Object l, Lisp_Object r)
1138 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1139 Lisp_Object inv = _ent_unop(ASE_UNARY_OP_INV, idx, l);
1140 Lisp_Object mul = _ent_binop(ASE_BINARY_OP_PROD, idx, inv, INT_T, r);
1145 ase_resclass_INT_T_div(Lisp_Object l, Lisp_Object r)
1147 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1148 Lisp_Object inv = _ent_unop(ASE_UNARY_OP_INV, idx, r);
1149 Lisp_Object mul = _ent_binop(ASE_BINARY_OP_PROD, idx, l, INT_T, inv);
1154 ase_resclass_div_BIGZ_T(Lisp_Object l, Lisp_Object r)
1156 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1157 Lisp_Object inv = _ent_unop(ASE_UNARY_OP_INV, idx, l);
1158 Lisp_Object mul = _ent_binop(ASE_BINARY_OP_PROD, idx, inv, BIGZ_T, r);
1163 ase_resclass_BIGZ_T_div(Lisp_Object l, Lisp_Object r)
1165 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1166 Lisp_Object inv = _ent_unop(ASE_UNARY_OP_INV, idx, r);
1167 Lisp_Object mul = _ent_binop(ASE_BINARY_OP_PROD, idx, l, BIGZ_T, inv);
1171 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1173 ase_resclass_pow(Lisp_Object l, Lisp_Object r)
1175 Lisp_Object rng = XASE_RESC_ELM_RING(l);
1180 bigz_set_long(expo, ent_int(r));
1181 } else if (BIGZP(r)) {
1182 bigz_set(expo, XBIGZ_DATA(r));
1184 Fsignal(Qoperation_error, r);
1187 if (XASE_RESC_ELM_SMALLP(l)) {
1192 bigz_set_long(tmp, XASE_RESC_RNG_SRING(rng));
1193 bigz_set_long(ent_scratch_bigz, XASE_RESC_ELM_SDATA(l));
1194 mpz_powm(ent_scratch_bigz, ent_scratch_bigz, expo, tmp);
1195 res = bigz_to_long(ent_scratch_bigz);
1198 return ase_make_resc_elm(make_int(res), rng);
1200 ase_resc_elm_t e = NULL;
1201 mpz_powm(ent_scratch_bigz, XASE_RESC_ELM_DATA(l),
1202 expo, XASE_RESC_RNG_RING(l));
1203 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1205 e->ring = XASE_RESC_ELM_RING(l);
1206 _ase_resc_elm_canonicalise_big(e);
1208 return _ase_wrap_resc_elm(e);
1216 ase_resclass_neg(Lisp_Object l)
1218 Lisp_Object rng = XASE_RESC_ELM_RING(l);
1219 if (XASE_RESC_ELM_SMALLP(l)) {
1221 XASE_RESC_RNG_SRING(rng) - XASE_RESC_ELM_SDATA(l);
1222 return ase_make_resc_elm(make_int(sum), rng);
1223 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1225 ase_resc_elm_t e = NULL;
1226 bigz_set(ent_scratch_bigz, XASE_RESC_RNG_RING(rng));
1227 bigz_sub(ent_scratch_bigz,
1228 ent_scratch_bigz, XASE_RESC_ELM_DATA(l));
1229 e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1232 _ase_resc_elm_canonicalise_big(e);
1233 return _ase_wrap_resc_elm(e);
1239 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1241 ase_resclass_inv(Lisp_Object r)
1243 Lisp_Object rng = XASE_RESC_ELM_RING(r);
1247 if (XASE_RESC_ELM_SMALLP(r)) {
1250 bigz_set_long(tmp, XASE_RESC_ELM_SDATA(r));
1251 bigz_set_long(ent_scratch_bigz, XASE_RESC_RNG_SRING(rng));
1252 state = mpz_invert(ent_scratch_bigz, tmp, ent_scratch_bigz);
1255 state = mpz_invert(ent_scratch_bigz,
1256 XASE_RESC_ELM_DATA(r),
1257 XASE_RESC_RNG_RING(rng));
1261 error("cannot operate on zero divisor");
1265 if (XASE_RESC_ELM_SMALLP(r)) {
1266 return ase_make_resc_elm(
1267 make_int(bigz_to_long(ent_scratch_bigz)), rng);
1269 ase_resc_elm_t e = __ase_make_resc_elm_bigz(ent_scratch_bigz);
1272 _ase_resc_elm_canonicalise_big(e);
1273 return _ase_wrap_resc_elm(e);
1281 ase_resclass_eq(Lisp_Object l, Lisp_Object r)
1283 ase_resclass_check_rings(l, r);
1285 if (XASE_RESC_ELM_SMALLP(l)) {
1286 return (XASE_RESC_ELM_SDATA(l) == XASE_RESC_ELM_SDATA(r));
1287 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1288 } else if (!XASE_RESC_ELM_SMALLP(l)) {
1289 return bigz_eql(XASE_RESC_ELM_DATA(l), XASE_RESC_ELM_DATA(r));
1296 ase_resclass_ne(Lisp_Object l, Lisp_Object r)
1298 ase_resclass_check_rings(l, r);
1300 if (XASE_RESC_ELM_SMALLP(l)) {
1301 return (XASE_RESC_ELM_SDATA(l) != XASE_RESC_ELM_SDATA(r));
1302 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1303 } else if (!XASE_RESC_ELM_SMALLP(l)) {
1304 return !bigz_eql(XASE_RESC_ELM_DATA(l), XASE_RESC_ELM_DATA(r));
1311 ase_resclass_zerop(Lisp_Object elm)
1313 if (XASE_RESC_ELM_SMALLP(elm)) {
1314 return (XASE_RESC_ELM_SDATA(elm) == 0);
1315 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1316 } else if (!XASE_RESC_ELM_SMALLP(elm)) {
1317 # define __d XASE_RESC_ELM_DATA(elm)
1318 return (bigz_fits_long_p(__d) && bigz_to_long(__d) == 0);
1326 ase_resclass_onep(Lisp_Object elm)
1328 if (XASE_RESC_ELM_SMALLP(elm)) {
1329 return (XASE_RESC_ELM_SDATA(elm) == 1);
1330 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1331 } else if (!XASE_RESC_ELM_SMALLP(elm)) {
1332 # define __d XASE_RESC_ELM_DATA(elm)
1333 return (bigz_fits_long_p(__d) && bigz_to_long(__d) == 1);
1340 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1342 ase_resclass_unitp(Lisp_Object elm)
1344 Lisp_Object rng = XASE_RESC_ELM_RING(elm);
1348 if (XASE_RESC_ELM_SMALLP(elm)) {
1350 bigz_set_long(tmp, XASE_RESC_ELM_SDATA(elm));
1351 bigz_set_long(ent_scratch_bigz, XASE_RESC_RNG_SRING(rng));
1352 state = mpz_invert(ent_scratch_bigz, tmp, ent_scratch_bigz);
1355 state = mpz_invert(ent_scratch_bigz,
1356 XASE_RESC_ELM_DATA(elm),
1357 XASE_RESC_RNG_RING(rng));
1364 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1366 ase_resclass_lift_to_BIGZ_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1368 if (XASE_RESC_ELM_SMALLP(number)) {
1369 make_bigz(XASE_RESC_ELM_SDATA(number));
1371 return make_bigz_bz(XASE_RESC_ELM_DATA(number));
1378 ase_resclass_lift_to_INT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1380 if (XASE_RESC_ELM_SMALLP(number)) {
1381 return make_int(XASE_RESC_ELM_SDATA(number));
1382 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1384 return make_int(bigz_to_long(XASE_RESC_ELM_DATA(number)));
1392 ase_resclass_lift_to_FLOAT_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1394 if (XASE_RESC_ELM_SMALLP(number)) {
1395 return make_float(XASE_RESC_ELM_SDATA(number));
1396 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1398 return make_float(bigz_to_fpfloat(XASE_RESC_ELM_DATA(number)));
1407 ent_resclass_nullary_optable_init(void)
1409 ent_nullop_register(ASE_NULLARY_OP_ZERO, INDEF_T, Qzero);
1410 ent_nullop_register(ASE_NULLARY_OP_ONE, INDEF_T, Qone);
1414 ent_resclass_unary_optable_init(void)
1416 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1417 ent_unop_register(ASE_UNARY_OP_NEG, idx, ase_resclass_neg);
1418 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1419 ent_unop_register(ASE_UNARY_OP_INV, idx, ase_resclass_inv);
1424 ent_resclass_binary_optable_init(void)
1426 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1428 ent_binop_register(ASE_BINARY_OP_SUM,
1429 idx, idx, ase_resclass_sum);
1430 ent_binop_register(ASE_BINARY_OP_SUM,
1431 idx, INT_T, ase_resclass_sum_intg);
1432 ent_binop_register(ASE_BINARY_OP_SUM,
1433 INT_T, idx, ase_resclass_sum_intg);
1434 ent_binop_register(ASE_BINARY_OP_SUM,
1435 idx, BIGZ_T, ase_resclass_sum_intg);
1436 ent_binop_register(ASE_BINARY_OP_SUM,
1437 BIGZ_T, idx, ase_resclass_sum_intg);
1439 ent_binop_register(ASE_BINARY_OP_DIFF,
1440 idx, idx, ase_resclass_diff);
1441 ent_binop_register(ASE_BINARY_OP_DIFF,
1442 idx, INT_T, ase_resclass_diff_intg);
1443 ent_binop_register(ASE_BINARY_OP_DIFF,
1444 idx, BIGZ_T, ase_resclass_diff_intg);
1446 ent_binop_register(ASE_BINARY_OP_PROD,
1447 idx, idx, ase_resclass_prod);
1448 ent_binop_register(ASE_BINARY_OP_PROD,
1449 idx, INT_T, ase_resclass_prod_intg);
1450 ent_binop_register(ASE_BINARY_OP_PROD,
1451 INT_T, idx, ase_resclass_prod_intg);
1452 ent_binop_register(ASE_BINARY_OP_PROD,
1453 idx, BIGZ_T, ase_resclass_prod_intg);
1454 ent_binop_register(ASE_BINARY_OP_PROD,
1455 BIGZ_T, idx, ase_resclass_prod_intg);
1457 ent_binop_register(ASE_BINARY_OP_DIV,
1458 idx, idx, ase_resclass_div);
1459 ent_binop_register(ASE_BINARY_OP_QUO,
1460 idx, idx, ase_resclass_div);
1461 ent_binop_register(ASE_BINARY_OP_DIV,
1462 idx, INT_T, ase_resclass_div_INT_T);
1463 ent_binop_register(ASE_BINARY_OP_QUO,
1464 idx, INT_T, ase_resclass_div_INT_T);
1465 ent_binop_register(ASE_BINARY_OP_DIV,
1466 INT_T, idx, ase_resclass_INT_T_div);
1467 ent_binop_register(ASE_BINARY_OP_QUO,
1468 INT_T, idx, ase_resclass_INT_T_div);
1469 ent_binop_register(ASE_BINARY_OP_DIV,
1470 idx, BIGZ_T, ase_resclass_div_BIGZ_T);
1471 ent_binop_register(ASE_BINARY_OP_QUO,
1472 idx, BIGZ_T, ase_resclass_div_BIGZ_T);
1473 ent_binop_register(ASE_BINARY_OP_DIV,
1474 BIGZ_T, idx, ase_resclass_BIGZ_T_div);
1475 ent_binop_register(ASE_BINARY_OP_QUO,
1476 BIGZ_T, idx, ase_resclass_BIGZ_T_div);
1478 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1479 ent_binop_register(ASE_BINARY_OP_POW,
1480 idx, INT_T, ase_resclass_pow);
1481 ent_binop_register(ASE_BINARY_OP_POW,
1482 idx, BIGZ_T, ase_resclass_pow);
1487 ent_resclass_unary_reltable_init(void)
1489 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1490 ent_unrel_register(ASE_UNARY_REL_ZEROP, idx, ase_resclass_zerop);
1491 ent_unrel_register(ASE_UNARY_REL_ONEP, idx, ase_resclass_onep);
1492 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1493 ent_unrel_register(ASE_UNARY_REL_UNITP, idx, ase_resclass_unitp);
1498 ent_resclass_binary_reltable_init(void)
1500 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1501 ent_binrel_register(ASE_BINARY_REL_EQUALP,
1502 idx, idx, ase_resclass_eq);
1503 ent_binrel_register(ASE_BINARY_REL_NEQP,
1504 idx, idx, ase_resclass_ne);
1508 ent_resclass_lifttable_init(void)
1510 ase_object_type_t idx = ase_optable_index_typesym(Qase_resc_elm);
1511 ent_lift_register(idx, INT_T, ase_resclass_lift_to_INT_T);
1512 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1513 ent_lift_register(idx, BIGZ_T, ase_resclass_lift_to_BIGZ_T);
1516 ent_lift_register(idx, FLOAT_T, ase_resclass_lift_to_FLOAT_T);
1522 DEFUN("make-residue-class-ring", Fmake_residue_class_ring, 1, 1, 0, /*
1523 Return a residue class ring of size MODULUS (>= 2).
1527 CHECK_INTEGER(modulus);
1528 if (NILP(Fnonnegativep(modulus)))
1529 error("cannot create ring with negative modulus");
1530 if (ent_unrel_zerop(modulus))
1531 error("cannot create ring of size 0");
1532 if (ent_unrel_onep(modulus))
1533 error("ring is identical to Z");
1535 return ase_make_resc_rng(modulus);
1539 DEFUN("make-residue-class", Fmake_residue_class, 2, 2, 0, /*
1540 Return the residue class of ELEMENT in RING.
1544 CHECK_ASE_RESC_RNG(ring);
1545 CHECK_INTEGER(element);
1547 return ase_make_resc_elm(element, ring);
1551 DEFUN("residue-class-ring", Fresidue_class_ring, 1, 1, 0, /*
1552 Return the parental residue class ring (the world) of RESCLASS.
1556 CHECK_ASE_RESC_ELM(resclass);
1558 return XASE_RESC_ELM_RING(resclass);
1563 D3FUN("residue-class-modulus", Fresidue_class_modulus, 1, 1, 0, /*
1564 Return the modulus of the residue class ring RING-OR-ELEMENT,
1565 or the modulus of a residue class, respectively.
1571 if (!ASE_RESC_ELM_P(ring_or_element) &&
1572 !ASE_RESC_RNG_P(ring_or_element)) {
1573 return wrong_type_argument(Qase_resc_elm_p, ring_or_element);
1576 if (ASE_RESC_ELM_P(ring_or_element))
1577 rng = XASE_RESC_ELM_RING(ring_or_element);
1578 else if (ASE_RESC_RNG_P(ring_or_element))
1579 rng = ring_or_element;
1583 return make_bigz_bz(XASE_RESC_RNG_RING(rng));
1587 D3FUN("residue-class-representant", Fresidue_class_representant, 1, 1, 0, /*
1588 Return the representant of the residue class ELEMENT lifted
1589 to the ring of rational integers.
1593 CHECK_ASE_RESC_ELM(element);
1595 return make_bigz_bz(XASE_RESC_ELM_DATA(element));
1600 DEFUN ("residue-class-ring-p", Fresidue_class_ring_p, 1, 1, 0, /*
1601 Return t if OBJECT is a residue class ring, nil otherwise.
1605 return ASE_RESC_RNG_P(object) ? Qt : Qnil;
1609 DEFUN ("residue-class-p", Fresidue_class_p, 1, 1, 0, /*
1610 Return t if OBJECT is a residue class, nil otherwise.
1614 return ASE_RESC_ELM_P(object) ? Qt : Qnil;
1617 /* from number-to-string */
1618 #ifdef HAVE_RESCLASS
1619 if (RESC_ELMP(number)) {
1620 char *estr = (char*)resc_elm_to_string(
1621 XRESC_ELM_DATA(number), 10);
1622 char *rstr = (char*)resc_rng_to_string(
1623 XRESC_RNG_DATA(XRESC_ELM_RING(number)), 10);
1624 int elen = strlen(estr);
1625 int rlen = strlen(rstr);
1628 XREALLOC_ARRAY(estr, char, elen+1+rlen+1 + 1);
1629 strncat(estr, "+", 1);
1630 strncat(estr, rstr, rlen);
1631 strncat(estr, "Z", 1);
1632 result = build_string(estr);
1639 /* from zero-divisor-p */
1640 #ifdef HAVE_RESCLASS
1645 if (mpz_invert(bz, XRESC_ELM_DATA(number),
1646 XRESC_RNG_DATA(XRESC_ELM_RING(number))))
1657 /* initialiser code */
1658 #define EMODNAME ase_resclass
1661 ase_resclass_binary_optable_init(void)
1663 ent_resclass_nullary_optable_init();
1664 ent_resclass_unary_optable_init();
1665 ent_resclass_binary_optable_init();
1666 ent_resclass_unary_reltable_init();
1667 ent_resclass_binary_reltable_init();
1668 ent_resclass_lifttable_init();
1674 DEFSUBR(Fmake_residue_class_ring);
1675 DEFSUBR(Fmake_residue_class);
1676 DEFSUBR(Fresidue_class_ring);
1678 DEFSUBR(Fresidue_class_modulus);
1679 DEFSUBR(Fresidue_class_representant);
1681 DEFSUBR(Fresidue_class_ring_p);
1682 DEFSUBR(Fresidue_class_p);
1684 DEFSYMBOL(Qase_resclass);
1685 DEFASETYPE_WITH_OPS(Qase_resc_rng, "ase:residue-class-ring");
1686 defsymbol(&Qase_resc_rng_p, "ase:residue-class-ring-p");
1687 DEFASETYPE_WITH_OPS(Qase_resc_elm, "ase:residue-class");
1688 defsymbol(&Qase_resc_elm_p, "ase:residue-class-p");
1690 ase_resclass_binary_optable_init();
1692 Fprovide(Qase_resclass);
1693 Fprovide(intern("resclass"));
1699 EMOD_PUBREINIT(void)
1701 sane_small = (snprintf(NULL, 0, "%ld", EMACS_INT_MAX) + 7) & -3;
1702 /* defined in lread.c, declared in ent.h */
1703 ase_resc_rng_pred_f = ase_resc_rng_string_p;
1704 ase_resc_rng_f = ase_resc_rng_from_string;
1705 ase_resc_elm_pred_f = ase_resc_elm_string_p;
1706 ase_resc_elm_f = ase_resc_elm_from_string;
1710 EMOD_PUBDEINIT(void)
1712 Frevoke(Qase_resclass);
1713 Frevoke(intern("resclass"));
1716 /* ent-resclass.c ends here */