00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX_SERIES_CARRY_RELAXED_HPP
00014 #define __MMX_SERIES_CARRY_RELAXED_HPP
00015 #include <algebramix/series_relaxed.hpp>
00016 #include <algebramix/series_carry_naive.hpp>
00017
00018 namespace mmx {
00019 #define Series series<M,V>
00020 #define Series_rep series_rep<M,V>
00021 #define C typename M::C
00022 #define Modulus typename M::modulus
00023 #define TMPL template<typename M, typename V>
00024
00025
00026
00027
00028
00029 template<typename V>
00030 struct series_carry_relaxed {};
00031
00032 template<typename U,typename V,typename W>
00033 struct implementation<V,W,series_carry_relaxed<U> >:
00034 public implementation<V,W,U> {};
00035
00036
00037
00038
00039
00040 template<typename U,typename W>
00041 struct implementation<series_multiply,U,series_carry_relaxed<W> >:
00042 public implementation<series_abstractions,U>
00043 {
00044
00045 public:
00046 TMPL
00047 class mul_series_rep: public Series_rep {
00048 public:
00049 typedef Lift_type(M) L;
00050
00051 protected:
00052 Series f, g;
00053
00054
00055
00056
00057
00058 int lnz_f;
00059 int lnz_g;
00060 nat zeros_f;
00061 nat zeros_g;
00062
00063 vector<L> b_f, d_f, b_g, d_g;
00064
00065
00066 vector<L> powers_of_p;
00067 vector<L> carry;
00068
00069 L get_power_of_p (const Modulus& p, nat i) {
00070
00071
00072 static const L zero (0);
00073 while (i >= N (powers_of_p))
00074 powers_of_p << vector<L> (zero, max ((nat) 1, N (powers_of_p)));
00075 if (powers_of_p [i] == zero) {
00076 if (i == 0) powers_of_p[0]= L(* p);
00077 else powers_of_p[i]= square (get_power_of_p (p, i - 1));
00078 }
00079 return powers_of_p [i];
00080 }
00081
00082 public:
00083 mul_series_rep (const Series& f2, const Series& g2):
00084 Series_rep (CF(f2)), f (f2), g (g2), lnz_f (-1), lnz_g (-1),
00085 zeros_f (0), zeros_g (0) {}
00086 ~mul_series_rep () {}
00087
00088 syntactic expression (const syntactic& z) const {
00089 return flatten (f, z) * flatten (g, z); }
00090
00091 void Set_order (nat l2) {
00092 Series_rep::Set_order (l2);
00093 nat m= log_2 (next_power_of_two (l2 + 1));
00094 if (N(b_f) < m) {
00095 vector<L> tmp (L(0), m - N(b_f));
00096 b_f << tmp; d_f << tmp;
00097 b_g << tmp; d_g << tmp;
00098 carry << tmp; } }
00099
00100 void Increase_order (nat l) {
00101 Set_order (l);
00102 increase_order (f, l);
00103 increase_order (g, l); }
00104
00105 M next () {
00106
00107 Modulus p= M::get_modulus ();
00108 nat k= this->n;
00109 if (exact_neq (f[k], M(0))) lnz_f= k;
00110 if (exact_neq (g[k], M(0))) lnz_g= k;
00111 if (k == 0) {
00112 C r= 0;
00113 if (lnz_f < 0) zeros_f |= 1;
00114 if (lnz_g < 0) zeros_g |= 1;
00115 if ((zeros_f&1) == 0 && (zeros_g&1) == 0) {
00116 C q= 0;
00117 mul_mod (r, * f[0], * g[0], p, q);
00118 carry[0]= as<L> (q);
00119 }
00120 b_f[0]= d_f[0]= lift (f[0]);
00121 b_g[0]= d_g[0]= lift (g[0]);
00122 return M (r, true);
00123 }
00124 else {
00125 k = 2 * (this->n + 2);
00126 L t= 0, e_f= lift (f[this->n]), e_g= lift (g[this->n]);
00127 nat q= -1;
00128 while ((k&1) == 0 && k != 2) {
00129 q++; k= k >> 1;
00130
00131 if (q > 0) {
00132 e_f= b_f[q-1] + get_power_of_p (p, q-1) * e_f;
00133 e_g= b_g[q-1] + get_power_of_p (p, q-1) * e_g;
00134 }
00135 if (k == 2) {
00136 if (lnz_f < ((int) (1<<q)-1)) zeros_f |= (1<<q);
00137 if (lnz_g < ((int) (1<<q)-1)) zeros_g |= (1<<q);
00138 d_f[q]= e_f; d_g[q]= e_g;
00139 }
00140 t += carry[q];
00141 if (q == 0 ||
00142 ((zeros_f & (1<<q)) == 0 && lnz_g >= ((int) (((k-1)<<q)-1))))
00143 t += d_f[q] * e_g;
00144 if (k == 2) break;
00145 if (q == 0 ||
00146 ((zeros_g & (1<<q)) == 0 && lnz_f >= ((int) (((k-1)<<q)-1)))) {
00147 t += e_f * d_g[q];
00148 }
00149 }
00150 b_f[q]= e_f; b_g[q]= e_g;
00151 while (q != (nat) -1) {
00152 t = rem (t, get_power_of_p (p, q), carry[q]);
00153 q--;
00154 }
00155 return M (as<C> (t), true); } }
00156 };
00157
00158 TMPL static inline Series
00159 ser_mul (const Series& f, const Series& g) {
00160
00161
00162 typedef mul_series_rep<M,V> Mul_rep;
00163 if (is_exact_zero (f) || is_exact_zero (g))
00164 return Series (CF(f));
00165 return (Series_rep*) new Mul_rep (f, g); }
00166
00167 TMPL static inline Series
00168 ser_truncate_mul (const Series& f, const Series& g, nat nf, nat ng) {
00169 typedef mul_series_rep<M,V> Mul_rep;
00170 if (is_exact_zero (f) || is_exact_zero (g) || nf == 0 || ng == 0)
00171 return Series (CF(f));
00172 return (Series_rep*)
00173 new Mul_rep (piecewise (f, Series (CF(f)), nf),
00174 piecewise (g, Series (CF(g)), ng)); }
00175
00176 };
00177
00178 #undef Series
00179 #undef Series_rep
00180 #undef C
00181 #undef Modulus
00182 #undef TMPL
00183
00184 }
00185 #endif // __MMX_SERIES_CARRY_RELAXED_HPP