numerix_doc 0.4
/Users/mourrain/Devel/mmx/numerix/include/numerix/modular_integer.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : modular_integer.hpp
00004 * DESCRIPTION: modulus for modular arithmetic over integers
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_INTEGER__HPP
00014 #define __MMX__MODULAR_INTEGER__HPP
00015 #include <numerix/integer.hpp>
00016 #include <numerix/modular.hpp>
00017 #include <numerix/modular_int.hpp>
00018 
00019 namespace mmx {
00020 
00021 #define TMPL template<typename C, typename M>
00022 
00023 /******************************************************************************
00024 * Naive implementation relying on direct division
00025 ******************************************************************************/
00026 // The modulus 'p' is always taken to be positive
00027 // The modulars are in the range [0, p-1]
00028 
00029 struct modulus_normalization_integer_naive {
00030 
00031   template<typename C> static inline bool
00032   normalize (C& p) {
00033     if (p < 0) p = -p;
00034     return true;
00035   }
00036 };
00037 
00038 template<typename V>
00039 struct modulus_add_integer_naive : public V {
00040 
00041   TMPL static inline void
00042   neg_mod (C& dest, const M& m) {
00043     if (dest != 0) dest = m.p - dest; }
00044 
00045   TMPL static inline void
00046   neg_mod (C& dest, const M& m, C& carry) {
00047     VERIFY (carry == 0 || carry == 1, "unexpected large carry");
00048     if (dest != 0 || carry != 0) { dest= m.p - dest - carry; carry= 1; } }
00049 
00050   TMPL static inline void
00051   neg_mod (C& dest, const C& s, const M& m) {
00052     if (s != 0) dest = m.p - s; else dest = s;
00053  }
00054 
00055   TMPL static inline void
00056   neg_mod (C& dest, const C& s, const M& m, C& carry) {
00057     VERIFY (carry == 0 || carry == 1, "unexpected large carry");
00058     if (s != 0 || carry != 0) { dest= m.p - s - carry; carry= 1; }
00059     else dest= 0; }
00060 
00061   TMPL static inline void
00062   add_mod (C& dest, const C& s, const M& m) {
00063     dest += s;
00064     if (dest >= m.p) dest -= m.p; }
00065 
00066   TMPL static inline void
00067   add_mod (C& dest, const C& s, const M& m, C& carry) {
00068     VERIFY (carry == 0 || carry == 1, "unexpected large carry");
00069     dest += s + carry;
00070     if (dest >= m.p) { dest -= m.p; carry= 1; } else carry= 0; }
00071 
00072   TMPL static inline void
00073   add_mod (C& dest, const C& s1, const C& s2, const M& m) {
00074     dest = s1;
00075     add_mod (dest, s2, m); }
00076   
00077   TMPL static inline void
00078   add_mod (C& dest, const C& s1, const C& s2, const M& m, C& carry) {
00079     dest = s1;
00080     add_mod (dest, s2, m, carry); }
00081   
00082   template<typename C> static inline void
00083   sub_mod_core (C& dest, const C& s, const C& p) {
00084     if (dest < s) dest += p;
00085     dest -= s; }
00086 
00087   template<typename C> static inline void
00088   sub_mod_core (C& dest, const C& s, const C& p, C& carry) {
00089     VERIFY (carry == 0 || carry == 1, "unexpected large carry");
00090     C t = s + carry;
00091     if (t == p || dest < t) { dest += p; carry= 1; } else carry= 0;
00092     dest -= t; }
00093 
00094   TMPL static inline void
00095   sub_mod (C& dest, const C& s, const M& m) {
00096     sub_mod_core (dest, s, m.p); }
00097 
00098   TMPL static inline void
00099   sub_mod (C& dest, const C& s, const M& m, C& carry) {
00100     sub_mod_core (dest, s, m.p, carry); }
00101 
00102   TMPL static inline void
00103   sub_mod (C& dest, const C& s1, const C& s2, const M& m) {
00104     dest = s1;
00105     sub_mod (dest, s2, m); }
00106 
00107   TMPL static inline void
00108   sub_mod (C& dest, const C& s1, const C& s2, const M& m, C& carry) {
00109     dest = s1;
00110     sub_mod (dest, s2, m, carry); }
00111 };
00112 
00113 template<typename V>
00114 struct modulus_inv_integer_naive : public V {
00115 
00116   TMPL static inline void
00117   inv_mod (C& a, const M& m) {
00118     if (m.p == 0) {
00119       if (a == 1 || a == -1)
00120         return;
00121       else
00122         ERROR ("inv_mod: argument is not invertible");  
00123     }
00124     a = invert_modulo (a, m.p);
00125     if (a == 0 && m.p != 1)
00126       ERROR ("inv_mod: argument is not invertible"); }
00127 
00128   TMPL static inline void
00129   inv_mod (C& dest, const C& s, const M& m) {
00130     dest = s;
00131     inv_mod (dest, m); }
00132 };
00133 
00134 template<typename V>
00135 struct modulus_encoding_integer_naive : public V {
00136   TMPL static inline void 
00137   encode_mod (C& dest, const C& s, const M& m) {
00138     if (s < 0 && m.p != 0) {
00139       dest = - s;
00140       V::reduce_mod (dest, m);
00141       dest = m.p - dest;
00142     }
00143     else
00144       dest = s;
00145       V::reduce_mod (dest, m);
00146   }
00147   TMPL static inline void 
00148   decode_mod (C& dest, const C& s, const M& m) {
00149     (void) m;
00150     dest = s; }
00151 };
00152 
00153 struct modulus_integer_naive:
00154   public modulus_encoding_integer_naive<
00155          modulus_div_naive<
00156          modulus_inv_integer_naive<
00157          modulus_mul_naive<
00158          modulus_add_integer_naive<
00159          modulus_reduction_naive<
00160          modulus_normalization_integer_naive> > > > > > {};
00161 
00162 /******************************************************************************
00163 * Helpers specializations for hardware integers
00164 ******************************************************************************/
00165 
00166 template<>
00167 struct modulus_variant_helper<integer> {
00168   typedef modulus_integer_naive MV; };
00169 
00170 #undef TMPL
00171 } // namespace mmx
00172 #endif //__MMX__MODULAR_INTEGER__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines