00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__SERIES_RELAXED__HPP
00014 #define __MMX__SERIES_RELAXED__HPP
00015 #include <algebramix/series_naive.hpp>
00016 namespace mmx {
00017 #define TMPL template<typename C,typename V>
00018 #define Series series<C,V>
00019 #define Series_rep series_rep<C,V>
00020
00021
00022
00023
00024
00025 template<typename V>
00026 struct series_relaxed {};
00027
00028 template<typename F, typename V, typename W>
00029 struct implementation<F,V,series_relaxed<W> >:
00030 public implementation<F,V,W> {};
00031
00032
00033
00034
00035
00036 template<typename U,typename W>
00037 struct implementation<series_multiply,U,series_relaxed<W> >:
00038 public implementation<series_abstractions,U>
00039 {
00040
00041 TMPL
00042 class mul_series_rep: public Series_rep {
00043 public:
00044 typedef typename series_polynomial_helper<C,V >::PV PV;
00045 typedef implementation<polynomial_multiply,PV> Pol;
00046
00047 protected:
00048 Series f, g;
00049
00050
00051
00052
00053
00054 int lnz_f;
00055 int lnz_g;
00056 nat zeros_f;
00057 nat zeros_g;
00058
00059 public:
00060 mul_series_rep (const Series& f2, const Series& g2):
00061 Series_rep (CF(f2)), f (f2), g (g2), lnz_f (-1), lnz_g (-1),
00062 zeros_f (0), zeros_g (0) {}
00063 ~mul_series_rep () {}
00064
00065 syntactic expression (const syntactic& z) const {
00066 return flatten (f, z) * flatten (g, z); }
00067
00068 void Set_order (nat l2) {
00069
00070 if (l2 <= this->l) return;
00071 mmx_delete<C> (this->a, this->l);
00072 this->a= mmx_new<C> (l2);
00073 this->l= l2;
00074 Pol::clear (this->a, this->l);
00075 nat k= this->n;
00076 this->n= 0;
00077 lnz_f= -1;
00078 lnz_g= -1;
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 while (this->n < k) {
00089 (void) next ();
00090 this->n++;
00091 }
00092 }
00093
00094 void Increase_order (nat l) {
00095 if (this->l < l) {
00096 nat k=1;
00097 while (k < (this->l << 1)) k= (k<<1) + 1;
00098 Set_order (max (k, l));
00099 }
00100 increase_order (f, l);
00101 increase_order (g, l);
00102 }
00103
00104 C next () {
00105 nat k= this->n;
00106 if (exact_neq (f[k], C(0))) lnz_f= k;
00107 if (exact_neq (g[k], C(0))) lnz_g= k;
00108 if (k == 0) {
00109 if (lnz_f < 0) zeros_f |= 1;
00110 if (lnz_g < 0) zeros_g |= 1;
00111 if ((zeros_f&1) == 0 && (zeros_g&1) == 0) this->a[0]= f[0] * g[0];
00112 }
00113 else {
00114 if ((zeros_f&1) == 0) this->a[k] += f[0] * g[k];
00115 if ((zeros_g&1) == 0) this->a[k] += f[k] * g[0];
00116 if ((k&1) == 0) {
00117 nat p= 0;
00118 k += 2;
00119 while ((k&1) == 0 && k != 2) {
00120 p++;
00121 k= k >> 1;
00122 nat len= min (this->l, ((k+2)<<p) - 3) - ((k<<p) - 2);
00123 nat ord= min (((nat) 1)<<p, len);
00124 if (k == 2) {
00125 if (lnz_f < ((int) (1<<p)-1)) zeros_f |= (1<<p);
00126 if (lnz_g < ((int) (1<<p)-1)) zeros_g |= (1<<p);
00127 }
00128 C* aux= mmx_new<C> ((ord << 1) - 1);
00129 if ((zeros_f & (1<<p)) == 0 && lnz_g >= ((int) (((k-1)<<p)-1))) {
00130
00131
00132 Pol::mul (aux, f->a + (1<<p)-1, g->a + ((k-1)<<p)-1, ord, ord);
00133 Pol::add (this->a + (k<<p)-2, aux, len);
00134 }
00135 if (k != 2)
00136 if ((zeros_g & (1<<p)) == 0 && lnz_f >= ((int) (((k-1)<<p)-1))) {
00137
00138
00139 Pol::mul (aux, f->a + ((k-1)<<p)-1, g->a + (1<<p)-1, ord, ord);
00140 Pol::add (this->a + (k<<p)-2, aux, len);
00141 }
00142 mmx_delete<C> (aux, (ord << 1) - 1);
00143 }
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 return this->a [this->n];
00162 }
00163 };
00164
00165 TMPL static inline Series
00166 ser_mul (const Series& f, const Series& g) {
00167 typedef mul_series_rep<C,V> Mul_rep;
00168 if (is_exact_zero (f) || is_exact_zero (g))
00169 return Series (CF(f));
00170 return (Series_rep*) new Mul_rep (f, g); }
00171
00172 TMPL static inline Series
00173 ser_truncate_mul (const Series& f, const Series& g, nat nf, nat ng) {
00174 typedef mul_series_rep<C,V> Mul_rep;
00175 if (is_exact_zero (f) || is_exact_zero (g) || nf == 0 || ng == 0)
00176 return Series (CF(f));
00177 return (Series_rep*)
00178 new Mul_rep (piecewise (f, Series (CF(f)), nf),
00179 piecewise (g, Series (CF(g)), ng)); }
00180
00181 };
00182
00183 #ifdef ALGEBRAMIX_ENABLE_UNSTABLE
00184
00185
00186
00187
00188
00189 TMPL Series compose (const Series& f, nat i, nat p, nat q, Series* H);
00190
00191 TMPL
00192 struct partial_pol_compose_series_rep: public Series_rep {
00193 Series f, h;
00194 nat i, r;
00195 partial_pol_compose_series_rep<C>
00196 (const Series& f2, nat i2, nat p, nat q, Series* H);
00197 generic expression (const generic& z) const {
00198 return gen ("partial_polynomial_compose"); }
00199 void Increase_order (nat l) {
00200 Series_rep::Increase_order (min (l, r));
00201 increase_order (h, min (l, r));
00202 }
00203 C next ();
00204 };
00205
00206 TMPL
00207 partial_pol_compose_series_rep<C>::partial_pol_compose_series_rep (
00208 const Series& f2, nat i2, nat p, nat q, Series* H):
00209 Series_rep (CF(f2)), f (f2), i (i2), r ((p-1) * (q-1) + 1)
00210 {
00211 assert (p > 1);
00212 Series h1= compose (f, i, p>>1, q, H);
00213 Series h2= compose (f, i+ (p>>1), p>>1, q, H);
00214 int d= p>>1;
00215 h= h1+ lshiftz (h2 * rshiftz (H[p>>1], d), d);
00216 }
00217
00218 TMPL C
00219 partial_pol_compose_series_rep<C>::next () {
00220 nat n= this->n;
00221 if (n == r) h= 0;
00222 if (n >= r) return 0;
00223 return h[n];
00224 }
00225
00226 TMPL Series
00227 compose (const Series& f, nat i, nat p, nat q, Series* H) {
00228 if (p == 1) return Series (f[i]);
00229 return (Series_rep*) new partial_pol_compose_series_rep<C> (f, i, p, q, H);
00230 }
00231
00232 TMPL
00233 struct pol_compose_series_rep: public Series_rep {
00234 Series f, *H, h;
00235 nat q;
00236 pol_compose_series_rep<C> (const Series& f, const Series& g, nat q);
00237 ~pol_compose_series_rep<C> () { mmx_classical_delete<Series > (H); }
00238 syntactic expression (const syntactic& z) const {
00239 return apply (GEN_COMPOSE, flatten (f, z), flatten (H[1], z)); }
00240 void Increase_order (nat l) {
00241 Series_rep::Increase_order (l);
00242 increase_order (f, l);
00243 increase_order (h, l);
00244 }
00245 C next ();
00246 };
00247
00248 TMPL
00249 pol_compose_series_rep<C>::pol_compose_series_rep
00250 (const Series& f2, const Series& g, nat q2):
00251 Series_rep (CF(f2)), f (f2), q (q2)
00252 {
00253 H= mmx_classical_new<Series > (2);
00254 H[1]= g;
00255 h= compose (f, 0, 1, q, H);
00256 }
00257
00258 TMPL C
00259 pol_compose_series_rep<C>::next () {
00260 nat n= this->n;
00261 nat k= n;
00262 nat i;
00263 if (k > 0) while ((k&1) == 0) k= k>>1;
00264 if (k == 1) {
00265 if (n > 1) {
00266 Series* H2= mmx_classical_new<Series > (n+1);
00267 for (i=1; i<n; i=i<<1) H2[i]= H[i];
00268 H2[n]= H[n>>1] * H[n>>1];
00269 mmx_classical_delete<Series > (H);
00270 H= H2;
00271 }
00272 h= compose (f, 0, n<<1, q, H);
00273 increase_order (h, this->l);
00274 }
00275 return h[n];
00276 }
00277
00278 TMPL Series
00279 compose (const Series& f, const Series& g, nat q) {
00280 if (is_exact_zero (f)) return Series (CF(f));
00281 ASSERT (g[0] == 0, "constant coefficient must be zero");
00282 return (Series_rep*) new pol_compose_series_rep<C> (f, g, q);
00283 }
00284
00285
00286
00287
00288
00289 template<typename C> C
00290 multiply_range (nat first, nat end) {
00291 if (end == first) return C(1);
00292 else if (end == first+1) return C (first);
00293 nat half= (first + end) >> 1;
00294 return multiply_range<C> (first, half) * multiply_range<C> (half, end);
00295 }
00296
00297 TMPL
00298 class relaxed_compose_series_rep: public Series_rep {
00299 protected:
00300 Series f, g, h;
00301
00302 public:
00303 relaxed_compose_series_rep (const Series& f2, const Series& g2):
00304 Series_rep (CF(f2)), f (f2), g (g2),
00305 h ((Series_rep*) new compose_series_rep<C,V> (f2, g2)) {}
00306 ~relaxed_compose_series_rep () {}
00307
00308 syntactic expression (const syntactic& z) const {
00309 return apply (GEN_COMPOSE, flatten (f, z), flatten (g, z)); }
00310
00311 void Increase_order (nat l) {
00312 Series_rep::Increase_order (l);
00313 increase_order (f, l);
00314 increase_order (g, l);
00315 }
00316
00317 C next () {
00318 nat n= this->n;
00319 if (n==0) return f[0];
00320 if (n==1) return f[1]*g[1];
00321 if (n==2) return f[2]*g[1]*g[1]+ f[1]*g[2];
00322 if (n==3) return (f[3]*g[1]*g[1]+ C(2)*f[2]*g[2])*g[1]+ f[1]*g[3];
00323
00324 nat p=0;
00325 while (((p+1) * (1<<(2*p))) <= n) p++;
00326 if ((n != 4) && ((p * (1<<(2*p-2))) <= (n-1))) return h[n];
00327
00328 nat nn= (p+1) * (1<<(2*p));
00329 nat i, q= 2<<p, r= (nn+q-1)/q;
00330 Series g1 = restrict (g, 0, q);
00331 Series dg1= derive (g1);
00332 Series g2 = rshiftz (g - g1, (int) q);
00333
00334 Series D= f;
00335 for (i=1; i<r; i++) D= derive (D);
00336 D= compose (D, g1, q) / multiply_range<C> (1, r);
00337 h= D;
00338
00339 for (i=r-1; i>0; i--) {
00340 D= (integrate (C(i) * D * dg1)) + f[i-1];
00341 h= D + lshiftz (h*g2, q);
00342 }
00343
00344 increase_order (h, this->l);
00345 return h[n];
00346 }
00347 };
00348
00349 TMPL Series
00350 bk_compose (const Series& f, const Series& g) {
00351
00352 if (is_exact_zero (f)) return Series (CF(f));
00353 ASSERT (g[0] == 0, "constant coefficient must be zero");
00354 return (Series_rep*) new relaxed_compose_series_rep<C> (f, g);
00355 }
00356 #endif // UNSTABLE
00357
00358 #undef TMPL
00359 #undef Series
00360 #undef Series_rep
00361 }
00362 #endif // __MMX__SERIES_RELAXED__HPP