numerix_doc 0.4
|
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