00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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 };
00128
00129
00130
00131
00132 #define Pair pair<integer,integer>
00133
00134 struct ser_carry_pth_root_reg_op {
00135
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
00141
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;
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= car (p_b0); integer b0= cdr (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 };
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 };
00251
00252
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
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 }
00308 #endif // __MMX_P_ADIC_HPP