00001 #ifndef synaps_solve_Symbolic_H
00002 #define synaps_solve_Symbolic_H
00003
00004 #include <synaps/init.h>
00005 #include <synaps/arithm/sign.h>
00006 #include <synaps/upol/UPolDse.h>
00007 #include <synaps/upol/SturmSeq.h>
00008 #include <synaps/usolve/Algebraic.h>
00009 #include <synaps/arithm/symbolic/real.h>
00010 #include <synaps/base/Seq.h>
00011 #include <synaps/usolve/bezier/IslBzBdg.h>
00012 #include <synaps/upol/SturmSeq.h>
00013
00014
00015 __BEGIN_NAMESPACE_SYNAPS
00016
00017 struct Bounding;
00018
00019 template<class C, class SLV= Bezier<C,Bounding> , class X=double>
00020
00021 struct Symbolic
00022 {
00023 X eps;
00024 Symbolic():eps(1.e-6) {}
00025 Symbolic(const X& e):eps(e) {}
00026 Symbolic(const Symbolic & mth): eps(mth.eps) {}
00027 };
00028
00029 namespace symbolic {
00030
00031 template<class C>
00032 struct sqrt_rep : public real_rep<C>
00033 {
00034 protected:
00035 real<C> alpha;
00036 public:
00037
00038 sqrt_rep(real<C> x)
00039 : real_rep<C>(sqrt(x.lower()),sqrt(x.upper())), alpha(x) {};
00040
00041 sqrt_rep(const C & x)
00042 :
00043 real_rep<C>(sqrt(x)-real<C>::eps/2,sqrt(x)+real<C>::eps/2),
00044 alpha(x) {};
00045
00046 C prec() { return this->upper()-this->lower(); }
00047 unsigned improve()
00048 {
00049 if(prec()> real<C>::eps)
00050 {
00051 C m = (this->lower()+this->upper())*0.5;
00052 int s =(alpha>m*m);
00053 if(s==1)
00054 { this->lower()=m; return 1;}
00055 else if(s==-1)
00056 { this->upper()=m; return 1;}
00057 else
00058 return 0;
00059 }
00060 else
00061 return 0;
00062 }
00063
00064 void print(std::ostream & os)
00065 {
00066 os<<"Sqrt["<<this->lower()<<", "<<this->upper()<<"] of "<<alpha;
00067 }
00068 };
00069
00071 template<class C>
00072 struct sqrt
00073 {
00074 protected:
00075 sqrt_rep<C>* _rep;
00076 public:
00077 sqrt(const real<C> & x): _rep(new sqrt_rep<C>(x)) {}
00078 sqrt(const C & x): _rep(new sqrt_rep<C>(x)) {}
00079 inline operator real<C> () { return real<C>(_rep); }
00080 };
00081
00083 template<class C>
00084 real<C> Sqrt(real<C> a) {return sqrt<C>(a);}
00085
00089 template<class C>
00090 real<C> Sqrt(const C a) {return sqrt<C>(a);}
00091
00092
00093 template<class C,class R> struct root_rep;
00094
00095 template<class C,class R>
00096 int sturmcompare(root_rep<C,R>* a, root_rep<C,R>* b)
00097 {
00098 if (a->upper() < b->lower())
00099 return -1;
00100 else if (b->upper() < a->lower())
00101 return 1;
00102 else if (a->poly() == b->poly())
00103 {
00104 if (a->su != b->sl)
00105 return 0;
00106 else
00107 if(a->lower() < b->lower())
00108 return -1;
00109 else if(a->lower()> b->lower())
00110 return 1;
00111 else
00112 return 0;
00113 }
00114 else
00115 {
00116
00117 SturmSeq<R> s(a->poly(), b->poly(), SUBRES());
00118 R l= std::max(a->lower(),b->lower()),
00119 u= std::min(a->upper(),b->upper());
00120 int v0 = variation(s,l) - variation(s,u);
00121 if(v0==0)
00122 if(a->lower() < b->lower())
00123 return -1;
00124 else if(a->lower()> b->lower())
00125 return 1;
00126 else
00127 return 0;
00128 else
00129 return v0 * b->su;
00130 }
00131 }
00132
00133
00134 template<class R, class ZT=R>
00135 struct root_rep: public real_rep<R>, ALGEBRAIC::root_of<ZT>
00136 {
00137 int sl, su;
00138
00139 typedef typename ALGEBRAIC::root_of<ZT>::FT FT;
00140
00141 root_rep(const UPolDse<ZT> & t, const FT & a, const FT &b)
00142 : ALGEBRAIC::root_of<ZT>(t,a,b)
00143 {
00144 let::assign(this->lower(),a);
00145 let::assign(this->upper(),b);
00146 sl=sign(UPOLDAR::eval_horner(this->poly(),this->lower()));
00147 su=sign(UPOLDAR::eval_horner(this->poly(),this->upper()));
00148 }
00149 root_rep(const UPolDse<ZT> & t, const FT & a, const FT &b, unsigned idx)
00150 : ALGEBRAIC::root_of<ZT>(t,a,b,idx)
00151 {
00152 let::assign(this->lower(),a);
00153 let::assign(this->upper(),b);
00154 sl=sign(UPOLDAR::eval_horner(this->poly(),this->lower()));
00155 su=sign(UPOLDAR::eval_horner(this->poly(),this->upper()));
00156 }
00157
00158 root_rep(char *s, const R& a, const R& b)
00159 : real_rep<R>(a,b),
00160 ALGEBRAIC::root_of<ZT>(s)
00161 {
00162 sl=sign(UPOLDAR::eval_horner(this->poly(),a));
00163 su=sign(UPOLDAR::eval_horner(this->poly(),b));
00164 }
00165
00166 UPolDse<ZT> pol() { return this->poly(); }
00167
00168 unsigned improve()
00169 {
00170 if (prec()> real<R>::eps)
00171 {
00172 int s = sign(UPOLDAR::eval_horner(this->poly(),R((this->lower()+this->upper())/2)));
00173 if(s==0) {
00174 this->lower()=(this->lower()+this->upper())/2; this->upper()=this->lower();
00175 }
00176 else if(s*sl<0) {
00177 this->upper()=(this->lower()+this->upper())/2; su=s;
00178 }
00179 else {
00180 this->lower()=(this->lower()+this->upper())/2; sl=s;
00181 }
00182 return 1;
00183 }
00184 else
00185 return 0;
00186 }
00187
00188 R prec() { return this->upper()-this->lower(); }
00189
00190 int compare(real_rep<R>* b)
00191 {
00192 #if 1
00193 if (this->upper() < b->lower()) return -1;
00194 else if (b->upper() < this->lower()) return 1;
00195 else if ( (this->prec() < real<R>::eps) &&
00196 (b->prec() < real<R>::eps) )
00197 return sturmcompare(this, dynamic_cast<root_rep<R,ZT>*>(b));
00198 else
00199 {
00200 int i1=this->improve(), i2=b->improve();
00201 if(i1 || i2)
00202 return (this->compare(b));
00203 }
00204 #endif
00205 return sturmcompare(this, dynamic_cast<symbolic::root_rep<R,ZT>*>(b));
00206 }
00207
00208 void print(std::ostream & os) const
00209 {
00210 os<<"Rootof(";
00211 UPOLDAR::print(os,this->poly());
00212 os<<", ["<<this->lower()<<", "<<this->upper()<<"])";
00213 }
00214 };
00215
00216
00222 template<class R, class Z=R>
00223 struct root
00224 {
00225 typedef typename ALGEBRAIC::root_of<Z>::FT FT;
00226 protected:
00227 root_rep<R,Z>* rep_;
00228 public:
00229 root(const UPolDse<Z> & t, const FT& a, const FT& b)
00230 :rep_(new root_rep<R,Z>(t,a,b)) {}
00231 root(const UPolDse<Z> & t, const FT& a, const FT& b,unsigned idx)
00232 :rep_(new root_rep<R,Z>(t,a,b,idx)) {}
00233 root_rep<R,Z>* operator -> () {return rep_;}
00234 root_rep<R,Z>* operator -> () const {return rep_;}
00235 root_rep<R,Z> rep () {return *rep_;}
00236
00237 inline operator real<R> () { return real<R> (rep_); }
00238 };
00239 }
00240
00242 template<class R>
00243 std::ostream& operator<<(std::ostream& os, const symbolic::root<R> &a)
00244 {
00245 a->print(os);
00246 }
00247
00248
00249
00251 template<class R> inline
00252 bool operator< (symbolic::real<R> a, symbolic::real<R> b)
00253 {
00254 return (a.compare(b)>0);
00255 }
00257 template<class R> inline
00258 bool operator> (symbolic::real<R> a, symbolic::real<R> b)
00259 {
00260 return (a.compare(b)<0);
00261 }
00263 template<class R> inline
00264 bool operator< (const R& a, symbolic::real<R> b) { return (compare(b,a)<0); }
00266 template<class R> inline
00267 bool operator> (const R& a, symbolic::real<R> b) { return (compare(b,a)>0); }
00269 template<class R> inline
00270 bool operator< (symbolic::real<R> a, const R& b) { return (compare(a,b)>0); }
00272 template<class R> inline
00273 bool operator> (symbolic::real<R> a, const R& b) { return (compare(a,b)<0); }
00274
00275
00289 template < typename C_T,
00290 typename UPOL_T >
00291 symbolic::root<C_T,typename UPOL_T::coeff_t> RealRoot(const UPOL_T& p, unsigned idx)
00292 {
00293 typedef typename UPOL_T::coeff_t RT;
00294 typedef typename Sturm<RT>::RO_t RO_t;
00295 typedef std::vector<RO_t> Cont;
00296 typedef std::back_insert_iterator< Cont > OutIter;
00297
00298 Cont sol;
00299 OutIter tt(sol);
00300 Sturm<RT> mth;
00301
00302 ALGEBRAIC::solve_sturm(p, tt, mth);
00303 std::stable_sort( sol.begin(), sol.end(), ALGEBRAIC::Refine_compare());
00304
00305 Seq<RO_t> solutions(sol);
00306 assert(idx<solutions.size());
00307 RO_t s=solutions[idx];
00308 return symbolic::root<C_T,RT>(s.poly(),s.left(),s.right(),idx);
00309 }
00310
00311 template<typename T, typename C>
00312 inline bool has_type(symbolic::real_rep<C>* object)
00313 {
00314 return dynamic_cast<T*>(object) != 0;
00315 }
00316
00317
00318
00319
00323 template<class FT, class C, class MTH>
00324 void AppendSol(Seq< symbolic::real<FT> > & res,
00325 const UPolDse<C> & P,
00326 const Symbolic<FT,MTH> & mth,
00327 const FT& a, const FT & b)
00328 {
00329 assert(a<=b);
00330
00331
00332 typedef FT sol_t;
00333 Seq<Interval<sol_t> > sol = solve(P,IslBzBdg<FT>(1e-2),a,b);
00334
00335
00336 int v0=0;
00337 if(v0==1)
00338 res.push_back(symbolic::root<FT,C>(P,a,b));
00339 else if(v0>1)
00340 {
00341 std::cout<<"Isolation still needed "<<a<<" "<<b<<std::endl;
00342
00343
00344
00345 }
00346 }
00347
00348 template<class FT, class C, class MTH>
00349 void AppendSol(Seq< symbolic::real<FT> > & res,
00350 const UPolDse<C> & P, const Symbolic<FT,MTH> & mth)
00351 {
00352 using let::assign;
00353 typedef typename NumberTraits<C>::FT field_t;
00354 typedef FT sol_t;
00355 SturmSeq<C> s(P, diff(P), HABICHT());
00356 if(degree(s[s.size()-1])!=0)
00357 {
00358 std::cout<<"Not square free"<<std::endl;
00359
00360 }
00361 else
00362 {
00363 Seq<Interval<double> > sol = solve(P, IslBzBdg<double>(1e-3));
00364
00365
00366
00367
00368 FT a,b;
00369 for(unsigned i=0; i<sol.size(); i++)
00370 {
00371 assign(a,sol[i].inf()); assign(b,sol[i].sup());
00372
00373
00374 if(a!= b)
00375 {
00376 int v0 = variation(s,a) - variation(s,b);
00377 if(v0==1)
00378 res.push_back(symbolic::root<FT,C>(P, a, b));
00379 else if(v0>1)
00380 AppendSol(res,P,mth,a,b);
00381 }
00382 else if(P(a)==0)
00383 res.push_back(symbolic::root<FT,C>(P, a, a));
00384
00385 }
00386 }
00387 }
00388
00389
00390 template<class C, class FT>
00391 Seq< symbolic::real<FT> >
00392 solve(const UPolDse<C> & P, const Symbolic<FT> & mth)
00393 {
00394 Seq< symbolic::real<FT> > res;
00395
00396 UPolDse<C> Pr = P;
00397 AppendSol(res, Pr, mth);
00398 return res;
00399 }
00400
00401 __END_NAMESPACE_SYNAPS
00402
00403 #endif // synaps_solve_Symbolic_H
00404