algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/fft_roots.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : fft_roots.hpp
00004 * DESCRIPTION: primitive roots for diadic and triadic FFTs
00005 * COPYRIGHT  : (C) 2005  Joris van der Hoeven
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__FFT_ROOTS__HPP
00014 #define __MMX__FFT_ROOTS__HPP
00015 #include <basix/int.hpp>
00016 #include <basix/vector_naive.hpp>
00017 #include <numerix/modular.hpp>
00018 #include <numerix/modular_int.hpp>
00019 #include <numerix/complex_double.hpp>
00020 
00021 namespace mmx {
00022 
00023 /******************************************************************************
00024 * Helper functions on bits
00025 ******************************************************************************/
00026 
00027 // diadic
00028 static nat
00029 bit_mirror (nat i, nat n) {
00030   if (n == 1) return i;
00031   else return (bit_mirror (i & ((n>>1) -1), n>>1) << 1) + i / (n>>1);
00032 }
00033 
00034 // triadic
00035 static nat
00036 digit_mirror_triadic (nat i, nat n) {
00037   if (n == 1) return i;
00038   else return digit_mirror_triadic (i % (n / 3), n / 3) * 3 + i / (n / 3);
00039 }
00040 
00041 /******************************************************************************
00042 * Primitive roots of unity
00043 ******************************************************************************/
00044 
00045 template<typename C>
00046 struct primitive_root_helper {
00047 
00048   // max order for b-adic fft
00049   static inline nat
00050   max_order (nat b) { return 0; } // means infinity
00051     
00052   static inline C
00053   op (nat n, nat i) {
00054     if (n == 1 || i == 0) return C (1);
00055     else if (n == 2) return C(-1);
00056     else {
00057       Real_type(C) angle= (2 * i * Pi(Real_type(C))) / n;
00058       return gaussian (cos (angle), sin (angle));
00059     }
00060   }
00061 };
00062 
00063 template<typename C> C
00064 primitive_root (nat n, nat i) {
00065   return primitive_root_helper<C>::op (n, i);
00066 }
00067 
00068 template<typename C> nat
00069 primitive_root_max_order (nat b) {
00070   return primitive_root_helper<C>::max_order (b);
00071 }
00072 
00073 // double
00074 #ifdef ACCURATE_ROOTS
00075 template<>
00076 struct primitive_root_helper<complex<double> > {
00077   static inline nat
00078   max_order (nat b) { return 0; }
00079 
00080   static complex<double> op (nat n, nat i);
00081 };
00082 #endif // ACCURATE_ROOTS
00083 
00084 // modular native integers
00085 template<typename I> nat
00086 primitive_root_max_order_int (nat b, I p, I& m) {
00087   // p must be nonnegative
00088   nat k= 0;
00089   m= (nat) (p-1);
00090   while (m % b == 0) { k++; m /= b; }
00091   return ((nat) (p-1)) / m;
00092 }
00093 
00094 template<typename I> I
00095 primitive_root_max_int (nat b, I p, nat& k, I& m) {
00096   // root of maximal order k for radix b modulo p
00097   typedef modulus<I, modulus_int_preinverse<8*sizeof(I)> > Modulus;
00098   typedef modular<Modulus> Modular;
00099   k= primitive_root_max_order_int (b, p, m);
00100   if (k == 1) return I (1);
00101   Modulus tmp= Modular::get_modulus ();
00102   Modular::set_modulus (p);
00103   Modular v;
00104   for (I x = 1; x < p; x++) {
00105     v = binpow (Modular (x), (nat) m);
00106     if (v == 1) continue;
00107     if (binpow (v, k / b) != 1) break;
00108   }
00109   Modular::set_modulus (tmp);
00110   return * v;
00111 }
00112 
00113 template<typename I, typename V, typename W>
00114 struct primitive_root_helper_modular_int {
00115   typedef modular<modulus<I,V>,W> C;
00116   
00117   static inline nat
00118   max_order (nat b) {
00119     I m, p= * C::get_modulus ();
00120     return primitive_root_max_order_int (b, p, m);
00121   }
00122     
00123   static inline C
00124   op (nat n, nat i) {
00125     nat b, k;
00126     if (n == next_power_of_two (n)) b = 2;
00127     else if (n == next_power_of_three (n)) b = 3;
00128     else ERROR ("only radices 2 and 3 are implemented");
00129     I m, p= * C::get_modulus ();
00130     C v= primitive_root_max_int (b, p, k, m);
00131     VERIFY (n <= k, "maximal order exceeded");
00132     // v is now a primitive root of maximal order k
00133     return binpow (v, i * (k / n));
00134   }
00135 };
00136 
00137 template<typename V, typename W>
00138 struct primitive_root_helper<modular<modulus<unsigned char,V>,W> > :
00139     primitive_root_helper_modular_int<unsigned char, V, W> {};
00140 
00141 template<typename V, typename W>
00142 struct primitive_root_helper<modular<modulus<signed char,V>,W> > :
00143     primitive_root_helper_modular_int<signed char, V, W> {};
00144 
00145 template<typename V, typename W>
00146 struct primitive_root_helper<modular<modulus<short unsigned int,V>,W> > :
00147     primitive_root_helper_modular_int<short unsigned int, V, W> {};
00148 
00149 template<typename V, typename W>
00150 struct primitive_root_helper<modular<modulus<short signed int,V>,W> > :
00151     primitive_root_helper_modular_int<short signed int, V, W> {};
00152 
00153 template<typename V, typename W>
00154 struct primitive_root_helper<modular<modulus<unsigned int,V>,W> > :
00155     primitive_root_helper_modular_int<unsigned int, V, W> {};
00156 
00157 template<typename V, typename W>
00158 struct primitive_root_helper<modular<modulus<int,V>,W> > :
00159     primitive_root_helper_modular_int<int, V, W> {};
00160 
00161 template<typename V, typename W>
00162 struct primitive_root_helper<modular<modulus<long unsigned int,V>,W> > :
00163     primitive_root_helper_modular_int<long unsigned int, V, W> {};
00164 
00165 template<typename V, typename W>
00166 struct primitive_root_helper<modular<modulus<long int,V>,W> > :
00167     primitive_root_helper_modular_int<long int, V, W> {};
00168 
00169 #ifdef BASIX_HAVE_LONG_LONG_INT
00170 template<typename V, typename W>
00171 struct primitive_root_helper<modular<modulus<long long unsigned int,V>,W> > :
00172     primitive_root_helper_modular_int<long long unsigned int, V, W> {};
00173 
00174 template<typename V, typename W>
00175 struct primitive_root_helper<modular<modulus<long long int,V>,W> > :
00176     primitive_root_helper_modular_int<long long int, V, W> {};
00177 #endif
00178 
00179 // special modulus 3 * 2^30 + 1 
00180 #define FFTP modular_fixed<nat,0x0c0000001> 
00181 
00182 template<typename V>
00183 struct primitive_root_helper<modular<modulus<nat,V>,FFTP> > {
00184   typedef modulus<nat, V> Modulus;
00185   typedef modular<Modulus,FFTP> Modular;
00186 
00187   static inline nat
00188   max_order (nat b) {
00189     if (b == 2) return 1<<30;
00190     if (b == 3) return 3;
00191     return 0;
00192   }
00193 
00194   static inline Modular
00195   op (nat n, nat i) {
00196     nat k;
00197     Modular v;
00198     if (n == next_power_of_two (n)) {
00199       k = max_order (2);
00200       v = 125;
00201     }
00202     else if (n == next_power_of_three (n)) {
00203       k = max_order (3);
00204       v = 1610563584;
00205     }
00206     else ERROR ("only radices 2 and 3 are implemented");
00207     ASSERT (n <= k, "maximal order exceeded");
00208     return binpow (v, i * (k / n));
00209   }
00210 };
00211 
00212 // Bivariate polynomials
00213 template<typename C, typename V> struct polynomial;
00214 
00215 template<typename C, typename V>
00216 struct primitive_root_helper<polynomial<C,V> > :
00217     primitive_root_helper<C> {};
00218 
00219 // Polynomials over modulars of polynomials
00220 template<typename C, typename U, typename V, typename W>
00221 struct primitive_root_helper<modular<modulus<polynomial<C,U>,V>,W> > :
00222     primitive_root_helper<C> {};
00223 
00224 /******************************************************************************
00225 * Cache for roots
00226 ******************************************************************************/
00227 
00228 template<typename V>
00229 struct cached_roots_helper: public V {
00230   typedef typename V::C C;
00231   typedef typename V::U U;
00232   static nat capacity;
00233   static U*  roots;
00234   
00235   static U*
00236   create_roots (nat n) {
00237     if (n > capacity) {
00238       if (capacity != 0) V::destroy_roots (roots, capacity);
00239       roots= V::create_roots (n);
00240       capacity= n;
00241     }
00242     return roots;
00243   }
00244 
00245   static void
00246   destroy_roots (U* u, nat n) {
00247     (void) u; (void) n;
00248   }
00249 };
00250 
00251 template<typename V> nat cached_roots_helper<V>::capacity= 0;
00252 template<typename V> typename V::U* cached_roots_helper<V>::roots= NULL;
00253 
00254 // Root caching is only used for when C can not be modified howsoever
00255 template<typename CC, typename UU=CC, typename SS=CC>
00256 struct roots_helper;
00257 
00258 template<typename C>
00259 struct std_roots {
00260   typedef roots_helper<C> roots_type;
00261 };
00262 
00263 template<typename C, typename V>
00264 struct std_roots<polynomial<C, V> > {
00265   typedef roots_helper<polynomial<C, V>, C, C> roots_type;
00266 };
00267 
00268 STMPL
00269 struct std_roots<complex<double> > {
00270   typedef complex<double> C;
00271   typedef cached_roots_helper<roots_helper<C> > roots_type;
00272 };
00273 
00274 template<typename M, typename D, D d>
00275 struct std_roots<modular<M, modular_fixed<D, d> > >{
00276   typedef modular<M, modular_fixed<D, d> > C;
00277   typedef cached_roots_helper<roots_helper<C> > roots_type;
00278 };
00279 
00280 } // namespace mmx
00281 #endif //__MMX__FFT_ROOTS__HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines