numerix_doc 0.4
/Users/mourrain/Devel/mmx/numerix/include/numerix/modular.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : modular.hpp
00004 * DESCRIPTION: modular arithmetic
00005 * COPYRIGHT  : (C) 2008  Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX__MODULAR__HPP
00014 #define __MMX__MODULAR__HPP
00015 #include <basix/generic.hpp>
00016 #include <basix/wrap.hpp>
00017 #include <basix/operators.hpp>
00018 #include <basix/int.hpp>
00019 #include <numerix/integer.hpp>
00020 #include <numerix/modulus.hpp>
00021 
00022 namespace mmx {
00023 #define Modular_variant(M) modular_variant_helper<M>::MV
00024 #define TMPL_DEF \
00025   template<typename M, typename V= typename Modular_variant(M)>
00026 #define TMPL template<typename M, typename V>
00027 #define Modulus modulus<C,V>
00028 #define Modular modular<M,V>
00029 
00030 template<typename M>
00031 struct modular_variant_helper;
00032 TMPL class modular;
00033 
00034 /******************************************************************************
00035 * Variant
00036 ******************************************************************************/
00037 
00038 // One modulus is attached to each modular
00039 struct modular_local {
00040   template<typename M>
00041   class modulus_storage {
00042     static inline M& dyn_modulus () {
00043       static M modulus = M ();
00044       return modulus; }
00045   public:
00046     static inline void set_modulus (const M& p) {
00047       if (! is_exact_zero (*p)) dyn_modulus () = p; }
00048     static inline M get_modulus () { return dyn_modulus (); }
00049   };
00050 };
00051 
00052 // Global storage of the modulus
00053 struct modular_global {
00054   template<typename M>
00055   class modulus_storage {
00056     static inline M& dyn_modulus () {
00057       static M modulus = M ();
00058       return modulus; }
00059   public:
00060     static inline void set_modulus (const M& p) { dyn_modulus () = p; }
00061     static inline M get_modulus () { return dyn_modulus (); }
00062   };
00063 };
00064 
00065 // Fixed modulus
00066 template<typename C, C p>
00067 struct modular_fixed {
00068   template<typename M>
00069   class modulus_storage {
00070     static inline M& dyn_modulus () {
00071       static fixed_value <C, p> _p;
00072       static M modulus = M (_p);
00073       return modulus; }
00074   public:
00075     static inline void set_modulus (const M& q) {
00076       ASSERT (q == dyn_modulus (),
00077               "modular_fixed: can not change the modulus");
00078     }
00079     static inline M get_modulus () { return dyn_modulus (); }
00080   };
00081 };
00082 
00083 /******************************************************************************
00084 * Variant helper, default storage of the modulus is "global"
00085 ******************************************************************************/
00086 
00087 template<typename M>
00088 struct modular_variant_helper {
00089   typedef modular_global MV; };
00090 
00091 /******************************************************************************
00092 * General modulars
00093 ******************************************************************************/
00094 
00095 TMPL_DEF
00096 class modular {
00097 MMX_ALLOCATORS
00098 public:
00099   typedef M modulus;
00100   typedef typename M::base C;
00101   typedef typename V::template modulus_storage<M> S;
00102 
00103   C rep;
00104   static inline M get_modulus () { return S::get_modulus (); }
00105   static inline void set_modulus (const M& p) { S::set_modulus (p); }
00106 
00107   inline C operator * () const {
00108     C dest;
00109     decode_mod (dest, rep, get_modulus ());
00110     return dest; }
00111 
00112   inline modular () { encode_mod (rep, C (), get_modulus ()); }
00113 
00114   inline modular (const Modular& s) : rep (s.rep) {}
00115 
00116   inline modular (const C& a, bool reduced) {
00117     if (reduced) rep = a;
00118     else encode_mod (rep, a, get_modulus ()); }
00119 
00120   inline modular (const C& s, const M& p, bool reduced=false) {
00121     VERIFY (p == get_modulus (), "wrong modulus");
00122     if (reduced) rep= s; 
00123     else encode_mod (rep, s, p); }
00124 
00125   template<typename O>
00126   inline modular (const O& a) {
00127     encode_mod (rep, as<C> (a), get_modulus ()); }
00128 
00129   inline Modular& operator = (const Modular& a) {
00130     rep = a.rep;
00131     return *this; }
00132 
00133   inline bool operator == (const Modular& a) const {
00134     return rep == a.rep; }
00135 
00136   inline bool operator != (const Modular& a) const {
00137     return rep != a.rep; }
00138 };
00139 
00140 STYPE_TO_TYPE(TMPL,lift_type,Modular,typename Modular::C);
00141 
00142 TMPL inline typename Modular::C
00143 lift (const Modular& x) { return *x; }
00144 
00145 TMPL
00146 struct project_helper<Modular > {
00147   template<typename C> static inline Modular
00148   op (const C& x) { return Modular (x); }
00149 };
00150 
00151 TMPL inline M get_modulus (const Modular& x) {
00152   (void) x; return Modular::get_modulus (); }
00153 TMPL inline void set_modulus (Modular& x, const M& p) {
00154   (void) x; Modular::set_modulus (p); }
00155 
00156 template<typename TM, typename TV, typename SM, typename SV>
00157 struct as_helper<modular<TM,TV>,modular<SM,SV> > {
00158   static inline modular<TM,TV>
00159   cv (const modular<SM,SV>& p) { return modular<TM,TV> (*p); }
00160 };
00161 
00162 template<typename C, typename V, typename W>
00163 struct as_helper<C,modular<modulus<C,V>,W> > {
00164   static inline C
00165   cv (const modular<modulus<C,V>,W>& p) { return *p; }
00166 };
00167 
00168 template<typename C, typename V, typename W>
00169 struct as_helper<generic, modular<modulus<C,V>,W> > {
00170   static inline generic cv (const modular<modulus<C,V>,W> & x) {
00171     return new generic_concrete_rep<modular<modulus<C,V>,W> > (x); }
00172 };
00173 
00174 WRAP_WRAPPED_IMPL(TMPL inline,Modular)
00175 
00176 /******************************************************************************
00177 * Arithmetic
00178 ******************************************************************************/
00179 
00180 TMPL inline Modular&
00181 operator += (Modular& dest, const Modular& s) {
00182   add_mod (dest.rep, s.rep, Modular::get_modulus ());
00183   return dest; }
00184 
00185 TMPL inline Modular&
00186 operator -= (Modular& dest, const Modular& s) {
00187   sub_mod (dest.rep, s.rep, Modular::get_modulus ());
00188   return dest; }
00189 
00190 TMPL inline Modular&
00191 operator *= (Modular& dest, const Modular& s) {
00192   mul_mod (dest.rep, s.rep, Modular::get_modulus ());
00193   return dest; }
00194 
00195 TMPL inline Modular&
00196 operator /= (Modular& dest, const Modular& s) {
00197   div_mod (dest.rep, s.rep, Modular::get_modulus ());
00198   return dest; }
00199 
00200 TMPL inline Modular
00201 operator + (const Modular& a, const Modular& b) {
00202   Modular c;
00203   add_mod (c.rep, a.rep, b.rep, Modular::get_modulus ());
00204   return c; }
00205 
00206 TMPL inline Modular
00207 operator + (const Modular& a, const typename M::base& b) {
00208   return a + Modular (b); }
00209 
00210 TMPL inline Modular
00211 operator + (const typename M::base& a, const Modular& b) {
00212   return Modular (a) + b; }
00213 
00214 TMPL inline Modular
00215 operator - (const Modular& a) {
00216   Modular c;
00217   neg_mod (c.rep, a.rep, Modular::get_modulus ());
00218   return c; }
00219 
00220 TMPL inline Modular
00221 operator - (const Modular& a, const Modular& b) {
00222   Modular c;
00223   sub_mod (c.rep, a.rep, b.rep, Modular::get_modulus ());
00224   return c; }
00225 
00226 TMPL inline Modular
00227 operator - (const Modular& a, const typename M::base& b) {
00228   return a - Modular (b); }
00229 
00230 TMPL inline Modular
00231 operator - (const typename M::base& a, const Modular& b) {
00232   return Modular (a) - b; }
00233 
00234 TMPL inline Modular
00235 operator * (const Modular& a, const Modular& b) {
00236   Modular c;
00237   mul_mod (c.rep, a.rep, b.rep, Modular::get_modulus ());
00238   return c; }
00239 
00240 TMPL inline Modular
00241 operator * (const Modular& a, const typename M::base& b) {
00242   return a * Modular (b); }
00243 
00244 TMPL inline Modular
00245 operator * (const typename M::base& a, const Modular& b) {
00246   return Modular (a) * b; }
00247 
00248 TMPL inline Modular
00249 operator / (const Modular& a, const Modular& b) {
00250   Modular c;
00251   div_mod (c.rep, a.rep, b.rep, Modular::get_modulus ());
00252   return c; }
00253 
00254 TMPL inline Modular
00255 operator / (const Modular& a, const typename M::base& b) {
00256   return a / Modular (b); }
00257 
00258 TMPL inline Modular
00259 operator / (const typename M::base& a, const Modular& b) {
00260   return Modular (a) / b; }
00261 
00262 TMPL inline Modular
00263 invert (const Modular& a) {
00264   Modular c;
00265   inv_mod (c.rep, a.rep, Modular::get_modulus ());
00266   return c; }
00267 
00268 /******************************************************************************
00269 * Gcd & lcm routine
00270 ******************************************************************************/
00271 
00272 TMPL inline Modular
00273 gcd (const Modular& a, const Modular& b) {
00274   if (a == 0) return b;
00275   return a; }
00276 
00277 TMPL inline Modular
00278 lcm (const Modular& a, const Modular& b) {
00279   return a * b; }
00280 
00281 /******************************************************************************
00282 * Output routine
00283 ******************************************************************************/
00284 
00285 WRAP_PRINT_IMPL(TMPL inline,Modular)
00286 
00287 /******************************************************************************
00288 * Syntactic sugar
00289 ******************************************************************************/
00290 
00291 ARITH_INT_SUGAR(TMPL,Modular)
00292 POOR_MAN_SQRT_SUGAR(TMPL,Modular)
00293 POOR_MAN_ELEMENTARY_SUGAR(TMPL,Modular)
00294 
00295 #undef TMPL_DEF
00296 #undef TMPL
00297 #undef Modulus
00298 #undef Modular
00299 
00300 /******************************************************************************
00301 * Modulars with local moduli
00302 ******************************************************************************/
00303 
00304 #define TMPL template<typename M>
00305 #define Modulus modulus<C,V>
00306 #define Modular modular<M,modular_local>
00307 
00308 TMPL
00309 class modular<M, modular_local> {
00310 MMX_ALLOCATORS
00311 public:
00312   typedef M modulus;
00313   typedef modular_local V;
00314   typedef typename M::base C;
00315   typedef typename V::template modulus_storage<M> S;
00316 
00317   C rep;
00318   M mod;
00319   static inline M get_modulus () { return S::get_modulus (); }
00320   static inline void set_modulus (const M& p) { S::set_modulus (p); }
00321 
00322   inline M get_local_modulus () const { return mod; }
00323   inline void set_local_modulus (const M& p) { mod= p; S::set_modulus (p); }
00324 
00325   inline C operator * () const {
00326     C dest;
00327     decode_mod (dest, rep, mod);
00328     return dest; }
00329 
00330   inline modular () {
00331     mod= get_modulus ();
00332     encode_mod (rep, C (), mod); }
00333 
00334   inline modular (const Modular& s) : rep (s.rep), mod (s.mod) {}
00335 
00336   inline modular (const C& s, bool reduced) {
00337     mod= get_modulus ();
00338     if (reduced) rep= s;
00339     else encode_mod (rep, s, mod); }
00340 
00341   inline modular (const C& s, const M& p, bool reduced=false) {
00342     mod= p;
00343     set_modulus (p);
00344     if (reduced) rep= s; 
00345     else encode_mod (rep, s, mod); }
00346 
00347   template<typename O>
00348   inline modular (const O& a) {
00349     mod= get_modulus ();
00350     encode_mod (rep, as<C> (a), mod); }
00351 
00352   inline Modular& operator = (const Modular& a) {
00353     rep = a.rep;
00354     mod = a.mod;
00355     return *this; }
00356 
00357   inline bool operator == (const Modular& a) const {
00358     if (mod   == a.mod) return rep == a.rep;
00359     if (mod   == C(0))  return Modular (* (*this), a.mod) == a;
00360     if (a.mod == C(0))  return Modular (* a, mod) == *this;
00361     return false; }
00362 
00363   inline bool operator != (const Modular& a) const {
00364     if (mod   == a.mod) return rep != a.rep;
00365     if (mod   == C(0))  return Modular (* (*this), a.mod) != a;
00366     if (a.mod == C(0))  return Modular (* a, mod) != *this;
00367     return true; }
00368 };
00369 
00370 template<typename M> inline M
00371 get_modulus (const modular<M, modular_local>& x) {
00372   return x.get_local_modulus (); }
00373 
00374 template<typename M> inline void
00375 set_modulus (Modular& x, const M& p) {
00376   x.set_local_modulus (p); }
00377 
00378 template<typename TM, typename SM, typename SV>
00379 struct as_helper<modular<TM,modular_local>,modular<SM,SV> > {
00380   static inline modular<TM,modular_local>
00381   cv (const modular<SM,SV>& p) {
00382     return modular<TM,modular_local> (* p, get_modulus (p)); }
00383 };
00384 
00385 TMPL nat 
00386 hash (const Modular& c) {
00387   nat h= hash (*c);
00388   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hash (get_modulus (c)); }
00389 
00390 TMPL nat
00391 exact_hash (const Modular& c) {
00392   nat h= exact_hash (*c);
00393   return (h<<1) ^ (h<<5) ^ (h>>29) ^ exact_hash (get_modulus (c)); }
00394 
00395 TMPL nat hard_hash (const Modular& c) {
00396   nat h= hard_hash (*c);
00397   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hard_hash (get_modulus (c)); }
00398 
00399 TMPL bool exact_eq (const Modular& c1, const Modular& c2) {
00400   return exact_eq (*c1, *c2) && 
00401          exact_eq (get_modulus (c1), get_modulus (c2)); }
00402 
00403 TMPL bool exact_neq (const Modular& c1, const Modular& c2) {
00404   return ! exact_eq (c1, c2); }
00405 
00406 TMPL bool hard_eq (const Modular& c1, const Modular& c2) {
00407   return hard_eq (*c1, *c2) && 
00408          hard_eq (get_modulus (c1), get_modulus (c2)); }
00409 
00410 TMPL bool hard_neq (const Modular& c1, const Modular& c2) {
00411   return ! hard_eq (c1, c2); }
00412 
00413 TMPL inline Modular&
00414 operator += (Modular& dest, const Modular& s) {
00415   M md= get_modulus (dest), ms= get_modulus (s);
00416   M mod= md == 0 ? ms : md;
00417   VERIFY (md == 0 || ms == 0 || md == ms, "incompatible moduli");
00418   add_mod (dest.rep, s.rep, mod);
00419   return dest; }
00420 
00421 TMPL inline Modular&
00422 operator -= (Modular& dest, const Modular& s) {
00423   M md= get_modulus (dest), ms= get_modulus (s);
00424   M mod= md == 0 ? ms : md;
00425   VERIFY (md == 0 || ms == 0 || md == ms, "incompatible moduli");
00426   sub_mod (dest.rep, s.rep, mod);
00427   return dest; }
00428 
00429 TMPL inline Modular&
00430 operator *= (Modular& dest, const Modular& s) {
00431   M md= get_modulus (dest), ms= get_modulus (s);
00432   M mod= md == 0 ? ms : md;
00433   VERIFY (md == 0 || ms == 0 || md == ms, "incompatible moduli");
00434   mul_mod (dest.rep, s.rep, mod);
00435   return dest; }
00436 
00437 TMPL inline Modular&
00438 operator /= (Modular& dest, const Modular& s) {
00439   M md= get_modulus (dest), ms= get_modulus (s);
00440   M mod= md == 0 ? ms : md;
00441   VERIFY (md == 0 || ms == 0 || md == ms, "incompatible moduli");
00442   div_mod (dest.rep, s.rep, mod);
00443   return dest; }
00444 
00445 TMPL inline Modular
00446 operator + (const Modular& a, const Modular& b) {
00447   M ma= get_modulus (a), mb= get_modulus (b);
00448   M mod= ma == 0 ? mb : ma;
00449   VERIFY (ma == 0 || mb == 0 || ma == mb, "incompatible moduli");
00450   Modular c;
00451   add_mod (c.rep, a.rep, b.rep, mod);
00452   c.mod= mod;
00453   return c; }
00454 
00455 TMPL inline Modular
00456 operator - (const Modular& a) {
00457   M mod= get_modulus (a);
00458   Modular c;
00459   neg_mod (c.rep, a.rep, mod);
00460   c.mod= mod;
00461   return c; }
00462 
00463 TMPL inline Modular
00464 operator - (const Modular& a, const Modular& b) {
00465   M ma= get_modulus (a), mb= get_modulus (b);
00466   M mod= ma == 0 ? mb : ma;
00467   VERIFY (ma == 0 || mb == 0 || ma == mb, "incompatible moduli");
00468   Modular c;
00469   sub_mod (c.rep, a.rep, b.rep, mod);
00470   c.mod= mod;
00471   return c; }
00472 
00473 TMPL inline Modular
00474 operator * (const Modular& a, const Modular& b) {
00475   M ma= get_modulus (a), mb= get_modulus (b);
00476   M mod= ma == 0 ? mb : ma;
00477   VERIFY (ma == 0 || mb == 0 || ma == mb, "incompatible moduli");
00478   Modular c;
00479   mul_mod (c.rep, a.rep, b.rep, mod);
00480   c.mod= mod;
00481   return c; }
00482 
00483 TMPL inline Modular
00484 operator / (const Modular& a, const Modular& b) {
00485   M ma= get_modulus (a), mb= get_modulus (b);
00486   M mod= ma == 0 ? mb : ma;
00487   VERIFY (ma == 0 || mb == 0 || ma == mb, "incompatible moduli");
00488   Modular c;
00489   div_mod (c.rep, a.rep, b.rep, mod);
00490   c.mod= mod;
00491   return c; }
00492 
00493 TMPL inline Modular
00494 invert (const Modular& a) {
00495   M mod= get_modulus (a);
00496   Modular c;
00497   inv_mod (c.rep, a.rep, mod);
00498   c.mod= mod;
00499   return c; }
00500 
00501 /******************************************************************************
00502 * Extras for glue
00503 ******************************************************************************/
00504 
00505 #define mmx_modular(R) modular<modulus<R >,modular_local>
00506 
00507 #undef TMPL
00508 #undef Modulus
00509 #undef Modular
00510 } // namespace mmx
00511 #endif //__MMX__MODULAR__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines