algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : p_adic.hpp 00004 * DESCRIPTION: p-adic integers 00005 * COPYRIGHT : (C) 2009 Jeremy Berthomieu 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_P_ADIC_HPP 00014 #define __MMX_P_ADIC_HPP 00015 #include <basix/pair.hpp> 00016 #include <algebramix/p_expansion_modular_int.hpp> 00017 #include <algebramix/p_expansion_modular_integer.hpp> 00018 #include <algebramix/series_int.hpp> 00019 #include <algebramix/series_integer.hpp> 00020 #include <algebramix/series_modular_int.hpp> 00021 #include <algebramix/series_integer.hpp> 00022 #include <algebramix/series_modular_integer.hpp> 00023 #include <algebramix/series_carry.hpp> 00024 #include <algebramix/series_carry_relaxed.hpp> 00025 #include <algebramix/series_carry_blocks.hpp> 00026 00027 namespace mmx { 00028 00029 #define P_adic_variant(M) Series_carry_variant (M) 00030 #define p_adic(M, V) series<M,V> 00031 #define default_p_adic(M) p_adic(M, typename P_adic_variant(M)) 00032 00033 #define Series series<M,V> 00034 #define Series_rep series_rep<M,V> 00035 #define C typename M::C 00036 #define TMPL template<typename M,typename V> 00037 00038 /****************************************************************************** 00039 * Specific variant for p-adic integer 00040 ******************************************************************************/ 00041 00042 template<typename V> 00043 struct series_carry_p_adic {}; 00044 00045 template<typename U,typename V,typename W> 00046 struct implementation<V,U,series_carry_p_adic<W> >: 00047 public implementation<V,U,W> {}; 00048 00049 /****************************************************************************** 00050 * Naive product optimized for small hardware integer 00051 ******************************************************************************/ 00052 00053 template<typename V> 00054 struct series_carry_modular_int_naive {}; 00055 00056 template<typename U,typename V,typename W> 00057 struct implementation<V,W,series_carry_modular_int_naive<U> >: 00058 public implementation<V,W,U> {}; 00059 00060 template<typename U,typename W> 00061 struct implementation<series_multiply,U,series_carry_modular_int_naive<W> >: 00062 public implementation<series_abstractions,U> 00063 { 00064 typedef implementation<series_abstractions,U> Ser; 00065 00066 template<typename M,typename V> 00067 class mul_series_rep: public Ser::template binary_series_rep<mul_op,M,V> { 00068 typedef typename M::modulus Modulus; 00069 typedef integer L; 00070 typedef unsigned long int N; 00071 nat nf, ng; 00072 L carry; 00073 xnat free_bits; 00074 00075 public: 00076 inline mul_series_rep (const Series& f, const Series& g, 00077 nat nf2= Maximal (nat), 00078 nat ng2= Maximal (nat)): 00079 Ser::template binary_series_rep<mul_op,M,V> (f, g), 00080 nf (nf2), ng (ng2), carry (0) { 00081 Modulus p= M::get_modulus (); 00082 xnat p_size= bit_size (* p); 00083 xnat N_size= 8 * sizeof (N); 00084 free_bits= N_size <= 2 * p_size ? 0 : (N_size - 2 * p_size); } 00085 M next () { 00086 nat n= this->n; 00087 Modulus p= M::get_modulus (); 00088 if (n < 8 || free_bits <= 3) { 00089 C acc= as<C> (rem (carry, * p, carry)), tmp_a, tmp_c; 00090 for (nat i= n >= ng ? n - ng + 1 : 0; i < min (1 + n, nf); i++) { 00091 tmp_c= 0; 00092 mul_mod (tmp_a, (this->f[i]).rep, (this->g[n-i]).rep, p, tmp_c); 00093 carry += tmp_c; tmp_c= 0; 00094 add_mod (acc, tmp_a, p, tmp_c); 00095 carry += tmp_c; 00096 } 00097 return acc; 00098 } 00099 C acc= as<C> (rem (carry, * p, carry)), tmp_a, tmp_c; 00100 nat n_max= min (1 + n, nf); 00101 for (nat i= n >= ng ? n - ng + 1 : 0; i < n_max;) { 00102 N t0= 0, t1= 0; 00103 nat i_max= i + min (((nat) 1 << free_bits), (nat) (n_max - i)); 00104 for (; i < i_max; i++) 00105 t0 += N((this->f[i]).rep) * N((this->g[n-i]).rep); 00106 tmp_a= rem (t0, * p, t1); 00107 tmp_c= 0; add_mod (acc, tmp_a, p, tmp_c); 00108 carry += tmp_c + t1; 00109 } 00110 return acc; } 00111 }; 00112 00113 template<typename M,typename V> static inline Series 00114 ser_mul (const Series& f, const Series& g) { 00115 typedef mul_series_rep<M,V> Mul_rep; 00116 if (is_exact_zero (f) || is_exact_zero (g)) 00117 return Series (CF(f)); 00118 return (Series_rep*) new Mul_rep (f, g); } 00119 00120 template<typename M,typename V> static inline Series 00121 ser_truncate_mul (const Series& f, const Series& g, nat nf, nat ng) { 00122 typedef mul_series_rep<M,V> Mul_rep; 00123 if (is_exact_zero (f) || is_exact_zero (g) || nf == 0 || ng == 0) 00124 return Series (CF(f)); 00125 return (Series_rep*) new Mul_rep (f, g, nf, ng); } 00126 00127 }; // implementation<series_multiply,U,series_carry_modular_int_naive<U> > 00128 00129 /****************************************************************************** 00130 * p-th root 00131 ******************************************************************************/ 00132 #define Pair pair<integer,integer> 00133 00134 struct ser_carry_pth_root_reg_op { 00135 // For the only computation of the regularized part for p >= 3 only 00136 00137 template<typename M, typename V> static Series 00138 binpow_no_tangent_normalized (const Series& x0, const Series& x1, 00139 const integer& r, const integer& p) { 00140 // ((x0 + p * x1)^r - r * p * x1 * x0^(r-1) - x0^r) / p^2 00141 // x1 has valuation at least 1 00142 ASSERT (p >= 3, "bug"); 00143 if (r <= 1) return Series (0); 00144 00145 Series x1_2= lshiftz (square (rshiftz (x1, 1)), 2); 00146 if (r == 2) return x1_2; 00147 00148 Series s_p (coefficients (as<default_p_expansion(M)> (p))); 00149 00150 if ((r & 1) == 1) { 00151 integer h= r - 1; 00152 Series w= binpow_no_tangent_normalized (x0, x1, h, p); 00153 Series s_h (coefficients (as<default_p_expansion(M)> (h))); 00154 Series x0_h_1= binpow (x0, h - 1); 00155 return lshiftz ((x0 + s_p * x1) * rshiftz (w, 1), 1) 00156 + s_h * x0_h_1 * x1_2; 00157 } 00158 00159 integer h= r >> 1; // r is now even 00160 Series s_h (coefficients (as<default_p_expansion(M)> (h))); 00161 Series s_p_2 (coefficients (as<default_p_expansion(M)> (square (p)))); 00162 Series x0_h_1= binpow (x0, h - 1); 00163 Series x0_h= x0 * x0_h_1; 00164 00165 Series d= binpow_no_tangent_normalized (x0, x1, h, p); 00166 Series l= s_h * s_p * x0_h_1 * x1 + x0_h; 00167 return lshiftz (rshiftz (d, 1) * (s_p_2 * d + l + l), 1) 00168 + square (s_h * x0_h_1) * x1_2; 00169 } 00170 00171 static generic name () { return "pth_root"; } 00172 00173 template<typename M> static inline M 00174 op (const M& a, const Pair& p) { 00175 (void) p; return a; } 00176 00177 template<typename M, typename V> static inline Series 00178 op (const Series& a, const Pair& p) { 00179 typedef implementation<series_pth_root_reg,V> Ser; 00180 return Ser::unsep_root_reg (a, p); } 00181 00182 template<typename M, typename V> static inline Series 00183 op_init (const Series& a, const Pair& p, const M& init) { 00184 typedef implementation<series_pth_root_reg,V> Ser; 00185 return Ser::unsep_root_reg (a, p, init); } 00186 00187 static inline syntactic 00188 op (const syntactic& a, const syntactic& p) { 00189 return apply ("pth_root_reg", a, p); } 00190 00191 static inline nat nr_init () { return 1; } 00192 00193 template<typename M, typename V> static inline Series 00194 def (const Series& me, const Series& a, const Pair& p_b0) { 00195 integer p= first (p_b0); integer b0= second (p_b0); 00196 integer q= as<integer> (* M::get_modulus ()); 00197 Series ser_p (coefficients (as<default_p_expansion(M)> (p))); 00198 if (p == 2) 00199 return (a - me[0] - ser_p 00200 * (square (Series (me[0])) 00201 + lshiftz (square (rshiftz (me, 1)), 2))) 00202 / (M(1) + square (ser_p) * me[0]); 00203 00204 Series tmp= binpow (Series (M(b0) + ser_p * me[0]), p) 00205 - binpow (Series (M(b0)), p); 00206 tmp= q == p ? rshiftz (tmp, 2): rshiftz (M (q / square (p)) * tmp, 1); 00207 Series ap= a - tmp; 00208 Series c= M (b0) + ser_p * me[0]; 00209 return (ap - binpow_no_tangent_normalized (c, me - me[0], p, p)) 00210 / binpow (c, p - 1); } 00211 00212 }; // struct ser_carry_pth_root_reg_op 00213 00214 template<typename U, typename W> 00215 struct implementation<series_pth_root_reg,U, 00216 series_carry_p_adic<W> > { 00217 00218 TMPL static inline Series 00219 unsep_root_reg (const Series& a, const Pair& p) { 00220 return binary_scalar_recursive_series 00221 <ser_carry_pth_root_reg_op> (a, p); } 00222 00223 TMPL static inline Series 00224 unsep_root_reg (const Series& a, const Pair& p, const M& init) { 00225 return binary_scalar_recursive_series 00226 <ser_carry_pth_root_reg_op> (a, p, init); } 00227 }; 00228 00229 template<typename U, typename W> 00230 struct implementation<series_pth_root,U,series_carry_p_adic<W> > { 00231 00232 typedef implementation<series_pth_root_reg,U> Reg; 00233 00234 TMPL static inline Series 00235 unsep_root (const Series& a) { 00236 if (is_exact_zero (a)) return Series (CF(a)); 00237 C p= * M::get_modulus (); 00238 if (p == 2) { 00239 ASSERT (a[0] == 1, "positive valuation is not allowed"); 00240 ASSERT (a[1] == 0 && a[2] == 0, "no root"); 00241 return 1 + lshiftz (Reg::unsep_root_reg (rshiftz (a, 3), Pair (p, 1)), 2); 00242 } 00243 ASSERT (! is_exact_zero (a[0]), "positive valuation is not allowed"); 00244 M b0= pth_root (a[0]); 00245 Series ap= a - binpow (Series (b0), p); 00246 ASSERT (ap[0] == 0 && ap[1] == 0, "no root"); 00247 return b0 + lshiftz (Reg::unsep_root_reg 00248 (rshiftz (ap, 2), Pair (p, * b0)), 1); } 00249 00250 }; // implementation<series_pth_root,U,series_carry_p_adic<W> > 00251 00252 // wrapper for block operations 00253 00254 template<typename U,typename W,nat s,typename BV,nat t> 00255 struct implementation<series_pth_root_reg,U, 00256 series_carry_monoblock<W,s,BV,t> > { 00257 00258 TMPL static inline Series 00259 unsep_root_reg (const Series& a, const Pair& p) { 00260 return as<Series> 00261 (binary_scalar_recursive_monoblock_series 00262 <ser_carry_pth_root_reg_op,M,W,s,BV,t,Pair> 00263 (as<series<M,W> > (a), p)); } 00264 00265 TMPL static inline Series 00266 unsep_root_reg (const Series& a, const Pair& p, const M& init) { 00267 return as<Series> 00268 (binary_scalar_recursive_monoblock_series 00269 <ser_carry_pth_root_reg_op,M,W,s,BV,t,Pair> 00270 (as<series<M,W> > (a), p, init)); } 00271 }; 00272 #undef Pair 00273 00274 #undef Series 00275 #undef Series_rep 00276 #undef C 00277 #undef TMPL 00278 00279 /****************************************************************************** 00280 * Default variants 00281 ******************************************************************************/ 00282 00283 #define IMPLEMENTATION_HELPER(C) \ 00284 template<typename V,typename W> \ 00285 struct series_carry_variant_helper<modular<modulus<C,V>,W> > { \ 00286 typedef series_carry_p_adic< \ 00287 series_carry_relaxed<series_carry_naive> > SV; }; 00288 00289 IMPLEMENTATION_HELPER(signed char) 00290 IMPLEMENTATION_HELPER(unsigned char) 00291 IMPLEMENTATION_HELPER(short int) 00292 IMPLEMENTATION_HELPER(unsigned short) 00293 IMPLEMENTATION_HELPER(int) 00294 IMPLEMENTATION_HELPER(unsigned int) 00295 IMPLEMENTATION_HELPER(long int) 00296 IMPLEMENTATION_HELPER(unsigned long int) 00297 IMPLEMENTATION_HELPER(long long int) 00298 IMPLEMENTATION_HELPER(unsigned long long int) 00299 #undef IMPLEMENTATION_HELPER 00300 00301 template<typename V,typename W> 00302 struct series_carry_variant_helper<modular<modulus<integer,V>,W> > { 00303 typedef series_carry_p_adic< 00304 series_carry_relaxed<series_carry_naive> > SV; 00305 }; 00306 00307 } // namespace mmx 00308 #endif // __MMX_P_ADIC_HPP