00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef synaps_upol_upoldar_H
00010 #define synaps_upol_upoldar_H
00011
00012 #include <iostream>
00013 #include <synaps/init.h>
00014 #include <synaps/arithm/let.h>
00015 #include <synaps/arithm/sign.h>
00016 #include <synaps/linalg/VECTOR.m>
00017
00018 __BEGIN_NAMESPACE_SYNAPS
00019
00020 namespace let {
00021 template<class A,class B> void assign(A&, const B&);
00022 }
00023 namespace VECTOR {}
00024
00026
00041 namespace UPOLDAR
00042 {
00043
00044 using VECTOR::add;
00045 using VECTOR::sub;
00046 using VECTOR::mul_ext;
00047 using VECTOR::div_ext;
00048
00049
00050 template <class R>
00051 int degree(const R & p)
00052 {
00053
00054 int i = p.size()-1;
00055 while(i>-1 && p[i]==0) i--;
00056 return i;
00057 }
00058
00060 template< class R >
00061 inline
00062 typename R::value_type
00063 lcoeff(const R& p)
00064 {
00065 return p;
00066 }
00067
00069 template< class R >
00070 inline
00071 typename R::value_type
00072 tcoeff(const R& p)
00073 {
00074 return p;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 template <class C>
00101 std::ostream & print_as_coeff(std::ostream & os, const C & c)
00102 {
00103 if(with_plus_sign(c))
00104 os <<"+";
00105 os<<c;
00106 return os;
00107 }
00108
00109 template <class R>
00110 inline std::ostream & print(std::ostream & os, const R & p,char* x = "x")
00111 {
00112 typedef typename R::value_type coeff_t;
00113 bool plus=false;
00114 if ( degree(p)<0) os << '(' << 0 << ')';
00115 else {
00116 for(int i= degree(p); i!= -1; i--)
00117 {
00118 if(p[i]!= 0) {
00119 plus=true;
00120 if(i!=degree(p))
00121 print_as_coeff(os,p[i]);
00122 else
00123 os <<p;
00124 if(i!=0)
00125 {
00126 os<<"*"<<x;
00127 if(i !=1) os<<'^'<<i;
00128 }
00129 }
00130 }
00131 if(!plus) os << '(' << 0 << ')';
00132 }
00133 return os;
00134 }
00135
00136 template <class R, class C>
00137 inline void set_monomial(R & x, const C & c, unsigned n)
00138 {
00139
00140 x.resize(n+1);
00141 VECTOR::init(x,(typename R::value_type)0);
00142 x=c;
00143 checkdegree(x);
00144
00145 }
00146
00147 template <class R, class S>
00148 inline void add_cst( R & r, const R & a, const S & c )
00149 {
00150
00151 };
00152
00153 template <class R, class S>
00154 inline void add_cst(R & r, const S & c)
00155 {
00156 r+=c;
00157 }
00158
00159 template <class R,class A, class B>
00160 inline void mul_index(R & r, const A & a, const B & b)
00161 {
00162 int da=degree(a),
00163 db=degree(b),i,j;
00164 for (i=0;i<=db;i++) {
00165 typename R::value_type bi = b[i];
00166 if (bi==0) continue;
00167 for (j=0;j<=da;j++) {r[i+j] += a[j]*bi;}
00168 }
00169 }
00170
00171 template <class R> inline
00172 void mul_index_it(R & r, const R & a, const R & b)
00173 {
00174 typename R::const_iterator ia, ib;
00175 typename R::iterator ir, it;
00176 ir=r.begin();
00177 for (ib=b.begin();ib !=b.end()&& ir != r.end();++ib) {
00178 typename R::value_type c = *ib;
00179 it=ir;
00180 if (c==0) {++ir;continue;}
00181 for (ia=a.begin();ia!=a.end();++ia,++it) {
00182 (*it)+=(*ia)*c;
00183 }
00184 ++ir;
00185 }
00186 }
00187
00188 template <class R> inline
00189 void mul(R & r, const R & a, const R & b)
00190 {
00191 VECTOR::init(r,0);
00192 mul_index(r,a,b);
00193 }
00194
00195 template <class R> inline
00196 void mul(R & a, const R & b)
00197 {
00198 if(degree(a)>=0 && degree(b)>=0)
00199 {
00200 R ta(a);
00201 a.resize(degree(a)+degree(b)+1);
00202 VECTOR::init(a,0);
00203 mul_index(a,ta,b);
00204 }
00205 else
00206 VECTOR::init(a,0);
00207 }
00208
00209 template <class R> inline
00210 void mul_index(R & a, const R & b)
00211 {
00212 R ta(a);
00213 a.resize(degree(a)+degree(b)+1);
00214 VECTOR::init(a,0);
00215 mul(a,ta,b);
00216 }
00217
00218 template <class R> inline
00219 void mul_karatsuba(R& r, const R & a, const R & b)
00220 {
00221 mul_index(r,a,b);
00222 }
00223
00224 template <class C, class R>
00225 inline C eval_horner(const R & p, const C & c)
00226 {
00227 using namespace let;
00228 C r,cf;
00229 if(degree(p)>0) {
00230 typedef typename R::const_reverse_iterator const_reverse_iterator;
00231 const_reverse_iterator it=p.rbegin();
00232 assign(r,*it); it++;
00233 for(; it !=p.rend(); ++it) {r*=c; assign(cf,*it); r+=cf;}
00234 return r;
00235 } else if(degree(p)>-1)
00236 {
00237 assign(r,p[0]); return r;
00238 }
00239 else
00240 return C(0);
00241 }
00242
00243 template <class C, class R>
00244 inline C eval_horner_idx(const R & p, const C & c)
00245 {
00246 if(degree(p)>0) {
00247 int d=degree(p);
00248 C r=p;
00249 for(int i=d-1; i>-1; --i) {r*=c; r+= p;}
00250 return r;
00251 } else if(degree(p)>-1)
00252 return p[0];
00253 else
00254 return C(0);
00255 }
00256
00257
00258 template<typename POL, typename X> inline
00259 int sign_at(const POL & p, const X& x)
00260 {
00261 X v= eval_horner(p,x);
00262 return sign(v);
00263 }
00264
00265 template <class C, class R>
00266 inline C eval(const R & p, const C & c)
00267 {
00268 return eval_horner(p,c);
00269 }
00270
00271 template<class R>
00272 void div_rem(R & q, R & a, const R & b)
00273 {
00274 typedef typename R::value_type CF;
00275 typedef typename R::iterator iterator;
00276 CF lb = b;
00277 q=0;
00278 while (degree(a)>=degree(b)) {
00279 CF lt(a[degree(a)]/lb);
00280 int s = degree(a)-degree(b);
00281 for ( int i = 0; i < degree(b)+1; i ++ )
00282 a[i+s] -= lt*b[i];
00283 if ( degree(q) < s ) q.resize(s+1);
00284 q = lt;
00285 }
00286
00287 }
00288
00289
00290 template<class R> inline void checkdegree(R & p) {
00291 int d = p.size()-1;
00292 if ( d < 0 ) return;
00293 while ( p[d] == 0 ) d--;
00294 p.resize(d+1);
00295 }
00296
00297 template <class R> inline void diff(R & r, const R & p);
00298
00300 template <class R> inline R diff(const R & p);
00301
00302 template<class R> void reciprocal(R & w,const R & p);
00303
00304 template<class R> void reverse(R & p, typename R::size_type n);
00305
00306 template<class R>
00307 typename R::value_type derive(const R p,typename R::value_type x);
00308
00309 template<class R> void reduce(R & p, const typename R::size_type & e);
00310
00311 template<class R>
00312 void shift(R & t, const typename R::value_type & x0);
00313 template<class R>
00314 void shift(R & t,const R & p,const typename R::value_type & x0);
00315
00316 template<class R, class C>
00317 void scale(R & t,const R & p,const C & l);
00318
00321 template<class R> inline
00322 void diff(R & r, const R & p)
00323 {
00324 int n,i;
00325 r.resize(n=degree(p));
00326 for( i = 1; i < n+1; ++i) r[i-1] =p[i]*i;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00343 template <class R> inline
00344 R diff(const R & p)
00345 {
00346 R r(p);
00347 diff(r,p);
00348 return r;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00373 template <class R>
00374 void reciprocal(R & w,const R & p)
00375 {
00376 typedef typename R::size_type size_type;
00377 typedef typename R::value_type C;
00378
00379 const size_type deg = UPOLDAR::degree(p)+1;
00380 R w0(deg),v(deg),xp(p);
00381 size_type K = (size_type) (log(p.degree()+1)/log(2)),j=1;
00382 C p0 = xp;
00383
00384 xp /= p0;
00385 w0 =xp/xp;
00386 v = w0;
00387 v *= C(-1.0);
00388 v+=C(2);
00389 w=v/xp;
00390 w0=w;
00391 while (j <= K) {
00392 UPOLDAR::reduce(w0,pow(2,j+1));
00393 w=xp*w0;
00394 v =w;
00395 v*=C(-1.0);
00396 v+=C(2);
00397 UPOLDAR::reduce(v,pow(2,j+1));
00398 w=w0*v;
00399 w0=w;
00400 j++;
00401 }
00402 UPOLDAR::reduce(w,deg);
00403 w/=p0;
00404 }
00405
00409 template <class T>
00410 inline void reduce(T & p, const typename T::size_type & e)
00411 {
00412
00413 T temp(e);
00414 for (typename T::size_type i = 0; i < e; i++) temp[i]=p[i];
00415 p.resize(e);
00416
00417 for (typename T::size_type i = 0; i < e; i++) p[i]=temp[i];
00418 }
00419
00429 template <class T>
00430 inline void reverse(T & p, int n)
00431 { for ( int i = 0; i < n/2; i++ ) std::swap(p[i],p[n-i]) ; }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00451 template<class O, class R, class I> inline
00452 void eval( O& p, O& dp, const R& Pol, const I& x )
00453 {
00454 int n = p.size()-1;
00455 p = Pol;
00456 dp = O(0);
00457 for ( int j = n-1; j >= 0; dp = dp*x + p, p =p*x + Pol, j-- );
00458 };
00459
00468 template <class R> inline
00469 typename R::value_type derive( const R& Pol, const typename R::value_type& x )
00470 {
00471 typename R::value_type p,res;
00472 eval(p,res,Pol,x);
00473 return res;
00474 };
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00491 template< class R>
00492 void shift( R& p, const typename R::value_type& c )
00493 {
00494 int j,k,s;
00495 for ( s = p.size(), j = 0; j <= s-2; j++ )
00496 for( k = s-2; k >= j; p += c*p, k-- );
00497 };
00498
00503 template<class R>
00504 void shift(R & r,const R & p,const typename R::value_type & x0)
00505 {
00506 r=p; shift(r,x0);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00525 template<class R, class C>
00526 void scale(R & r, const R & p, const C & l)
00527 {
00528 r.resize(p.size());
00529 r=p;
00530 typename R::value_type s=l;
00531 for(unsigned i=1; i< p.size();i++){
00532 r[i]=p[i]*s;
00533 s *=l;
00534 }
00535 }
00536
00537 template<class R>
00538 void coeff_modulo( R & r, const typename R::value_type & x )
00539 {
00540 for ( typename R::iterator i = r.begin(); i != r.end(); *i %= x, ++i );
00541 };
00542
00543 }
00544
00545 __END_NAMESPACE_SYNAPS
00546
00547 #endif // SYNAPS_UPOL_UPOLDAR_H
00548