1 // Modular integer operations.
9 #include "cl_modinteger.h"
18 #include "cl_integer_io.h"
22 #include "cl_alloca.h"
25 cl_heap_modint_ring::cl_heap_modint_ring (cl_I m, cl_modint_setops* setopv, cl_modint_addops* addopv, cl_modint_mulops* mulopv)
26 : setops (setopv), addops (addopv), mulops (mulopv), modulus (m)
28 refcount = 0; // will be incremented by the `cl_modint_ring' constructor
29 type = &cl_class_modint_ring;
30 if (minusp(m)) cl_abort();
32 var uintL b = integer_length(m-1);
33 // m <= 2^b, hence one needs b bits for a representative mod m.
35 log2_bits = 0; bits = 1;
36 } else if (b <= cl_word_size) {
38 integerlength32(b-1,bb=); // b <= 2^bb with bb minimal
39 log2_bits = bb; bits = 1<<bb;
41 log2_bits = -1; bits = -1;
44 log2_bits = -1; bits = -1;
48 static void cl_modint_ring_destructor (cl_heap* pointer)
50 (*(cl_heap_modint_ring*)pointer).~cl_heap_modint_ring();
53 cl_class cl_class_modint_ring = {
54 cl_modint_ring_destructor,
58 // This tells the compiler to put the `cl_heap_modint_ring' vtable
60 void cl_heap_modint_ring::dummy () {}
63 static cl_boolean modint_equal (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y)
66 return cl_equal(x.rep,y.rep);
69 #include "cl_MI_int.h"
70 #include "cl_MI_std.h"
71 #include "cl_MI_fix16.h"
72 #if (cl_value_len <= 32)
73 #include "cl_MI_fix29.h"
74 #include "cl_MI_int32.h"
76 #include "cl_MI_fix32.h"
78 #include "cl_MI_pow2.h"
79 #include "cl_MI_pow2m1.h"
80 #include "cl_MI_pow2p1.h"
81 #include "cl_MI_montgom.h"
84 static inline cl_heap_modint_ring* make_modint_ring (const cl_I& m) // m >= 0
87 return new cl_heap_modint_ring_int();
90 var uintL log2_m = power2p(m);
92 return new cl_heap_modint_ring_pow2(m,log2_m-1);
96 var uintL log2_m = integer_length(m); // = integerlength(m-1)
97 if (log2_m < 16) // m < 0x10000
98 return new cl_heap_modint_ring_fix16(m);
99 #if (cl_value_len <= 32)
100 if (log2_m < cl_value_len)
101 return new cl_heap_modint_ring_fix29(m);
102 if (log2_m < 32) // m < 0x100000000
103 return new cl_heap_modint_ring_int32(m);
105 if (log2_m < 32) // m < 0x100000000
106 return new cl_heap_modint_ring_fix32(m);
110 var uintL m1 = power2p(m+1);
112 return new cl_heap_modint_ring_pow2m1(m,m1-1);
115 var uintL m1 = power2p(m-1);
117 return new cl_heap_modint_ring_pow2p1(m,m1-1);
120 var cl_heap_modint_ring* R = try_make_modint_ring_montgom(m);
124 return new cl_heap_modint_ring_std(m);
128 // The table of modular integer rings.
129 // A weak hash table cl_I -> cl_modint_ring.
130 // (It could also be a weak hashuniq table cl_I -> cl_modint_ring.)
132 #include "cl_I_hashweak_rcpointer.h"
134 // An entry can be collected when the value (the ring) isn't referenced any more
135 // except from the hash table, and when the key (the modulus) isn't referenced
136 // any more except from the hash table and the ring. Note that the ring contains
137 // exactly one reference to the modulus.
139 static cl_boolean maygc_htentry (const cl_htentry_from_integer_to_rcpointer& entry)
141 if (!entry.key.pointer_p() || (entry.key.heappointer->refcount == 2))
142 if (!entry.val.pointer_p() || (entry.val.heappointer->refcount == 1))
147 static const cl_wht_from_integer_to_rcpointer modint_ring_table = cl_wht_from_integer_to_rcpointer(maygc_htentry);
149 static inline cl_modint_ring* get_modint_ring (const cl_I& m)
151 return (cl_modint_ring*) modint_ring_table.get(m);
154 static inline void store_modint_ring (const cl_modint_ring& R)
156 modint_ring_table.put(R->modulus,R);
160 const cl_modint_ring cl_find_modint_ring (const cl_I& m)
164 var cl_modint_ring* ring_in_table = get_modint_ring(m);
165 if (!ring_in_table) {
166 var cl_modint_ring R = make_modint_ring(m);
167 store_modint_ring(R);
168 ring_in_table = get_modint_ring(m);
172 return *ring_in_table;
176 const cl_modint_ring cl_modint0_ring = cl_find_modint_ring(0);
178 CL_PROVIDE_END(cl_MI)