You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
15 KiB

25 years ago
  1. // Modular integer operations.
  2. #ifndef _CL_MODINTEGER_H
  3. #define _CL_MODINTEGER_H
  4. #include "cl_object.h"
  5. #include "cl_ring.h"
  6. #include "cl_integer.h"
  7. #include "cl_random.h"
  8. #include "cl_malloc.h"
  9. #include "cl_io.h"
  10. #include "cl_proplist.h"
  11. #include "cl_condition.h"
  12. #include "cl_abort.h"
  13. #undef random // Linux defines random() as a macro!
  14. // Representation of an element of a ring Z/mZ.
  15. // To protect against mixing elements of different modular rings, such as
  16. // (3 mod 4) + (2 mod 5), every modular integer carries its ring in itself.
  17. // Representation of a ring Z/mZ.
  18. class cl_heap_modint_ring;
  19. class cl_modint_ring : public cl_ring {
  20. public:
  21. // Default constructor.
  22. cl_modint_ring ();
  23. // Constructor. Takes a cl_heap_modint_ring*, increments its refcount.
  24. cl_modint_ring (cl_heap_modint_ring* r);
  25. // Copy constructor.
  26. cl_modint_ring (const cl_modint_ring&);
  27. // Assignment operator.
  28. cl_modint_ring& operator= (const cl_modint_ring&);
  29. // Automatic dereferencing.
  30. cl_heap_modint_ring* operator-> () const
  31. { return (cl_heap_modint_ring*)heappointer; }
  32. };
  33. // Z/0Z
  34. extern const cl_modint_ring cl_modint0_ring;
  35. // Default constructor. This avoids dealing with NULL pointers.
  36. inline cl_modint_ring::cl_modint_ring ()
  37. : cl_ring (as_cl_private_thing(cl_modint0_ring)) {}
  38. CL_REQUIRE(cl_MI)
  39. // Copy constructor and assignment operator.
  40. CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring)
  41. CL_DEFINE_ASSIGNMENT_OPERATOR(cl_modint_ring,cl_modint_ring)
  42. // Normal constructor for `cl_modint_ring'.
  43. inline cl_modint_ring::cl_modint_ring (cl_heap_modint_ring* r)
  44. : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount((cl_heap*)r), r)) {}
  45. // Operations on modular integer rings.
  46. inline bool operator== (const cl_modint_ring& R1, const cl_modint_ring& R2)
  47. { return (R1.pointer == R2.pointer); }
  48. inline bool operator!= (const cl_modint_ring& R1, const cl_modint_ring& R2)
  49. { return (R1.pointer != R2.pointer); }
  50. inline bool operator== (const cl_modint_ring& R1, cl_heap_modint_ring* R2)
  51. { return (R1.pointer == R2); }
  52. inline bool operator!= (const cl_modint_ring& R1, cl_heap_modint_ring* R2)
  53. { return (R1.pointer != R2); }
  54. // Condition raised when a probable prime is discovered to be composite.
  55. struct cl_composite_condition : public cl_condition {
  56. SUBCLASS_cl_condition()
  57. cl_I p; // the non-prime
  58. cl_I factor; // a nontrivial factor, or 0
  59. // Constructors.
  60. cl_composite_condition (const cl_I& _p)
  61. : p (_p), factor (0)
  62. { print(cl_stderr); }
  63. cl_composite_condition (const cl_I& _p, const cl_I& _f)
  64. : p (_p), factor (_f)
  65. { print(cl_stderr); }
  66. // Implement general condition methods.
  67. const char * name () const;
  68. void print (cl_ostream) const;
  69. ~cl_composite_condition () {}
  70. };
  71. // Representation of an element of a ring Z/mZ.
  72. class _cl_MI /* cf. _cl_ring_element */ {
  73. public:
  74. cl_I rep; // representative, integer >=0, <m
  75. // (maybe the Montgomery representative!)
  76. // Default constructor.
  77. _cl_MI () : rep () {}
  78. public: /* ugh */
  79. // Constructor.
  80. _cl_MI (const cl_heap_modint_ring* R, const cl_I& r) : rep (r) { (void)R; }
  81. _cl_MI (const cl_modint_ring& R, const cl_I& r) : rep (r) { (void)R; }
  82. public:
  83. // Conversion.
  84. CL_DEFINE_CONVERTER(_cl_ring_element)
  85. public: // Ability to place an object at a given address.
  86. void* operator new (size_t size) { return cl_malloc_hook(size); }
  87. void* operator new (size_t size, _cl_MI* ptr) { (void)size; return ptr; }
  88. void operator delete (void* ptr) { cl_free_hook(ptr); }
  89. };
  90. class cl_MI /* cf. cl_ring_element */ : public _cl_MI {
  91. protected:
  92. cl_modint_ring _ring; // ring Z/mZ
  93. public:
  94. const cl_modint_ring& ring () const { return _ring; }
  95. // Default constructor.
  96. cl_MI () : _cl_MI (), _ring () {}
  97. public: /* ugh */
  98. // Constructor.
  99. cl_MI (const cl_modint_ring& R, const cl_I& r) : _cl_MI (R,r), _ring (R) {}
  100. cl_MI (const cl_modint_ring& R, const _cl_MI& r) : _cl_MI (r), _ring (R) {}
  101. public:
  102. // Conversion.
  103. CL_DEFINE_CONVERTER(cl_ring_element)
  104. // Debugging output.
  105. void debug_print () const;
  106. public: // Ability to place an object at a given address.
  107. void* operator new (size_t size) { return cl_malloc_hook(size); }
  108. void* operator new (size_t size, cl_MI* ptr) { (void)size; return ptr; }
  109. void operator delete (void* ptr) { cl_free_hook(ptr); }
  110. };
  111. // Representation of an element of a ring Z/mZ or an exception.
  112. class cl_MI_x {
  113. private:
  114. cl_MI value;
  115. public:
  116. cl_composite_condition* condition;
  117. // Constructors.
  118. cl_MI_x (cl_composite_condition* c) : value (), condition (c) {}
  119. cl_MI_x (const cl_MI& x) : value (x), condition (NULL) {}
  120. // Cast operators.
  121. //operator cl_MI& () { if (condition) cl_abort(); return value; }
  122. //operator const cl_MI& () const { if (condition) cl_abort(); return value; }
  123. operator cl_MI () const { if (condition) cl_abort(); return value; }
  124. };
  125. // Ring operations.
  126. struct _cl_modint_setops /* cf. _cl_ring_setops */ {
  127. // print
  128. void (* fprint) (cl_heap_modint_ring* R, cl_ostream stream, const _cl_MI& x);
  129. // equality
  130. cl_boolean (* equal) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y);
  131. // random number
  132. const _cl_MI (* random) (cl_heap_modint_ring* R, cl_random_state& randomstate);
  133. };
  134. struct _cl_modint_addops /* cf. _cl_ring_addops */ {
  135. // 0
  136. const _cl_MI (* zero) (cl_heap_modint_ring* R);
  137. cl_boolean (* zerop) (cl_heap_modint_ring* R, const _cl_MI& x);
  138. // x+y
  139. const _cl_MI (* plus) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y);
  140. // x-y
  141. const _cl_MI (* minus) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y);
  142. // -x
  143. const _cl_MI (* uminus) (cl_heap_modint_ring* R, const _cl_MI& x);
  144. };
  145. struct _cl_modint_mulops /* cf. _cl_ring_mulops */ {
  146. // 1
  147. const _cl_MI (* one) (cl_heap_modint_ring* R);
  148. // canonical homomorphism
  149. const _cl_MI (* canonhom) (cl_heap_modint_ring* R, const cl_I& x);
  150. // x*y
  151. const _cl_MI (* mul) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y);
  152. // x^2
  153. const _cl_MI (* square) (cl_heap_modint_ring* R, const _cl_MI& x);
  154. // x^y, y Integer >0
  155. const _cl_MI (* expt_pos) (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y);
  156. // x^-1
  157. const cl_MI_x (* recip) (cl_heap_modint_ring* R, const _cl_MI& x);
  158. // x*y^-1
  159. const cl_MI_x (* div) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y);
  160. // x^y, y Integer
  161. const cl_MI_x (* expt) (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y);
  162. // x -> x mod m for x>=0
  163. const cl_I (* reduce_modulo) (cl_heap_modint_ring* R, const cl_I& x);
  164. // some inverse of canonical homomorphism
  165. const cl_I (* retract) (cl_heap_modint_ring* R, const _cl_MI& x);
  166. };
  167. #if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8) // workaround two g++-2.7.0 bugs
  168. #define cl_modint_setops _cl_modint_setops
  169. #define cl_modint_addops _cl_modint_addops
  170. #define cl_modint_mulops _cl_modint_mulops
  171. #else
  172. typedef const _cl_modint_setops cl_modint_setops;
  173. typedef const _cl_modint_addops cl_modint_addops;
  174. typedef const _cl_modint_mulops cl_modint_mulops;
  175. #endif
  176. // Representation of the ring Z/mZ.
  177. // Currently rings are garbage collected only when they are not referenced
  178. // any more and when the ring table gets full.
  179. // Modular integer rings are kept unique in memory. This way, ring equality
  180. // can be checked very efficiently by a simple pointer comparison.
  181. class cl_heap_modint_ring /* cf. cl_heap_ring */ : public cl_heap {
  182. SUBCLASS_cl_heap_ring()
  183. private:
  184. cl_property_list properties;
  185. protected:
  186. cl_modint_setops* setops;
  187. cl_modint_addops* addops;
  188. cl_modint_mulops* mulops;
  189. public:
  190. cl_I modulus; // m, normalized to be >= 0
  191. public:
  192. // Low-level operations.
  193. void _fprint (cl_ostream stream, const _cl_MI& x)
  194. { setops->fprint(this,stream,x); }
  195. cl_boolean _equal (const _cl_MI& x, const _cl_MI& y)
  196. { return setops->equal(this,x,y); }
  197. const _cl_MI _random (cl_random_state& randomstate)
  198. { return setops->random(this,randomstate); }
  199. const _cl_MI _zero ()
  200. { return addops->zero(this); }
  201. cl_boolean _zerop (const _cl_MI& x)
  202. { return addops->zerop(this,x); }
  203. const _cl_MI _plus (const _cl_MI& x, const _cl_MI& y)
  204. { return addops->plus(this,x,y); }
  205. const _cl_MI _minus (const _cl_MI& x, const _cl_MI& y)
  206. { return addops->minus(this,x,y); }
  207. const _cl_MI _uminus (const _cl_MI& x)
  208. { return addops->uminus(this,x); }
  209. const _cl_MI _one ()
  210. { return mulops->one(this); }
  211. const _cl_MI _canonhom (const cl_I& x)
  212. { return mulops->canonhom(this,x); }
  213. const _cl_MI _mul (const _cl_MI& x, const _cl_MI& y)
  214. { return mulops->mul(this,x,y); }
  215. const _cl_MI _square (const _cl_MI& x)
  216. { return mulops->square(this,x); }
  217. const _cl_MI _expt_pos (const _cl_MI& x, const cl_I& y)
  218. { return mulops->expt_pos(this,x,y); }
  219. const cl_MI_x _recip (const _cl_MI& x)
  220. { return mulops->recip(this,x); }
  221. const cl_MI_x _div (const _cl_MI& x, const _cl_MI& y)
  222. { return mulops->div(this,x,y); }
  223. const cl_MI_x _expt (const _cl_MI& x, const cl_I& y)
  224. { return mulops->expt(this,x,y); }
  225. const cl_I _reduce_modulo (const cl_I& x)
  226. { return mulops->reduce_modulo(this,x); }
  227. const cl_I _retract (const _cl_MI& x)
  228. { return mulops->retract(this,x); }
  229. // High-level operations.
  230. void fprint (cl_ostream stream, const cl_MI& x)
  231. {
  232. if (!(x.ring() == this)) cl_abort();
  233. _fprint(stream,x);
  234. }
  235. cl_boolean equal (const cl_MI& x, const cl_MI& y)
  236. {
  237. if (!(x.ring() == this)) cl_abort();
  238. if (!(y.ring() == this)) cl_abort();
  239. return _equal(x,y);
  240. }
  241. const cl_MI random (cl_random_state& randomstate = cl_default_random_state)
  242. {
  243. return cl_MI(this,_random(randomstate));
  244. }
  245. const cl_MI zero ()
  246. {
  247. return cl_MI(this,_zero());
  248. }
  249. cl_boolean zerop (const cl_MI& x)
  250. {
  251. if (!(x.ring() == this)) cl_abort();
  252. return _zerop(x);
  253. }
  254. const cl_MI plus (const cl_MI& x, const cl_MI& y)
  255. {
  256. if (!(x.ring() == this)) cl_abort();
  257. if (!(y.ring() == this)) cl_abort();
  258. return cl_MI(this,_plus(x,y));
  259. }
  260. const cl_MI minus (const cl_MI& x, const cl_MI& y)
  261. {
  262. if (!(x.ring() == this)) cl_abort();
  263. if (!(y.ring() == this)) cl_abort();
  264. return cl_MI(this,_minus(x,y));
  265. }
  266. const cl_MI uminus (const cl_MI& x)
  267. {
  268. if (!(x.ring() == this)) cl_abort();
  269. return cl_MI(this,_uminus(x));
  270. }
  271. const cl_MI one ()
  272. {
  273. return cl_MI(this,_one());
  274. }
  275. const cl_MI canonhom (const cl_I& x)
  276. {
  277. return cl_MI(this,_canonhom(x));
  278. }
  279. const cl_MI mul (const cl_MI& x, const cl_MI& y)
  280. {
  281. if (!(x.ring() == this)) cl_abort();
  282. if (!(y.ring() == this)) cl_abort();
  283. return cl_MI(this,_mul(x,y));
  284. }
  285. const cl_MI square (const cl_MI& x)
  286. {
  287. if (!(x.ring() == this)) cl_abort();
  288. return cl_MI(this,_square(x));
  289. }
  290. const cl_MI expt_pos (const cl_MI& x, const cl_I& y)
  291. {
  292. if (!(x.ring() == this)) cl_abort();
  293. return cl_MI(this,_expt_pos(x,y));
  294. }
  295. const cl_MI_x recip (const cl_MI& x)
  296. {
  297. if (!(x.ring() == this)) cl_abort();
  298. return _recip(x);
  299. }
  300. const cl_MI_x div (const cl_MI& x, const cl_MI& y)
  301. {
  302. if (!(x.ring() == this)) cl_abort();
  303. if (!(y.ring() == this)) cl_abort();
  304. return _div(x,y);
  305. }
  306. const cl_MI_x expt (const cl_MI& x, const cl_I& y)
  307. {
  308. if (!(x.ring() == this)) cl_abort();
  309. return _expt(x,y);
  310. }
  311. const cl_I reduce_modulo (const cl_I& x)
  312. {
  313. return _reduce_modulo(x);
  314. }
  315. const cl_I retract (const cl_MI& x)
  316. {
  317. if (!(x.ring() == this)) cl_abort();
  318. return _retract(x);
  319. }
  320. // Miscellaneous.
  321. sintL bits; // number of bits needed to represent a representative, or -1
  322. int log2_bits; // log_2(bits), or -1
  323. // Property operations.
  324. cl_property* get_property (const cl_symbol& key)
  325. { return properties.get_property(key); }
  326. void add_property (cl_property* new_property)
  327. { properties.add_property(new_property); }
  328. // Constructor.
  329. cl_heap_modint_ring (cl_I m, cl_modint_setops*, cl_modint_addops*, cl_modint_mulops*);
  330. // This class is intented to be subclassable, hence needs a virtual destructor.
  331. virtual ~cl_heap_modint_ring () {}
  332. private:
  333. virtual void dummy ();
  334. };
  335. #define SUBCLASS_cl_heap_modint_ring() \
  336. SUBCLASS_cl_heap_ring()
  337. // Lookup or create a modular integer ring Z/mZ
  338. extern const cl_modint_ring cl_find_modint_ring (const cl_I& m);
  339. CL_REQUIRE(cl_MI)
  340. // Runtime typing support.
  341. extern cl_class cl_class_modint_ring;
  342. // Operations on modular integers.
  343. // Output.
  344. inline void fprint (cl_ostream stream, const cl_MI& x)
  345. { x.ring()->fprint(stream,x); }
  346. CL_DEFINE_PRINT_OPERATOR(cl_MI)
  347. // Add.
  348. inline const cl_MI operator+ (const cl_MI& x, const cl_MI& y)
  349. { return x.ring()->plus(x,y); }
  350. inline const cl_MI operator+ (const cl_MI& x, const cl_I& y)
  351. { return x.ring()->plus(x,x.ring()->canonhom(y)); }
  352. inline const cl_MI operator+ (const cl_I& x, const cl_MI& y)
  353. { return y.ring()->plus(y.ring()->canonhom(x),y); }
  354. // Negate.
  355. inline const cl_MI operator- (const cl_MI& x)
  356. { return x.ring()->uminus(x); }
  357. // Subtract.
  358. inline const cl_MI operator- (const cl_MI& x, const cl_MI& y)
  359. { return x.ring()->minus(x,y); }
  360. inline const cl_MI operator- (const cl_MI& x, const cl_I& y)
  361. { return x.ring()->minus(x,x.ring()->canonhom(y)); }
  362. inline const cl_MI operator- (const cl_I& x, const cl_MI& y)
  363. { return y.ring()->minus(y.ring()->canonhom(x),y); }
  364. // Shifts.
  365. extern const cl_MI operator<< (const cl_MI& x, sintL y); // assume 0 <= y < 2^31
  366. extern const cl_MI operator>> (const cl_MI& x, sintL y); // assume m odd, 0 <= y < 2^31
  367. // Equality.
  368. inline bool operator== (const cl_MI& x, const cl_MI& y)
  369. { return x.ring()->equal(x,y); }
  370. inline bool operator!= (const cl_MI& x, const cl_MI& y)
  371. { return !x.ring()->equal(x,y); }
  372. inline bool operator== (const cl_MI& x, const cl_I& y)
  373. { return x.ring()->equal(x,x.ring()->canonhom(y)); }
  374. inline bool operator!= (const cl_MI& x, const cl_I& y)
  375. { return !x.ring()->equal(x,x.ring()->canonhom(y)); }
  376. inline bool operator== (const cl_I& x, const cl_MI& y)
  377. { return y.ring()->equal(y.ring()->canonhom(x),y); }
  378. inline bool operator!= (const cl_I& x, const cl_MI& y)
  379. { return !y.ring()->equal(y.ring()->canonhom(x),y); }
  380. // Compare against 0.
  381. inline cl_boolean zerop (const cl_MI& x)
  382. { return x.ring()->zerop(x); }
  383. // Multiply.
  384. inline const cl_MI operator* (const cl_MI& x, const cl_MI& y)
  385. { return x.ring()->mul(x,y); }
  386. // Squaring.
  387. inline const cl_MI square (const cl_MI& x)
  388. { return x.ring()->square(x); }
  389. // Exponentiation x^y, where y > 0.
  390. inline const cl_MI expt_pos (const cl_MI& x, const cl_I& y)
  391. { return x.ring()->expt_pos(x,y); }
  392. // Reciprocal.
  393. inline const cl_MI recip (const cl_MI& x)
  394. { return x.ring()->recip(x); }
  395. // Division.
  396. inline const cl_MI div (const cl_MI& x, const cl_MI& y)
  397. { return x.ring()->div(x,y); }
  398. inline const cl_MI div (const cl_MI& x, const cl_I& y)
  399. { return x.ring()->div(x,x.ring()->canonhom(y)); }
  400. inline const cl_MI div (const cl_I& x, const cl_MI& y)
  401. { return y.ring()->div(y.ring()->canonhom(x),y); }
  402. // Exponentiation x^y.
  403. inline const cl_MI expt (const cl_MI& x, const cl_I& y)
  404. { return x.ring()->expt(x,y); }
  405. // Scalar multiplication.
  406. inline const cl_MI operator* (const cl_I& x, const cl_MI& y)
  407. { return y.ring()->mul(y.ring()->canonhom(x),y); }
  408. inline const cl_MI operator* (const cl_MI& x, const cl_I& y)
  409. { return x.ring()->mul(x.ring()->canonhom(y),x); }
  410. // TODO: implement gcd, index (= gcd), unitp, sqrtp
  411. // Debugging support.
  412. #ifdef CL_DEBUG
  413. extern int cl_MI_debug_module;
  414. static void* const cl_MI_debug_dummy[] = { &cl_MI_debug_dummy,
  415. &cl_MI_debug_module
  416. };
  417. #endif
  418. #endif /* _CL_MODINTEGER_H */