00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef SYNAPS_ARITHM_ALGEBRAIC_ASOLVER_H
00017 #define SYNAPS_ARITHM_ALGEBRAIC_ASOLVER_H
00018
00019 #include <synaps/usolve/Algebraic_config.h>
00020 #include <synaps/usolve.h>
00021 #include <synaps/usolve/Method_name.h>
00022 #include <synaps/usolve/Construct_rootof.h>
00023 #include <synaps/upol/SturmSeq.h>
00024 #include <synaps/upol/SquareFree.h>
00025 #include <synaps/usolve/Util.h>
00026 #include <synaps/upol/Bound.h>
00027 #include <synaps/usolve/method_name.h>
00028 #include <stack>
00029
00030
00031 __ALGEBRAIC_BEGIN_NAMESPACE
00032
00033 #if 0
00034
00035
00036
00037 template < typename RT, typename POLY >
00038 void
00039 compute_intermediate_points(const Seq< root_of<RT, POLY> >& V,
00040 Seq< typename NumberTraits<RT>::FT >& Points)
00041 {
00042 typedef root_of<RT, POLY> RO_t;
00043 typedef NumberTraits<RT> NTR;
00044 typedef typename NTR::FT FT;
00045 typedef typename NTR::FIT FIT;
00046
00047 typedef typename Seq<RO_t>::const_iterator IT1;
00048
00049 IT1 it = V.begin();
00050 Points.push_back( FT(it->left() - 1) );
00051
00052 ++it;
00053 for (; it != V.end(); ++it) {
00054 while ( ((it-1)->right() >= it->left()) ) {
00055 (it-1)->refine_interval();
00056 it->refine_interval();
00057 }
00058 Points.push_back( FT(((it - 1)->right() + it->left())/2) );
00059 }
00060 Points.push_back(FT((it-1)->right() + 1));
00061 return;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 template < typename RT,
00073 typename OutputIterator >
00074 OutputIterator
00075 solve( const typename Sturm<RT>::Poly& F,
00076 OutputIterator sol,
00077 unsigned mult,
00078 const Sturm<RT>& mth)
00079 {
00080 typedef typename Sturm<RT>::FT FT;
00081 typedef typename Sturm<RT>::FIT FIT;
00082 typedef typename Sturm<RT>::RO_t RO_t;
00083 typedef typename Sturm<RT>::Poly POLY;
00084
00085 typedef Quadtuple<FT> Quad;
00086
00087 std::stack<Quad> Work;
00088 std::vector<FIT> result;
00089
00090 SturmSeq<RT> sth(F, UPOLDAR::diff(F), SUBRES());
00091
00092 FT b = max_bound(sth[0], Cauchy());
00093 FT a = -b;
00094 POLY h = sth[0];
00095
00096 int Va = Var(sth, a);
00097 int Vb = Var(sth, b);
00098 int V = Va - Vb;
00099
00100 if (V == 0) return sol;
00101 if (V == 1) {
00102 *sol++ = RO_t(sth[0], a, b, mult);
00103 return sol;
00104 }
00105 Work.push( Quad(a, b, Va, Vb) );
00106
00107 POLY x(2, AsSize()); x[1] = RT(1);
00108
00109 while (!Work.empty()) {
00110 Quad q = Work.top();
00111 Work.pop();
00112
00113 FT c = (q.a() + q.b())/2;
00114 if (sign(UPOLDAR::eval_horner(sth[0], c)) == ZERO) {
00115 result.push_back( FIT(c, c) );
00116
00117 POLY t(2, AsSize());
00118 t[1] = denominator(c);
00119 t[0] = -numerator(c);
00120 h = EUCLIDIAN::pquo(h, t);
00121
00122 POLY f = translate(sth[0], c)/x;
00123 FT M = min_bound(f, Cauchy());
00124
00125 int Vc_plus = Var(sth, FT(c + M));
00126
00127 int Vc_minus = Vc_plus + 1;
00128
00129 if (q.Va() == Vc_minus + 1) {
00130 result.push_back( FIT(q.a(), FT(c - M)) );
00131
00132 }
00133 if (q.Va() > Vc_minus + 1) {
00134 Work.push( Quad(q.a(), FT(c - M), q.Va(), Vc_minus) );
00135
00136 }
00137 if (q.Vb() == Vc_plus - 1) {
00138 FIT I(FT(c + M), q.b());
00139 result.push_back( FIT(FT(c + M), q.b()) );
00140
00141 }
00142 if (q.Vb() < Vc_plus - 1) {
00143 Work.push( Quad(c + M, q.b(), Vc_plus, q.Vb()) );
00144
00145 }
00146 } else {
00147 int Vc = Var(sth, c);
00148 if (q.Va() == Vc + 1) {
00149 result.push_back( FIT(q.a(), c) );
00150
00151 }
00152 if (q.Vb() == Vc - 1) {
00153 result.push_back( FIT(c, q.b()) );
00154
00155 }
00156
00157 if (q.Vb() < Vc - 1) {
00158 Work.push( Quad(c, q.b(), Vc, q.Vb()) );
00159
00160 }
00161 if (q.Va() > Vc + 1) {
00162 Work.push( Quad(q.a(), c, q.Va(), Vc) );
00163
00164 }
00165 }
00166
00167 }
00168 std::sort(result.begin(), result.end());
00169 typename std::vector<FIT>::const_iterator it;
00170 for (it = result.begin(); it != result.end(); ++it) {
00171 if (singleton(*it) ) {
00172 RO_t r = make_root_of_1(RT(-numerator(it->lower())), denominator(it->lower()), mth);
00173 r.set_multiplicity(mult);
00174 *sol++ = r;
00175 } else {
00176 *sol++ = RO_t(h, it->lower(), it->upper(), mult);
00177 }
00178 }
00179
00180 return sol;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 template < typename RT,
00190 typename OutputIterator >
00191 OutputIterator
00192 sturm_in_interval( const SturmSeq<RT> StHa,
00193 const typename Sturm<RT>::FIT I,
00194 OutputIterator sol,
00195 unsigned mult,
00196 const Sturm<RT>& MTH)
00197 {
00198 typedef typename Sturm<RT>::FT FT;
00199 typedef typename Sturm<RT>::FIT FIT;
00200 typedef typename Sturm<RT>::Poly Poly;
00201 typedef typename Sturm<RT>::RO_t RO_t;
00202
00203 typedef Quadtuple<FT> Quad;
00204
00205 std::stack<Quad> Work;
00206 std::vector<FIT> result;
00207
00208 FT a = lower(I);
00209 FT b = upper(I);
00210
00211 Poly h = StHa[0];
00212
00213 int Va = Var(StHa, a);
00214 int Vb = Var(StHa, b);
00215 int V = Va - Vb;
00216
00217 if (V == 0) return sol;
00218 if (V == 1) {
00219 *sol++ = RO_t(StHa[0], a, b, mult);
00220 return sol;
00221 }
00222 Work.push( Quad(a, b, Va, Vb) );
00223
00224 Poly x(2, AsSize()); x[1] = RT(1);
00225
00226 while (!Work.empty()) {
00227 Quad q = Work.top();
00228 Work.pop();
00229
00230 FT c = (q.a() + q.b())/2;
00231 if (sign(UPOLDAR::eval_horner(StHa[0], c)) == ZERO) {
00232 result.push_back( FIT(c, c) );
00233
00234 Poly t(2, AsSize());
00235 t[1] = denominator(c);
00236 t[0] = -numerator(c);
00237 h = EUCLIDIAN::pquo(h, t);
00238
00239 Poly f = translate(StHa[0], c)/x;
00240 FT M = min_bound(f, Cauchy());
00241 int Vc_plus = Var(StHa, FT(c + M));
00242
00243 int Vc_minus = Vc_plus + 1;
00244
00245 if (q.Va() == Vc_minus + 1) { result.push_back( FIT(q.a(), FT(c - M)) ); }
00246 if (q.Va() > Vc_minus + 1) { Work.push( Quad(q.a(), FT(c - M), q.Va(), Vc_minus) ); }
00247
00248 if (q.Vb() == Vc_plus - 1) { result.push_back( FIT(FT(c + M), q.b()) ); }
00249 if (q.Vb() < Vc_plus - 1) { Work.push( Quad(c + M, q.b(), Vc_plus, q.Vb()) ); }
00250 } else {
00251 int Vc = Var(StHa, c);
00252 if (q.Va() == Vc + 1) { result.push_back( FIT(q.a(), c) ); }
00253 if (q.Vb() == Vc - 1) { result.push_back( FIT(c, q.b()) ); }
00254
00255 if (q.Vb() < Vc - 1) { Work.push( Quad(c, q.b(), Vc, q.Vb()) ); }
00256 if (q.Va() > Vc + 1) { Work.push( Quad(q.a(), c, q.Va(), Vc) ); }
00257 }
00258 }
00259 std::sort(result.begin(), result.end());
00260 typename std::vector<FIT>::const_iterator it;
00261 for (it = result.begin(); it != result.end(); ++it) {
00262 if (singleton(*it) ) {
00263 RO_t r = make_root_of_1(it->lower(), MTH);
00264 r.set_multiplicity(mult);
00265 *sol++ = r;
00266 } else {
00267 *sol++ = RO_t(h, it->lower(), it->upper(), mult);
00268 }
00269 }
00270 return sol;
00271 }
00272
00273
00274
00275
00276
00277 template < typename NT,
00278 typename OutputIterator >
00279 OutputIterator
00280 solve( const typename Sturm<NT>::Poly& f,
00281 OutputIterator sol,
00282 const Sturm<NT>& mth)
00283 {
00284
00285 typedef typename Sturm<NT>::RT RT;
00286 typedef typename Sturm<NT>::FT FT;
00287 typedef typename Sturm<NT>::FIT FIT;
00288 typedef typename Sturm<NT>::RO_t RO_t;
00289 typedef typename Sturm<NT>::Poly Poly;
00290
00291 if (UPOLDAR::degree(f) < 5) {
00292 return solve(f, sol, Small_degree<RT>());
00293 }
00294
00295 Seq<Poly> PL = SquareFreeFactorization(f);
00296
00297 for (int i = 0; i < PL.size(); ++i) {
00298 if (UPOLDAR::degree(PL[i]) < 5) {
00299
00300 solve(PL[i], sol, i+1, Small_degree<NT>());
00301 } else {
00302
00303 solve(PL[i], sol, i+1, Sturm<NT>());
00304 }
00305 }
00306 return sol;
00307 }
00308
00309 #endif
00310
00312
00313 __ALGEBRAIC_END_NAMESPACE
00314
00315
00316 #endif // SYNAPS_ARITHM_ALGEBRAIC_ASOLVER_H
00317