algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/crt_int.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : crt_int.hpp
00004 * DESCRIPTION: CRT subroutines for hardware integers
00005 * COPYRIGHT  : (C) 2008  Joris van der Hoeven and 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_CRT_INT_HPP
00014 #define __MMX_CRT_INT_HPP
00015 #include <numerix/integer.hpp>
00016 #include <numerix/modular_int.hpp>
00017 #include <algebramix/crt_naive.hpp>
00018 
00019 namespace mmx {
00020 
00021 /******************************************************************************
00022 * Variant for hardware integers
00023 ******************************************************************************/
00024 
00025 DEFINE_VARIANT(crt_int,crt_signed<crt_naive>)
00026 DEFINE_VARIANT(crt_unsigned_int,crt_naive)
00027 
00028 #define DECLARE_HELPER(C)                       \
00029   STMPL struct crt_naive_variant_helper<C> {    \
00030     typedef crt_int CV; };
00031 DECLARE_HELPER (signed char)
00032 DECLARE_HELPER (short int)
00033 DECLARE_HELPER (int)
00034 DECLARE_HELPER (long int)
00035 DECLARE_HELPER (long long int)
00036 #undef DECLARE_HELPER
00037 
00038 #define DECLARE_HELPER(C)                       \
00039   STMPL struct crt_naive_variant_helper<C> {    \
00040     typedef crt_unsigned_int CV; };
00041 DECLARE_HELPER (unsigned char)
00042 DECLARE_HELPER (unsigned short int)
00043 DECLARE_HELPER (unsigned int)
00044 DECLARE_HELPER (unsigned long int)
00045 DECLARE_HELPER (unsigned long long int)
00046 #undef DECLARE_HELPER
00047 
00048 /******************************************************************************
00049 * Special transform taking care of casual overflows
00050 ******************************************************************************/
00051 
00052 template<typename V>
00053 struct implementation<crt_transform,V,crt_int> :
00054     public implementation<crt_project,V> {
00055   typedef implementation<crt_project,V> Crt;
00056 
00057   template<typename C, typename M, typename I> static inline void
00058   direct (I* c, const C& a, const M* p, nat n) {
00059     for (nat i= 0; i < n; i++)
00060       c[i]= Crt::mod (a, p[i]); }
00061 
00062   template<typename C, typename M, typename I, typename K> static inline void
00063   inverse (C& a, const I* c, const M* p, const K& P,
00064            const C* q, const I* m, nat n) {
00065     a= 0; I t;
00066     for (nat i= 0; i < n; i++) {
00067       mul_mod (t, m[i], c[i], p[i]);
00068       add_mod (a, t * q[i], P); } }
00069 };
00070 
00071 template<typename V>
00072 struct implementation<crt_transform,V,crt_unsigned_int> :
00073     public implementation<crt_transform,V,crt_int> {};
00074 
00075 /******************************************************************************
00076 * Sequence of prime numbers
00077 ******************************************************************************/
00078 
00079 #define TMPL template<typename M>
00080 
00081 struct prime_sequence_int {
00082 private:
00083   TMPL static inline bool
00084   is_prime (const vector<M>& v, nat n) {
00085     for (nat i= 0; true; i++) {
00086       nat p= (nat) *v[i];
00087       if (n % p == 0) return false;
00088       if (p*p >= n) break;
00089     }
00090     return true; }
00091 
00092 public:
00093   TMPL static bool
00094   extend (vector<M>& v, nat i) {
00095     if (N(v) == 0) v= vec (M(2), M(3));
00096     nat p= *(v[N(v) - 1]) + 2;
00097     while (N(v) < i) {
00098       if (is_prime (v, p)) v << M(p);
00099       p += 2;
00100     }
00101     return true; }
00102 };
00103 
00104 #define DECLARE_HELPER(I)                               \
00105 template<typename V>                                    \
00106  struct coprime_moduli_helper<modulus<I, V> > {         \
00107   typedef prime_sequence_int sequence;                  \
00108 };
00109 DECLARE_HELPER (signed char)
00110 DECLARE_HELPER (unsigned char)
00111 DECLARE_HELPER (short int)
00112 DECLARE_HELPER (unsigned short int)
00113 DECLARE_HELPER (int)
00114 DECLARE_HELPER (unsigned int)
00115 DECLARE_HELPER (long int)
00116 DECLARE_HELPER (unsigned long int)
00117 DECLARE_HELPER (long long int)
00118 DECLARE_HELPER (unsigned long long int)
00119 #undef DECLARE_HELPER
00120 
00121 /******************************************************************************
00122 * Covering
00123 ******************************************************************************/
00124 
00125 template<typename C, typename M, typename W>
00126 struct moduli_unsigned_integer_helper {
00127   // C is an unsigned int type
00128   template<typename V> static bool
00129   covering (vector<M, V>& v, nat s) {
00130     static coprime_moduli_sequence<M,W> seq;
00131     v= vector<M, V> ();
00132     C p (1), q; nat i= 0;
00133     while (bit_size (p) < s + 1) {
00134       if (seq [i] == 0) return false;
00135       v << seq [i];
00136       q = p * C (* seq [i]);
00137       if (quo (q, p) != C (* seq [i])) return false; // means overflow!
00138       p = q;
00139       i++;
00140     }
00141     return true; }
00142 };
00143 
00144 template<typename C, typename M, typename W>
00145 struct moduli_signed_integer_helper {
00146   // C is a signed int type
00147   template<typename V> static bool
00148   covering (vector<M, V>& v, nat s) {
00149     static coprime_moduli_sequence<M,W> seq;
00150     v= vector<M, V> ();
00151     C p (1), q; nat i= 0;
00152     while (bit_size (p) < s + 2) { // s + 2 is needed for sign decoding!
00153       if (seq [i] == 0) return false;
00154       v << seq [i];
00155       q = p * C (* (seq [i]));
00156       if (quo (q, p) != C (* seq [i])) return false; // means overflow!
00157       p = q;
00158       i++;
00159     }
00160     return true; }
00161 };
00162 
00163 #define DECLARE_HELPER(C)                                               \
00164   template<typename M, typename W>                                      \
00165   struct moduli_helper<C,M,W> : moduli_signed_integer_helper<C,M,W> {};
00166 DECLARE_HELPER (signed char)
00167 DECLARE_HELPER (short int)
00168 DECLARE_HELPER (int)
00169 DECLARE_HELPER (long int)
00170 DECLARE_HELPER (long long int)
00171 #undef DECLARE_HELPER
00172 
00173 #define DECLARE_HELPER(C)                                               \
00174   template<typename M, typename W>                                      \
00175   struct moduli_helper<C,M,W> : moduli_unsigned_integer_helper<C,M,W> {};
00176 DECLARE_HELPER (unsigned char)
00177 DECLARE_HELPER (unsigned short int)
00178 DECLARE_HELPER (unsigned int)
00179 DECLARE_HELPER (unsigned long int)
00180 DECLARE_HELPER (unsigned long long int)
00181 #undef DECLARE_HELPER
00182 
00183 /******************************************************************************
00184 * Naive primality test
00185 ******************************************************************************/
00186 
00187 bool is_prime (nat n);
00188 bool is_probable_prime (unsigned long int n);
00189 
00190 /******************************************************************************
00191 * Sequence of prime numbers of bit size s
00192 ******************************************************************************/
00193 
00194 template <nat s>
00195 struct fft_prime_sequence_int {
00196   // prime numbers of bit-size at most s,
00197   // starting with primes suitable to fft.
00198 private:
00199   static nat
00200   bit_reverse (nat i, nat n) {
00201     if (n <= 1) return i;
00202     nat n2= n >> 1;
00203     nat n1= n - n2;
00204     return (bit_reverse (i & ((1 << n2) - 1), n2) << n1) +
00205       bit_reverse (i >> n2, n1);
00206   }
00207 public:
00208   template<typename C, typename V> static bool
00209   extend (vector<modulus<C,V> >& v, nat n) {
00210     // construct prime moduli of s bits exactly,
00211     // starting with those which have a maximal number of
00212     // primitive 2^k-th roots of unity
00213     typedef modulus<C,V> M;
00214     const nat b= V::template maximum_size_helper<C>::value;
00215     ASSERT (s <= b, "bitsize overflow");
00216     ASSERT (b <= 8 * sizeof (nat), "bitsize overflow");
00217     if (s < 2 && n > 0) return false;
00218     const C m= 1 + MMX_SAFE_LEFT_SHIFT_INT (C, 1, (s-1));
00219     const C l= MMX_SAFE_LEFT_SHIFT_INT (C, 1, s);
00220     for (nat i= N(v); i < n; i++) {
00221       C j= i == 0 ? m : (bit_reverse (* v[i-1], s) + 2), k;
00222       for (; j <= l - 1 && j >= m; j += 2)
00223         if (is_prime (k= bit_reverse (j, s))) break;
00224       if (j > l - 1 || j < m) return false;
00225       v << M(k); }
00226     return true; }
00227 };
00228 
00229 /******************************************************************************
00230 * Sequence of probable prime numbers of bit size s
00231 ******************************************************************************/
00232 
00233 template <nat s>
00234 struct probable_prime_sequence_int {
00235   // probable prime numbers of bit-size at least s
00236 
00237   template<typename C, typename V> static bool
00238   extend (vector<modulus<C,V> >& v, nat n) {
00239     // construct probable prime moduli of s bits exactly.
00240     typedef modulus<C,V> M;
00241     const nat b= V::template maximum_size_helper<C>::value;
00242     ASSERT (s <= b, "bitsize overflow");
00243     if (s < 2 && n > 0) return false;
00244     integer a (N(v) == 0 ? (integer (1) << (s-1)) : integer (* v[N(v)-1]));
00245     integer p= probable_next_prime (a);
00246     if (bit_size (p) > b) return false;
00247     v << M(as <C> (p));
00248     return true; }
00249 };
00250 
00251 #undef TMPL
00252 } // namespace mmx
00253 #endif // __MMX_CRT_INT_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines