00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef SYNAPS_UPOL_MODUPOL_H
00010 #define SYNAPS_UPOL_MODUPOL_H
00011
00012 #include <synaps/init.h>
00013 #include <synaps/base/type.h>
00014 #include <synaps/upol/UPOLDAR.m>
00015 #include <synaps/upol/UPolDse.h>
00016 #include <synaps/upol/horner.h>
00017 #include <synaps/linalg/MatrStr.h>
00018 #include <synaps/linalg/hankel.h>
00019 #ifdef FFT
00020 #include <synaps/upol/mult_fft.h>
00021 #endif
00022 #include <synaps/upol/resultant.h>
00023
00024 __BEGIN_NAMESPACE_SYNAPS
00025
00028 namespace quotient
00029 {
00037 template<class C, class R=UPolDse<C> >
00038 struct ModUPol
00039 {
00040
00041 R poly;
00042
00043 typedef typename R::value_type value_type;
00044 typedef typename R::size_type size_type;
00045 typedef typename R::iterator iterator;
00046 typedef typename R::reverse_iterator iterator_r;
00047 typedef upol::horner<C> rep_type;
00048 typedef ModUPol<C,R> self_t;
00049
00050 ModUPol():poly() {}
00051 ModUPol(const R & r): poly(r) {}
00052 ModUPol(const ModUPol<R> & Mod): poly(Mod.poly) {}
00053
00054 template<class S>
00055 void monomial_to_horner(rep_type& h, const S & pol);
00056 template<class S>
00057 void horner_to_monomial(S& h, const rep_type & h);
00058
00059
00060 size_type dim() {return UPOLDAR::degree(poly);}
00061
00062 void assign(rep_type& r, const rep_type & a) {r=a;}
00063 void assign(rep_type& r, const R & a) {monomial_to_horner(r,a);}
00064 void assign(rep_type& r, const value_type & a)
00065 {r.resize(dim()); r[dim()-1]=a/poly[dim()];}
00066 void assign(rep_type& r, int a) {assign(r,value_type(a));}
00067
00068 void add(rep_type& r, const rep_type & a, const rep_type& b);
00069 void add(rep_type& r, const rep_type & a);
00070 void sub(rep_type& r, const rep_type & a, const rep_type& b);
00071 void sub(rep_type& r, const rep_type & a);
00072 void mul(rep_type& r, const rep_type & a, const rep_type& b);
00073 void mul(rep_type& r, const rep_type & a, const C& b);
00074 void div(rep_type& r, const rep_type & a, const C& b);
00075
00076 void square(rep_type& r, const rep_type & a);
00077
00078 void print(std::ostream & os, const rep_type & a)
00079 { R p; horner_to_monomial(p,a); UPOLDAR::print(os,p); }
00080 void read (std::istream & is, rep_type & a);
00081 };
00082
00084 template <class C, class R>
00085 void ModUPol<C,R>::add(rep_type & r,const rep_type & a, const rep_type& b)
00086 {
00087 r.resize(dim()); UPOLDAR::add(r,a,b);
00088 }
00089
00091 template <class C, class R>
00092 void ModUPol<C,R>::add(rep_type & r,const rep_type & a)
00093 {
00094 r.resize(dim()); UPOLDAR::add(r,a);
00095 }
00096
00098 template <class C, class R>
00099 void ModUPol<C,R>::sub(rep_type & r,const rep_type & a, const rep_type& b)
00100 {
00101 r.resize(dim()); UPOLDAR::sub(r,a,b);
00102 }
00103
00105 template <class C, class R>
00106 void ModUPol<C,R>::sub(rep_type & r,const rep_type & a)
00107 {
00108 r.resize(dim()); UPOLDAR::sub(r,a);
00109 }
00110
00112 template <class C, class R>
00113 void ModUPol<C,R>::square(rep_type & x,const rep_type & f)
00114 {
00115 assert(&x != &f);
00116
00117 typedef typename R::value_type value_type;
00118 typedef typename R::size_type size_type;
00119
00120 size_type degree = dim();
00121 size_type M = 2*degree;
00122
00123
00124
00125 x.resize(M); VECTOR::init(x,0);
00126
00127 #ifdef FFT
00128 UPOLDAR::mul_fft(x, poly, f);
00129 #else
00130 UPOLDAR::mul_index(x, poly, f);
00131
00132 #endif
00133
00134
00135 for (size_type i = M-1; i>=degree; i--) x[i]*= value_type(-1);
00136
00137
00138 linalg::rep1d<value_type> res(M+degree-1);
00139
00140 #ifdef FFT
00141 UPOLDAR::mul_fft(res,x,f);
00142 #else
00143 UPOLDAR::mul_index(res,x,f);
00144
00145 #endif
00146
00147
00148 for (size_type j = 0, i = degree; i<M; i++,j++)
00149 x[j] = value_type(-1)*(res[i]);
00150
00151 for(size_type i = degree; i<x.size();++i) x[i]=0;
00152
00153 UPOLDAR::checkdegree(x);
00154
00155 }
00156
00157
00159 template <class C,class R>
00160 void ModUPol<C,R>::mul(rep_type & x, const rep_type & a, const rep_type& b)
00161 {
00162 typedef typename R::size_type size_type;
00163 typedef typename R::value_type value_type;
00164
00165 size_type degree = dim();
00166 rep_type res(degree,type::AsSize()), temp(degree,type::AsSize());
00167
00168 add(temp,a,b);
00169 square(x,temp);
00170 sub(temp,a,b);
00171 square(res,temp);
00172 sub(x,res);
00173 VECTOR::div_ext(x,value_type(4));
00174
00175 }
00176
00177
00184 template <class C, class R>
00185 template<class S>
00186 void ModUPol<C,R>::monomial_to_horner(rep_type &x, const S & pol)
00187 {
00188 typedef typename R::value_type value_type;
00189 typedef typename R::size_type size_type;
00190 typedef typename R::rep_type rep_type;
00191
00192 size_type degree = dim();
00193 rep_type h1(2*degree-1, type::AsSize());
00194 h1[degree-1]=1/poly[degree];
00195 for (size_type i = degree; i < 2*degree-1; i++)
00196 {
00197 for(size_type j=0; j<degree; j++)
00198 h1[i] -= h1[i-degree+j]*poly[j];
00199 h1[i]/=poly[degree];
00200 }
00201
00202
00203
00204
00205 MatrStr<linalg::hankel<value_type> > P(degree, degree, h1.begin());
00206 rep_type tmp(pol.begin(),pol.end());
00207 tmp.resize(degree);
00208 x.resize(degree); VECTOR::init(x,0);
00209 using namespace MATRIX; mul_vect(x,P,tmp);
00210
00211 VECTOR::reverse(x,degree);
00212 }
00213
00214
00221 template <class C, class R>
00222 template<class S>
00223 void ModUPol<C,R>::horner_to_monomial(S &x, const rep_type & pol)
00224 {
00225 typedef typename R::value_type value_type;
00226 typedef typename R::size_type size_type;
00227 typedef typename R::rep_type rep_type;
00228
00229 size_type degree = dim();
00230 rep_type h1(2*degree,type::AsSize());
00231 R r(degree,type::AsSize());
00232
00233
00234
00235 MatrStr<linalg::hankel<value_type> > P =bezout(poly);
00236
00237 S tmp(pol.begin(),pol.end()); tmp.resize(degree);
00238 VECTOR::reverse(tmp,degree);
00239 x.resize(degree); VECTOR::init(x,0);
00240 using namespace MATRIX; mul_vect(x,P,tmp);
00241 }
00242
00243 }
00244 __END_NAMESPACE_SYNAPS
00245
00246 #endif // SYNAPS_UPOL_MODUPOL_H
00247