synaps/msolve/BSolver.h

Go to the documentation of this file.
00001 // Copyright (c) 2003  INRIA Sophia-Antipolis (France) and
00002 //                     Department of Informatics and Telecommunications
00003 //                     University of Athens (Greece).
00004 // All rights reserved.
00005 //
00006 // Authors : Elias P. TSIGARIDAS <et@di.uoa.gr>
00007 
00008 // Partially supported by INRIA's project "CALAMATA", a
00009 // bilateral collaboration with National Kapodistrian University of
00010 // Athens.
00011 // Partially supported by the IST Programme of the EU as a Shared-cost
00012 // RTD (FET Open) Project under Contract No  IST-2000-26473
00013 // (ECG - Effective Computational Geometry for Curves and Surfaces)
00014 //
00015 //--------------------------------------------------------------------
00016 #ifndef SYNAPS_ARITHM_ALGEBRAIC_BSOLVER_H
00017 #define SYNAPS_ARITHM_ALGEBRAIC_BSOLVER_H
00018 //--------------------------------------------------------------------
00019 #include <synaps/init.h>
00020 #include <synaps/usolve/Algebraic.h>
00021 #include <synaps/usolve/algebraic/sign_fct_2.h>
00022 //#include <synaps/usolve/root_of.h>
00023 #include <synaps/mpol/MPoly_2_2.h>
00024 
00025 #include <synaps/usolve/sturm/solve_small.h>
00026 //#include <synaps/solve/sturmsmdeg.h>
00027 #include <synaps/linalg/VectDse.h>
00028 
00029 //--------------------------------------------------------------------
00030 __ALGEBRAIC_BEGIN_NAMESPACE
00031 //--------------------------------------------------------------------
00033 //--------------------------------------------------------------------
00034 
00035 
00036 template<class A>
00037 VectDse<A> make_vector(const A& a, const A& b)
00038 {
00039   VectDse<A> res(2,AsSize());
00040   res[0]=a;res[1]=b;
00041   return res;
00042 }
00043 
00044 
00045 
00046 template < typename SOLVER,
00047            typename OutputIterator >
00048 OutputIterator
00049 solve_for_circles( const typename SOLVER::MPoly_2_2& f1, 
00050                    const typename SOLVER::MPoly_2_2& f2, 
00051                    OutputIterator res, 
00052                    const SOLVER& mth)
00053 {
00054     typedef typename SOLVER::Poly     POLY;
00055     typedef typename SOLVER::RO_t     RO_t;
00056     typedef typename SOLVER::FT       FT;
00057 
00058     POLY Rx = resultant_y<POLY>(f1, f2);
00059     POLY Ry = resultant_x<POLY>(f1, f2);
00060     //  cout << "Rx = " << Rx << endl;
00061     //  cout << "Ry = " << Ry << endl;
00062 
00063     Seq<RO_t> solX;
00064     Seq<RO_t> solY;
00065 
00066     solve(Rx, std::back_inserter(solX.rep()), mth);
00067     solve(Ry, std::back_inserter(solY.rep()), mth);
00068  
00069     // The circles have no intersections
00070     if ((solX.size() == 0) || (solY.size() == 0)) return res;
00071 
00072     // The circles have a tangent intersection
00073     if ((solX.size() == 1) && (solY.size() == 1)){
00074         *res++ = std::make_pair( make_vector(solX[0], solY[0]), static_cast<unsigned>(2) );
00075         return res;
00076     }
00077 
00078     // Two intersections but with the same X-coordinate
00079     if ((solX.size() == 1) && (solY.size() == 2)) {
00080         *res++ = std::make_pair( make_vector(solX[0], solY[0]), static_cast<unsigned>(1) );
00081         *res++ = std::make_pair( make_vector(solX[0], solY[1]), static_cast<unsigned>(1) );
00082         return res;
00083     }
00084 
00085     // Two intersections but with the same Y-coordinate
00086     if ((solX.size() == 2) && (solY.size() == 1)) {
00087         *res++ = std::make_pair( make_vector(solX[0], solY[0]), static_cast<unsigned>(1) );
00088         *res++ = std::make_pair( make_vector(solX[1], solY[0]), static_cast<unsigned>(1) );
00089         return res;
00090     }
00091 
00092     // Two distinct intersections
00093     FT dx = f2.xc() - f1.xc();
00094     FT dy = f2.yc() - f1.yc();
00095   
00096     // From the slope decide how to match the coordinates
00097     bool slope = (sign(dx) * sign(dy) <= 0);
00098     if (slope) {
00099         *res++ = std::make_pair( make_vector(solX[0], solY[0]),static_cast<unsigned>(1) );
00100         *res++ = std::make_pair( make_vector(solX[1], solY[1]),static_cast<unsigned>(1) );
00101     } else {
00102         *res++ = std::make_pair( make_vector(solX[0], solY[1]),static_cast<unsigned>(1) );
00103         *res++ = std::make_pair( make_vector(solX[1], solY[0]),static_cast<unsigned>(1) );
00104     }
00105 
00106     return res;
00107 }
00108 
00109 
00110 
00111 template < typename SOLVER,
00112            typename OutputIterator >
00113 OutputIterator
00114 fast_solve(const typename SOLVER::MPoly_2_2& f1, 
00115            const typename SOLVER::MPoly_2_2& f2, 
00116            OutputIterator ii,
00117            const SOLVER& mth)
00118 {
00119     typedef typename SOLVER::Poly     POLY;
00120     typedef typename SOLVER::RO_t     RO_t;
00121     typedef typename SOLVER::FT       FT;
00122 
00123     POLY Rx = resultant_y<POLY>(f1, f2);
00124     POLY Ry = resultant_x<POLY>(f1, f2);
00125     //  cout << "Rx = " << Rx << endl;
00126     //  cout << "Ry = " << Ry << endl;
00127 
00128     Seq<RO_t> solx = Solve(Rx, mth);
00129     Seq<RO_t> soly = Solve(Ry, mth);
00130   
00131     // Indentify the multiplicities of the roots
00132     std::vector<int> x_multiplicity(solx.size());
00133     for (unsigned int i = 0; i < solx.size(); ++i) {
00134         x_multiplicity[i] = solx[i].multiplicity();
00135     }
00136 
00137     std::vector<int> y_multiplicity(soly.size());
00138     for (unsigned int i = 0; i < soly.size(); ++i) {
00139         y_multiplicity[i] = soly[i].multiplicity();
00140     }
00141 
00142     //  cout << "--- Testing with StHa -------------" << endl;
00143     typename Seq<RO_t>::const_iterator tx, ty;
00144     int i = 0;
00145     for (tx = solx.begin(); tx != solx.end(); ++tx, ++i) {
00146 
00147         POLY xPoly(tx->poly());
00148         FT x_lisol = tx->left();
00149         std::vector<POLY> f1_leftStHa =
00150             compute_StHa_x_cx2y2(f1, xPoly, numerator(x_lisol), denominator(x_lisol));
00151 
00152         FT x_risol = tx->right();
00153         std::vector<POLY> f1_rightStHa =
00154             compute_StHa_x_cx2y2(f1, xPoly, numerator(x_risol), denominator(x_risol));
00155 
00156         std::vector<POLY> f2_leftStHa;
00157         std::vector<POLY> f2_rightStHa;
00158         bool second_computed = false;
00159 
00160         int j = 0;
00161         for (ty = soly.begin(); ty != soly.end(); ++ty, ++j) {
00162             //    cout << "m =" <<  x_multiplicity[i] << " " << y_multiplicity[j] << endl;
00163             if ((x_multiplicity[i] == 0) || (y_multiplicity[j] == 0)) continue;
00164             //    cout << "after " << endl;
00165 
00166             int sgn_a = opposite((tx->degree()-1-tx->which()) % 2 ? NEGATIVE : POSITIVE);
00167             int sgn_b = opposite(sgn_a);
00168 
00169             int V1;
00170             if (tx->degree() == 1) {
00171                 V1 = sign_at(f1_leftStHa[1], *ty);
00172             } else {
00173                 int Va = sign_on_StHa(f1_leftStHa,  sgn_a, *ty);
00174                 int Vb = sign_on_StHa(f1_rightStHa, sgn_b, *ty);
00175                 V1 = Va - Vb;
00176             }
00177             //    cout << "V1 = " << V1 << endl;
00178             if (V1) continue;
00179 
00180             if (!second_computed) {
00181                 //              cout << " In here " << endl;
00182                 f2_leftStHa =
00183                     compute_StHa_x_cx2y2(f2, xPoly, numerator(x_lisol), denominator(x_lisol));
00184 
00185                 f2_rightStHa =
00186                     compute_StHa_x_cx2y2(f2, xPoly, numerator(x_risol), denominator(x_risol));
00187                 second_computed = true;
00188             }
00189             int V2;
00190             if (tx->degree() == 1) {
00191                 V2 = sign_at(f2_leftStHa[1], *ty);
00192             } else {
00193                 int Va = sign_on_StHa(f2_leftStHa,  sgn_a, *ty);
00194                 int Vb = sign_on_StHa(f2_rightStHa, sgn_b, *ty);
00195                 V2 = Va - Vb;
00196             }
00197             //    cout << "V2 = " << V2 << endl;
00198             if (V2) continue;
00199 
00200             // We found a root
00201             *ii++ = make_vector(*tx, *ty);
00202             --x_multiplicity[i];
00203             --y_multiplicity[j];
00204         }
00205         //      cout << " ---- end x ----- " <<endl;
00206     }
00207     return ii;
00208 }
00209 
00210 
00211 
00212 // Compute the solutions of a system of 2 conics, using only bivariate
00213 // @sign_at@ functions.
00214 // Note however that the total number of intersections cannot exceeds the multilicity
00215 // of @X@-coordiante (resp. @Y@). This is taken into account.
00216 // It is very difficult with this functions to compute the multiplicities of the
00217 // intersection points.
00218 template < typename SOLVER,
00219            typename OutputIterator >
00220 OutputIterator
00221 trivial_solve(const typename SOLVER::MPoly_2_2& f1, 
00222               const typename SOLVER::MPoly_2_2& f2,
00223               OutputIterator res,
00224               const SOLVER& mth)
00225 {
00226     std::cout << __FUNCTION__ << std::endl;
00227   
00228     typedef typename SOLVER::Poly     POLY;
00229     typedef typename SOLVER::RO_t     RO_t;
00230 
00231     POLY Rx = resultant_y<POLY>(f1, f2);
00232     POLY Ry = resultant_x<POLY>(f1, f2);
00233 
00234     Seq<RO_t> Xsol = Solve(Rx, mth);
00235     Seq<RO_t> Ysol = Solve(Ry, mth);
00236 
00237     Seq<int> Xmult(Xsol.size());
00238     for (int i = 0; i < Xmult.size(); ++i) Xmult[i] = Xsol[i].multiplicity();
00239 
00240     Seq<int> Ymult(Ysol.size());
00241     for (int i = 0; i < Ymult.size(); ++i) Ymult[i] = Ysol[i].multiplicity();
00242 
00243     for (int i = 0; i < Xsol.size(); ++i) {
00244         for (int j = 0; j < Ysol.size(); ++j) {
00245             if (Ymult[j] == 0) continue;
00246             if (Xmult[i] == 0) break;
00247             if ( (sign_at(f1, Xsol[i], Ysol[j]) == ZERO) && 
00248                  (sign_at(f2, Xsol[i], Ysol[j]) == ZERO) ) {
00249                 *res++ = make_vector( Xsol[i], Ysol[j] );
00250                 --Xmult[i];
00251                 --Ymult[j];
00252             }
00253         }
00254     }
00255     return res;
00256 }
00257 
00258 
00259 
00260 
00261 // Check if the 1st subresultant evaluated over x
00262 // is inside the isolating interval of y
00263 template < typename RO_t >
00264 int
00265 check_where(const RO_t& y, const RO_t& x,
00266             const typename RO_t::POLY& A,
00267             const typename RO_t::POLY& B)
00268 {
00269     typedef typename RO_t::RT     RT;
00270     typedef typename RO_t::FT     FT;
00271     typedef typename RO_t::POLY   POLY;
00272 
00273     POLY P;
00274     FT q;
00275 
00276 
00277 #if 0
00278     // TODO: Do a more clever approximation!!!
00279 
00280     double xx = to_double(x);
00281     double  apx = UPOLDAR::eval_horner(-B, xx) /
00282         UPOLDAR::eval_horner(A, xx);
00283 
00284     if (y.interval().lower() > apx) return SMALLER;
00285     if (y.interval().upper() < apx) return LARGER;
00286     return EQUAL;
00287 #endif
00288 
00289     q = y.left();
00290     P = -B * denominator(q) - A * numerator(q);
00291     if (sign_at(P, x) * sign_at(A, x) < 0) return SMALLER;
00292 
00293     q = y.right();
00294     P = -B * denominator(q) - A * numerator(q);
00295     if (sign_at(P, x) * sign_at(A, x) > 0) return LARGER;
00296 
00297     return EQUAL;
00298 
00299 }
00300 
00301 
00302 
00303 template < typename SOLVER,
00304            typename OutputIterator >
00305 OutputIterator
00306 solve(const typename SOLVER::MPoly_2_2& f1, 
00307       const typename SOLVER::MPoly_2_2& f2,
00308       OutputIterator ii, 
00309       const SOLVER& mth)
00310 {
00311     typedef typename SOLVER::RT       RT;
00312     typedef typename SOLVER::FT       FT;
00313   
00314     typedef typename SOLVER::Poly     POLY;
00315     typedef typename SOLVER::RO_t     RO_t;
00316 
00317     POLY Ax, Bx;
00318     POLY Rx;
00319     resultant_y(f1, f2, Ax, Bx, Rx);
00320 
00321     POLY Ay, By;
00322     POLY Ry;
00323     resultant_x(f1, f2, Ay, By, Ry);
00324 
00325 
00326     std::vector<RO_t> solx;
00327     solve_small_degree(Rx, 1, std::back_inserter(solx), mth);
00328 
00329     std::vector<RO_t> soly;
00330     solve_small_degree(Ry, 1, std::back_inserter(soly), mth);
00331 
00332   
00333     bool x_has_multiplicities = false;
00334     bool y_has_multiplicities = false;
00335 
00336     // Indentify the multiplicities of the roots
00337     std::vector<int> x_multiplicity(solx.size());
00338     for (unsigned int i = 0; i < solx.size(); ++i) {
00339         x_multiplicity[i] = solx[i].multiplicity();
00340         if (x_multiplicity[i] > 1) x_has_multiplicities = true;
00341     }
00342 
00343     std::vector<int> y_multiplicity(soly.size());
00344     for (unsigned int i = 0; i < soly.size(); ++i) {
00345         y_multiplicity[i] = soly[i].multiplicity();
00346         if (y_multiplicity[i] > 1) y_has_multiplicities = true;
00347     }
00348 
00349     // if ( (solx.size() == 2) && (soly.size() == 2))
00350 //     {
00351 //      std::cout << "f1: " << f1 << std::endl;
00352 //      std::cout << "f2: " << f2 << std::endl;
00353 
00354 //      for (int i = 0; i < solx.size(); ++i)
00355 //          std::cout << solx[i].multiplicity() << " ";
00356 //      std::cout << std::endl;
00357 //      for (int i = 0; i < soly.size(); ++i)
00358 //          std::cout << soly[i].multiplicity() << " ";
00359 //      std::cout << std::endl;
00360 //     }
00361 
00362     bool revert = false;
00363     bool solve_by_subres = false;
00364 
00365     if ( (!x_has_multiplicities) && (!y_has_multiplicities) ) {
00366         solve_by_subres = true;
00367     }
00368 
00369     POLY A, B, R;
00370     if (!revert) {
00371         A = Ax; B = Bx; R = Rx;
00372     } else {
00373         std::swap(solx, soly);
00374         A = Ay; B = By; R = Ry;
00375     }
00376 
00377     // We are in generic position, use the 1st subresultant
00378     if (solve_by_subres) {
00379         for (typename std::vector<RO_t>::iterator xt = solx.begin(); xt != solx.end(); ++xt) {
00380             int start = 0;
00381             int end = soly.size() - 1;
00382 
00383             while (start <= end) {
00384                 int mid = static_cast<int>(std::ceil((end-start)/2.0));
00385                 int pos = start + mid;
00386 
00387                 int result = check_where(soly[pos], *xt, A, B);
00388                 if (result == EQUAL) {
00389                     if (!revert) { *ii++ = make_vector(*xt, soly[pos]); }
00390                     else {      *ii++ = make_vector(soly[pos], *xt); }
00391                     typename std::vector<RO_t>::iterator jt = soly.begin() + pos;
00392                     soly.erase(jt);
00393                     break;
00394                 }
00395                 if (result == SMALLER) {
00396                     end = pos - 1;
00397                     continue;
00398                 }
00399                 // result == GREATER
00400                 start = pos + 1;
00401             }
00402         }
00403         return ii;
00404     }
00405 
00406     // We are not in generic position
00407     // cout << "--- Testing with StHa -------------" << endl;
00408     typename Seq<RO_t>::const_iterator tx, ty;
00409     int i = 0;
00410     for (tx = solx.begin(); tx != solx.end(); ++tx, ++i) {
00411 
00412         POLY xPoly(tx->poly());
00413         FT x_lisol = tx->left();
00414         std::vector<POLY> f1_leftStHa =
00415             compute_StHa_x_cx2y2(f1, xPoly, numerator(x_lisol), denominator(x_lisol));
00416 
00417         FT x_risol = tx->right();
00418         std::vector<POLY> f1_rightStHa =
00419             compute_StHa_x_cx2y2(f1, xPoly, numerator(x_risol), denominator(x_risol));
00420 
00421         std::vector<POLY> f2_leftStHa;
00422         std::vector<POLY> f2_rightStHa;
00423         bool second_computed = false;
00424 
00425         int j = 0;
00426         for (ty = soly.begin(); ty != soly.end(); ++ty, ++j) {
00427             if ((x_multiplicity[i] == 0) || (y_multiplicity[j] == 0)) continue;
00428 
00429             int sgn_a = opposite((tx->degree()-1-tx->which()) % 2 ? NEGATIVE : POSITIVE);
00430             int sgn_b = opposite(sgn_a);
00431             int V1;
00432             if (tx->degree() == 1) {
00433                 V1 = sign_at(f1_leftStHa[1], *ty);
00434             } else {
00435                 int Va = sign_on_StHa(f1_leftStHa,  sgn_a, *ty);
00436                 int Vb = sign_on_StHa(f1_rightStHa, sgn_b, *ty);
00437                 V1 = Va - Vb;
00438             }
00439             if (V1) continue;
00440 
00441             if (!second_computed) {
00442                 f2_leftStHa =
00443                     compute_StHa_x_cx2y2(f2, xPoly, numerator(x_lisol), denominator(x_lisol));
00444 
00445                 f2_rightStHa =
00446                     compute_StHa_x_cx2y2(f2, xPoly, numerator(x_risol), denominator(x_risol));
00447                 second_computed = true;
00448             }
00449             int V2;
00450             if (tx->degree() == 1) {
00451                 V2 = sign_at(f2_leftStHa[1], *ty);
00452             } else {
00453                 int Va = sign_on_StHa(f2_leftStHa,  sgn_a, *ty);
00454                 int Vb = sign_on_StHa(f2_rightStHa, sgn_b, *ty);
00455                 V2 = Va - Vb;
00456             }
00457             if (V2) continue;
00458 
00459             // We have found a root
00460             *ii++ = make_vector(*tx, *ty);
00461             --x_multiplicity[i];
00462             --y_multiplicity[j];
00463         }
00464         //      cout << " ---- end x ----- " <<endl;
00465     }
00466 
00467 
00468     return ii;
00469 }
00470 
00471 
00472 
00473 template < typename SOLVER,
00474            typename OutputIterator >
00475 OutputIterator
00476 solve_in_range(const typename SOLVER::MPoly_2_2& f1, 
00477                const typename SOLVER::MPoly_2_2& f2, 
00478                OutputIterator ii,
00479                const typename SOLVER::RO_t& start,
00480                const typename SOLVER::RO_t& end,
00481                const SOLVER& mth)
00482 {
00483     typedef typename SOLVER::RT       RT;
00484     typedef typename SOLVER::FT       FT;
00485 
00486     typedef typename SOLVER::Poly     POLY;
00487     typedef typename SOLVER::RO_t     RO_t;
00488 
00489     POLY Ax, Bx;
00490     POLY Rx;
00491     resultant_y(f1, f2, Ax, Bx, Rx);
00492 
00493     POLY Ay, By;
00494     POLY Ry;
00495     resultant_x(f1, f2, Ay, By, Ry);
00496 
00497     Seq<RO_t> solx = Solve(Rx, mth);
00498     Seq<RO_t> soly = Solve(Ry, mth);
00499   
00500     bool x_has_multiplicities = false;
00501     bool y_has_multiplicities = false;
00502 
00503     // Indentify the multiplicities of the roots
00504     std::vector<int> x_multiplicity(solx.size());
00505     for (unsigned int i = 0; i < solx.size(); ++i) {
00506         x_multiplicity[i] = solx[i].multiplicity();
00507         if (x_multiplicity[i] > 1) x_has_multiplicities = true;
00508     }
00509 
00510     std::vector<int> y_multiplicity(soly.size());
00511     for (unsigned int i = 0; i < soly.size(); ++i) {
00512         y_multiplicity[i] = soly[i].multiplicity();
00513         if (y_multiplicity[i] > 1) y_has_multiplicities = true;
00514     }
00515 
00516     bool solve_by_subres = false;
00517 
00518     if ( (!x_has_multiplicities) && (!y_has_multiplicities) ) {
00519         solve_by_subres = true;
00520     }
00521 
00522     POLY A(Ax);
00523     POLY B(Bx);
00524     POLY R(Rx);
00525 
00526     // We are in generic position, use the 1st subresultant
00527     if (solve_by_subres) {
00528         for (typename Seq<RO_t>::const_iterator xt = solx.begin(); xt != solx.end(); ++xt) {
00529             if ((*xt >= start) && (*xt <= end)) {
00530                 int start = 0;
00531                 int end = soly.size() - 1;
00532 
00533                 while (start <= end) {
00534                     int mid = static_cast<int>(std::ceil((end-start)/2.0));
00535                     int pos = start + mid;
00536 
00537                     int result = check_where(soly[pos], *xt, A, B);
00538                     if (result == EQUAL) {
00539                         *ii++ = make_vector(*xt, soly[pos]);
00540                         break;
00541                     }
00542                     if (result == SMALLER) {
00543                         end = pos - 1;
00544                         continue;
00545                     }
00546                     // result == GREATER
00547                     start = pos + 1;
00548                 }
00549             }
00550         }
00551         return ii;
00552     }
00553 
00554     // We are not in generic position
00555     //  cout << "--- Testing with StHa -------------" << endl;
00556     typename Seq<RO_t>::const_iterator tx, ty;
00557     int i = 0;
00558     for (tx = solx.begin(); tx != solx.end(); ++tx, ++i) {
00559         if ((*tx >= start) && (*tx <= end)) {
00560 
00561             POLY xPoly(tx->poly());
00562             FT x_lisol = tx->left();
00563             std::vector<POLY> f1_leftStHa =
00564                 compute_StHa_x_cx2y2(f1, xPoly, numerator(x_lisol), denominator(x_lisol));
00565 
00566             FT x_risol = tx->right();
00567             std::vector<POLY> f1_rightStHa =
00568                 compute_StHa_x_cx2y2(f1, xPoly, numerator(x_risol), denominator(x_risol));
00569 
00570             std::vector<POLY> f2_leftStHa;
00571             std::vector<POLY> f2_rightStHa;
00572             bool second_computed = false;
00573 
00574             int j = 0;
00575             for (ty = soly.begin(); ty != soly.end(); ++ty, ++j) {
00576                 if ((x_multiplicity[i] == 0) || (y_multiplicity[j] == 0)) continue;
00577 
00578                 int sgn_a = opposite((tx->degree()-1-tx->which()) % 2 ? NEGATIVE : POSITIVE);
00579                 int sgn_b = opposite(sgn_a);
00580                 int V1;
00581                 if (tx->degree() == 1) {
00582                     V1 = sign_at(f1_leftStHa[1], *ty);
00583                 } else {
00584                     int Va = sign_on_StHa(f1_leftStHa,  sgn_a, *ty);
00585                     int Vb = sign_on_StHa(f1_rightStHa, sgn_b, *ty);
00586                     V1 = Va - Vb;
00587                 }
00588                 if (V1) continue;
00589 
00590                 if (!second_computed) {
00591                     f2_leftStHa =
00592                         compute_StHa_x_cx2y2(f2, xPoly, numerator(x_lisol), denominator(x_lisol));
00593 
00594                     f2_rightStHa =
00595                         compute_StHa_x_cx2y2(f2, xPoly, numerator(x_risol), denominator(x_risol));
00596                     second_computed = true;
00597                 }
00598                 int V2;
00599                 if (tx->degree() == 1) {
00600                     V2 = sign_at(f2_leftStHa[1], *ty);
00601                 } else {
00602                     int Va = sign_on_StHa(f2_leftStHa,  sgn_a, *ty);
00603                     int Vb = sign_on_StHa(f2_rightStHa, sgn_b, *ty);
00604                     V2 = Va - Vb;
00605                 }
00606                 if (V2) continue;
00607 
00608                 // We have found a root
00609                 *ii++ = make_vector(*tx, *ty);
00610                 --x_multiplicity[i];
00611                 --y_multiplicity[j];
00612             }
00613             //  cout << " ---- end x ----- " <<endl;
00614         }
00615     }
00616     return ii;
00617 }
00618 
00619 
00620 
00630 template < typename SOLVER, typename O, typename R >
00631 Seq< VectDse< typename SOLVER::RO_t > >
00632 Solve_with_sign( const MPol<typename SOLVER::RT, O, R>& s1, 
00633                  const MPol<typename SOLVER::RT, O, R>& s2,
00634                  const SOLVER& mth)
00635 {
00636     //std::cout << __FUNCTION__ << std::endl;
00637     assert((NbVar(s1) <= 2) && (NbVar(s2) <= 2));
00638 
00639     typedef typename SOLVER::Poly       Poly;
00640     typedef typename SOLVER::Poly_2     Poly_2;
00641     typedef typename SOLVER::RO_t       RO_t;
00642 
00643     Poly_2 f1x = let::convert_to_upoly_2(s1, POLY_wrt_Y);
00644     Poly_2 f2x = let::convert_to_upoly_2(s2, POLY_wrt_Y);
00645 
00646     SturmSeq<Poly> stha(f1x, f2x, HABICHT());
00647     Poly Rx = stha[stha.size() - 1][0];
00648     Seq<RO_t> solx = Solve(Rx, SOLVER());
00649 
00650 
00651     Poly_2 f1y = let::convert_to_upoly_2(s1, POLY_wrt_X);
00652     Poly_2 f2y = let::convert_to_upoly_2(s2, POLY_wrt_X);
00653 
00654     SturmSeq<Poly> sthb(f1y, f2y, HABICHT());
00655     Poly Ry = sthb[sthb.size() - 1][0];
00656     Seq< RO_t > soly = Solve(Ry, SOLVER());
00657 
00658 #if 0
00659     std::cout << "Rx: " << Rx << std::endl;
00660     std::cout << "Ry: " << Ry << std::endl;
00661     for (int i = 0; i < solx.size(); ++i) {
00662         std::cout << to_double(solx[i]) << std::endl;
00663     }
00664     std::cout << "-------" << std::endl;
00665     for (int i = 0; i < soly.size(); ++i) {
00666         std::cout << to_double(soly[i]) << std::endl;
00667     }
00668 #endif
00669 
00670     typedef typename Seq<RO_t>::const_iterator  IT;
00671     std::vector< VectDse<RO_t> > sol;
00672     for (IT xt = solx.begin(); xt != solx.end(); ++xt) {
00673         for (IT yt = soly.begin(); yt != soly.end(); ++yt) {
00674             if ((sign_at(f1x, *xt, *yt) == ZERO) && (sign_at(f2x, *xt, *yt) == ZERO)) {
00675                 sol.push_back( make_vector(*xt, *yt) );
00676             }
00677         }
00678     }
00679 
00680     return sol;
00681 }
00682 
00683 
00684 
00685 
00695 template < typename SOLVER, typename O, typename R >
00696 Seq< std::pair< typename SOLVER::RO_t, typename SOLVER::RO_t > >
00697 Solve_with_subres( const MPol<typename SOLVER::RT, O, R>& F1, 
00698                    const MPol<typename SOLVER::RT, O, R>& F2,
00699                    const SOLVER& mth)
00700 {  
00701     assert((NbVar(F1) <= 2) && (NbVar(F2) <= 2));
00702  
00703     typedef typename SOLVER::RT    RT;
00704 
00705     typedef MPol<RT, O, R>              MPoly;
00706 
00707     typedef typename SOLVER::Poly        Poly;
00708     typedef typename SOLVER::Poly_2      Poly_2;
00709     typedef typename SOLVER::RO_t        RO_t;
00710 
00711     Poly_2 f1y = let::convert_to_upoly_2(F1, POLY_wrt_Y);
00712     Poly_2 f2y = let::convert_to_upoly_2(F2, POLY_wrt_Y);
00713 
00714     Poly_2 f1x = let::convert_to_upoly_2(F1, POLY_wrt_X);
00715     Poly_2 f2x = let::convert_to_upoly_2(F2, POLY_wrt_X);
00716 
00717     int dg_1 = UPOLDAR::degree( UPOLDAR::lcoeff(f1y) );
00718     int dg_2 = UPOLDAR::degree( UPOLDAR::lcoeff(f2y) );
00719     if ((dg_1 >= 1) && (dg_2 >= 1))
00720     {
00721         std::cout << "Linear transformation" << std::endl;
00722         Poly_2 h = construct_X_minus_aY(RT(1));
00723         Poly_2 tf1y = compose(f1y, h);
00724         Poly_2 tf2y = compose(f2y, h);
00725 
00726         //Poly_2 tf1y = changeOfVariable(f1y);
00727         //Poly_2 tf2y = changeOfVariable(f2y);
00728 
00729         //tf1y = changeOfVariable(tf1y);
00730         //tf2y = changeOfVariable(tf2y);
00731 
00732         Poly_2 tf1x = interchange_variables(tf1y);
00733         Poly_2 tf2x = interchange_variables(tf2y);
00734 
00735         std::swap(f1y, tf1y);
00736         std::swap(f2y, tf2y);
00737         std::swap(f1x, tf1x);
00738         std::swap(f2x, tf2x);
00739     }
00740     if ((dg_1 >= 1) && (dg_2 < 1)) {
00741         std::cout << "Do a swap" << std::endl;
00742         std::swap(f1y, f2y);
00743         std::swap(f1x, f2x);
00744     }
00745 
00746     //std::cout << "Done init" << std::endl;
00747     SturmSeq<Poly> StHa_Y(f1y, f2y, HABICHT());
00748     Poly Rx = StHa_Y[StHa_Y.size() - 1][0];
00749     //Seq< root_of<RT> > solx = Solve(Rx, SOLVER<RT>());
00750 
00751 
00752     SturmSeq<Poly> StHa_X(f1x, f2x, HABICHT());
00753     Poly Ry = StHa_X[StHa_X.size() - 1][0];
00754     Seq<RO_t> solY = Solve(Ry, SOLVER());
00755 
00756     Poly Resultant = SquareFree(Rx);
00757 
00758     Seq<Poly> stha_list = CoeffStHa< Seq<Poly> >(StHa_Y);
00759     Seq<Poly> decomposition_list;
00760     Poly Fi = Resultant;
00761     for (int i = 0; i < stha_list.size() -1 ; ++i) {
00762         std::cout << Fi << ", " << stha_list[stha_list.size()-i-2]
00763                   << " gcd = " << PGcd(Fi, stha_list[stha_list.size()-i-2]) << std::endl;
00764         Poly Fin = PGcd(Fi, stha_list[stha_list.size()-i-2]);
00765         std::cout << " / = " << (Fi / Fin) << std::endl;
00766         decomposition_list.push_back(Fi / Fin);
00767         Fi = Fin;
00768     }
00769 
00770 #if 1
00771     {
00772         std::cout << "Rx: " << Rx << std::endl;
00773         Seq< Poly > dec = SquareFreeFactorization(Rx);
00774         for (int i = 0; i < dec.size(); ++i) {
00775             std::cout << i << ": " << dec[i] << std::endl;
00776         }
00777         std::cout << "-----------------------------" << std::endl;
00778     }
00779     {
00780         std::cout << "Ry: " << Ry << std::endl;
00781         Seq< Poly > dec = SquareFreeFactorization(Ry);
00782         for (int i = 0; i < dec.size(); ++i) {
00783             std::cout << i << ": " << dec[i] << std::endl;
00784         }
00785         std::cout << "-----------------------------" << std::endl;
00786         std::cout << "Done resultants" << std::endl;
00787     }
00788 
00789     std::cout << "psc: " << std::endl;
00790     for (int i = 0; i < stha_list.size(); ++i) {
00791         std::cout << i << ": " << stha_list[i] << std::endl;
00792     }
00793     std::cout << std::endl;
00794     std::cout << "decomp" << std::endl;
00795     for (int i = 0; i < decomposition_list.size(); ++i) {
00796         std::cout << i << ": " << decomposition_list[i] << std::endl;
00797     }
00798     std::cout << std::endl;
00799 #endif
00800 
00801 
00802     Seq< VectDse< RO_t > > solutions;
00803 
00804     //std::cout << "Decomp sz: " << decomposition_list.size() << std::endl;
00805     for (int j = 0; j < decomposition_list.size(); ++j) {
00806         if (UPOLDAR::degree(decomposition_list[j]) < 1) continue;
00807 
00808         //cout << "start ------------------------------------------\n";
00809         //cout << j << ": " << decomposition_list[j] << endl;
00810 
00811         Seq<RO_t> solX = Solve(decomposition_list[j], SOLVER());
00812         //std::cout << "solX sz: " << solX.size() << std::endl;
00813 
00814         Poly_2 tp = StHa_Y[ StHa_Y.size() - j - 2 ];
00815         if ((UPOLDAR::degree(tp) >= j) && (j < (StHa_Y.size() - 3))) {
00816             // RUR
00817             //cout << StHa_Y.size() << ", ";
00818             //cout << UPOLDAR::degree(tp) << ", "
00819             //   << j << ", "
00820             //   << (UPOLDAR::degree(tp) >= j) << endl;
00821             //std::cout << j << " tp = " << tp << ", dg: " << UPOLDAR::degree(tp) << endl;
00822             //cout << "StHa: " << StHa_Y[ StHa_Y.size() - j - 2] << endl;
00823             Poly B =  tp[j];
00824             Poly A =  tp[j+1] * (j+1);
00825             for (int k = 0; k < solX.size(); ++k) {
00826                 int start = 0;
00827                 int end = solY.size() - 1;
00828                 while (start <= end) {
00829                     int mid = static_cast<int>(std::ceil((end-start)/2.0));
00830                     int pos = start + mid;
00831 
00832                     int result = check_where(solY[pos], solX[k], A, B);
00833                     if (result == EQUAL) {
00834                         solutions.push_back(make_vector(solX[k], solY[pos]));
00835                         std::cout << "solution\n";
00836                         std::cout << to_double(solX[k]) << ", "
00837                                   << to_double(solY[pos])
00838                                   << " mu ="<< j+1 << std::endl;
00839                         break;
00840                     }
00841                     if (result == SMALLER) {
00842                         end = pos - 1;
00843                         continue;
00844                     }
00845                     // result == GREATER
00846                     start = pos + 1;
00847                 }
00848             }
00849         } else {
00850             std::cout << "Degenerate case ?" << std::endl;
00851         }
00852         //cout << "end------------------------------------------\n";
00853     }
00854     return solutions;
00855 }
00856 
00857 
00858 
00859 
00861 
00862 // compute the relative position of an algebraic number wrt two rational numbers.
00863 // The algebraic number is in RUR (Rational Univariate Representation)
00864 // i.e  y = -B(r) / A(r)
00865 // This function is needed in a series of computations, and so the type of the
00866 // rational number is a pair, where the first element is the number and the second
00867 // is the order of y wrt to this number, if we know it already.
00868 template < typename SOLVER >
00869 int
00870 pos_wrt_point( std::pair< typename SOLVER::FT, int >& isol_point,
00871                const typename SOLVER::RO_t& r,
00872                const typename SOLVER::Poly& A, 
00873                const typename SOLVER::Poly& B,
00874                const SOLVER& )
00875 {
00876     typedef typename SOLVER::RT    RT;
00877     typedef typename SOLVER::FT    FT;
00878     typedef typename SOLVER::Poly  Poly;
00879     typedef typename SOLVER::RO_t  RO_t;
00880 
00881     if (isol_point.second != UNKNOWN) return isol_point.second;    
00882 
00883     int sgnA = sign_at(A, r);
00884   
00885     FT q = isol_point.first;
00886     Poly P  =  B * denominator(q) + A * numerator(q);
00887 
00888     if (sign_at(P, r) * sgnA > 0) isol_point.second = SMALLER;
00889     else isol_point.second = LARGER;
00890 
00891     return isol_point.second;
00892 }
00893 
00894 // IP: are the the intermediate points
00895 template < typename SOLVER >
00896 int
00897 compute_y_in_generic_position( const Seq< typename SOLVER::FT >& IP,
00898                                const typename SOLVER::RO_t& r,
00899                                const typename SOLVER::Poly& A, 
00900                                const typename SOLVER::Poly& B,
00901                                const SOLVER& )
00902 {
00903     typedef typename SOLVER::RT    RT;
00904     typedef typename SOLVER::FT    FT;
00905     typedef typename SOLVER::Poly  Poly;
00906     typedef typename SOLVER::RO_t  RO_t;
00907 
00908     for (int i = 0; i < IP.size(); ++i) {
00909         std::cout << to_double(IP[i]) << "  ";
00910     }
00911     std::cout << std::endl;
00912     double apx = - UPOLDAR::eval_horner(B, to_double(r)) 
00913         / UPOLDAR::eval_horner(A, to_double(r));
00914     std::cout << "(" << to_double(r) << ", " << apx << ")" << std::endl;
00915     
00916     
00917 
00918 
00919     Seq< std::pair<FT, int> > P(IP.size());
00920     for (int i = 0; i < IP.size(); ++i) {
00921         P[i] = make_vector( IP[i], UNKNOWN );
00922     }
00923     P[0].second = LARGER;
00924     P[P.size()-1].second = SMALLER;
00925     
00926     int start = 0;
00927     int end = P.size() - 1;
00928     while (start <= end) {
00929         if ((end - start) == 1) {
00930             assert( (P[start].second == LARGER) && (P[end].second == SMALLER));
00931             return start;
00932         }
00933         
00934         int pos  = static_cast<int>( std::ceil((start+end)/2.0) );
00935         int result = pos_wrt_point(P[pos], r, A, B, SOLVER());
00936         
00937         std::cout << "s, p, e : " << start << ", " << pos << ", " << end << std::endl; 
00938         std::cout << "In " << to_double(IP[start]) << ", " << to_double(IP[end]) << std::endl; 
00939         std::cout << "Testing point: " << to_double(P[pos].first) 
00940                   << " found " << result << std::endl;
00941         if (result == SMALLER) { 
00942             end = pos;
00943             continue;
00944         }
00945         if (result == LARGER) {
00946             start = pos;
00947             continue;
00948         }
00949     }
00950     std::cout << "We must always find a solution" << std::endl;
00951     return -1;
00952 }
00953 
00954 
00955 
00956 
00957 template < typename SOLVER,
00958            typename OutputIterator >
00959 OutputIterator
00960 New_solve(const typename SOLVER::MPoly_2_2& f1, 
00961           const typename SOLVER::MPoly_2_2& f2,
00962           OutputIterator res, 
00963           const SOLVER& mth)
00964 {
00965     std::cout << __FUNCTION__ << std::endl;
00966     
00967     typedef typename SOLVER::RT       RT;
00968     typedef typename SOLVER::FT       FT;
00969   
00970     typedef typename SOLVER::Poly     Poly;
00971     typedef typename SOLVER::RO_t     RO_t;
00972 
00973     Poly Ax, Bx;
00974     Poly Rx;
00975     resultant_y(f1, f2, Ax, Bx, Rx);
00976 
00977     Poly Ay, By;
00978     Poly Ry;
00979     resultant_x(f1, f2, Ay, By, Ry);
00980 
00981 
00982     Seq<RO_t> Xsol = Solve(Rx, SOLVER());
00983     Seq<RO_t> Ysol = Solve(Ry, SOLVER());
00984 
00985     if ((Xsol.size() == 0) || (Ysol.size() == 0)) return res;
00986    
00987 
00988     std::vector<int> Xmult( Xsol.size() );
00989     for (int i = 0; i < Xmult.size(); ++i) Xmult[i] = Xsol[i].multiplicity();
00990     std::vector<int> possible_x_roots = Xmult;
00991   
00992   
00993     std::vector<int> Ymult( Ysol.size() );
00994     for (int i = 0; i < Ymult.size(); ++i) Ymult[i] = Ysol[i].multiplicity();
00995     std::vector<int> possible_y_roots = Ymult;
00996 
00997     unsigned sol_matrix[4][4] = { {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} };
00998             
00999     Seq<FT> Y_isol_points;
01000     compute_intermediate_points(Ysol, Y_isol_points);
01001   
01002 
01003     // std::copy( Xmult.begin(), Xmult.end(),
01004 //             std::ostream_iterator<int>(std::cout, " " ));
01005 //     std::cout << std::endl;
01006 //     std::copy( Ymult.begin(), Ymult.end(),
01007 //             std::ostream_iterator<int>(std::cout, " " ));
01008 //     std::cout << std::endl;  
01009     Poly A(Ax);
01010     Poly B(Bx);
01011     Poly R(Rx);
01012 
01013     for (int i = 0; i < Xsol.size(); ++i) {  
01014         if (Xsol[i].multiplicity() == 1) {
01015             std::cout << "We are in generic position" << std::endl;
01016             int j = compute_y_in_generic_position(Y_isol_points, Xsol[i], A, B, SOLVER());
01017             sol_matrix[i][j] = 1;
01018             //std::cout << "found: " << i << ", " << j << std::endl; 
01019             --possible_x_roots[i];
01020             --possible_y_roots[j];
01021             continue;
01022         }
01023  
01024         if (Xsol[i].is_rational()) {
01025             std::cout << "Check with rational" << std::endl;
01026             // Xsol[i] is rational so left() == right() == Xsol[i]        
01027             FT r = Xsol[i].left();
01028           
01029             Poly sf1 = specialize_x<Poly>(f1, r);
01030             Poly sf2 = specialize_x<Poly>(f2, r);
01031 
01032             for (int j = 0; ((j < Ysol.size()) && possible_x_roots[i]); ++j) {
01033                 if (possible_y_roots[j]) {
01034                     if ((sign_at(sf1, Ysol[j]) == ZERO) && (sign_at(sf2, Ysol[j]) == ZERO)) {
01035                         --possible_x_roots[i];
01036                         --possible_y_roots[j];
01037                         sol_matrix[i][j] = 1;
01038                     }
01039                 }
01040             }
01041             continue;       
01042         }
01043  
01044         std::cout << "Check with sign_at" << std::endl;
01045         for (int j = 0; ((j < Ysol.size()) && possible_x_roots[i]); ++j) {
01046             if (possible_y_roots[j]) {
01047                 if ( (sign_at(f1, Xsol[i], Ysol[j]) == ZERO) && 
01048                      (sign_at(f2, Xsol[i], Ysol[j]) == ZERO) ) {
01049                     --possible_x_roots[i];
01050                     --possible_y_roots[j];
01051                     sol_matrix[i][j] = 1;
01052                 }
01053             }
01054         }
01055         
01056     }
01057     for (int i = 0; i < Xsol.size(); ++i) {
01058         for (int j = 0; j < Ysol.size(); ++j) {
01059             if (sol_matrix[i][j] == 1)
01060                 *res++ = make_vector( Xsol[i], Ysol[j] );
01061         }
01062     }
01063     return res;
01064 }
01065 
01066 
01067 
01068 
01069 //--------------------------------------------------------------------
01070 __ALGEBRAIC_END_NAMESPACE
01071 //--------------------------------------------------------------------
01072 #endif // SYNAPS_ARITHM_ALGEBRAIC_BSOLVER_H
01073 

SYNAPS DOCUMENTATION
logo