00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00018 #include "config.hpp"
00019 
00020 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00021     defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_algebrslt)
00022 
00023 #include "exception.hpp"
00024 #include "cmp.hpp"
00025 #include "vector.hpp"
00026 #include "sparse_polynom.hpp"
00027 #include "polyalg.hpp"
00028 #include "sturm.hpp"
00029 #include "resultant.hpp"
00030 
00031 #include "algebrslt.hpp"
00032 
00033 
00034 namespace Arageli
00035 {
00036 
00037 
00038 template
00039 <
00040     typename PolyVec,
00041     typename SegVec,
00042     typename Rslt,
00043     typename P,
00044     typename Seg,
00045     typename F
00046 >
00047 void algebraic_func_rslt
00048 (
00049     const PolyVec& polyvec, 
00050     SegVec segvec, 
00051     Rslt rslt, 
00052     P& p, Seg& seg, 
00053     F f 
00054 )
00055 {
00056     
00057 
00058     ARAGELI_ASSERT_0(polyvec.size() == segvec.size());
00059 
00060     
00061 
00062     
00063     
00064 
00065     
00066 
00067     
00068     Rslt gcd_rslt_df = gcd(rslt, diff(rslt));
00069     gcd_rslt_df /= gcd_rslt_df.leading_coef_cpy();  
00070     rslt /= gcd_rslt_df;
00071 
00072     
00073 
00074     rslt = polynom_primpart(rslt);
00075 
00076     
00077 
00078     vector<Rslt, false> ss;
00079     sturm_diff_sys(rslt, ss);
00080     typedef typename vector<Rslt, false>::size_type size_type;
00081 
00082     
00083 
00084     for(;;)
00085     {
00086         seg = f(segvec);
00087 
00088         
00089         
00090 
00091         size_type snr = sturm_number_roots(ss, seg);
00092 
00093         if(snr == 0)
00094             throw invalid_argument
00095             (
00096 
00097 
00098 );
00099         else if(snr == 1)   
00100             break;
00101         else    
00102             for(size_type i = 0; i < polyvec.size(); ++i)
00103                 if(!segvec[i].is_negligible())
00104                     interval_root_dichotomy
00105                     (
00106                         polyvec[i],
00107                         sign(polyvec[i].subs(segvec[i].first())),
00108                         segvec[i]
00109                     );
00110     }
00111 
00112     p = rslt;
00113 
00114     
00115 
00116     
00117     
00118 }
00119 
00120 
00121 namespace _Internal
00122 {
00123 
00124 template <typename T>
00125 struct vector_2_plus_algebraic_helper
00126 {
00127     typename T::value_type operator() (const T& x) const
00128     {
00129         ARAGELI_ASSERT_0(x.size() == 2);
00130         return x.front() + x.back();
00131     }
00132 };
00133 
00134 
00135 template <typename T>
00136 struct vector_2_minus_algebraic_helper
00137 {
00138     typename T::value_type operator() (const T& x) const
00139     {
00140         ARAGELI_ASSERT_0(x.size() == 2);
00141         return x.front() - x.back();
00142     }
00143 };
00144 
00145 
00146 template <typename T>
00147 struct vector_2_multiplies_algebraic_helper
00148 {
00149     typename T::value_type operator() (const T& x) const
00150     {
00151         ARAGELI_ASSERT_0(x.size() == 2);
00152         return x.front() * x.back();
00153     }
00154 };
00155 
00156 
00157 template <typename T>
00158 struct vector_2_divides_algebraic_helper
00159 {
00160     typename T::value_type operator() (const T& x) const
00161     {
00162         ARAGELI_ASSERT_0(x.size() == 2);
00163         return x.front() / x.back();
00164     }
00165 };
00166 
00167 
00168 } 
00169 
00170 
00171 template
00172 <
00173     typename P1, typename Seg1,
00174     typename P2, typename Seg2,
00175     typename P3, typename Seg3
00176 >
00177 void algebraic_plus
00178 (
00179     const P1& p1, const Seg1& seg1,
00180     const P2& p2, const Seg2& seg2,
00181     P3& p3, Seg3& seg3
00182 )
00183 {
00184     typedef sparse_polynom<P1> Pxy;
00185     typedef vector<P1, false> Polyvec;
00186     typedef vector<Seg1, false> Segvec;
00187 
00188     
00189     
00190 
00191     Polyvec polyvec;
00192     polyvec.push_back(p1);
00193     polyvec.push_back(p2);
00194     
00195     Segvec segvec;
00196     segvec.push_back(seg1);
00197     segvec.push_back(seg2);
00198     
00199     P1 rslt = resultant(p1.subs(Pxy("((x)-x)")), p2);
00200 
00201     algebraic_func_rslt
00202     (
00203         polyvec, segvec, rslt, p3, seg3,
00204         _Internal::vector_2_plus_algebraic_helper<Segvec>()
00205     );
00206 }
00207 
00208 
00209 
00210 template
00211 <
00212     typename P1, typename Seg1,
00213     typename P2, typename Seg2,
00214     typename P3, typename Seg3
00215 >
00216 void algebraic_minus
00217 (
00218     const P1& p1, const Seg1& seg1,
00219     const P2& p2, const Seg2& seg2,
00220     P3& p3, Seg3& seg3
00221 )
00222 {
00223     typedef sparse_polynom<P1> Pxy;
00224     typedef vector<P1, false> Polyvec;
00225     typedef vector<Seg1, false> Segvec;
00226 
00227     
00228     
00229 
00230     Polyvec polyvec;
00231     polyvec.push_back(p1);
00232     polyvec.push_back(p2);
00233     
00234     Segvec segvec;
00235     segvec.push_back(seg1);
00236     segvec.push_back(seg2);
00237     
00238     P1 rslt = resultant(p1.subs(Pxy("((x)+x)")), p2);
00239 
00240     algebraic_func_rslt
00241     (
00242         polyvec, segvec, rslt, p3, seg3,
00243         _Internal::vector_2_minus_algebraic_helper<Segvec>()
00244     );
00245 }
00246 
00247 
00248 
00249 template
00250 <
00251     typename P1, typename Seg1,
00252     typename P2, typename Seg2,
00253     typename P3, typename Seg3
00254 >
00255 void algebraic_multiplies
00256 (
00257     const P1& p1, const Seg1& seg1,
00258     const P2& p2, const Seg2& seg2,
00259     P3& p3, Seg3& seg3
00260 )
00261 {
00262     typedef sparse_polynom<P1> Pxy;
00263     typedef vector<P1, false> Polyvec;
00264     typedef vector<Seg1, false> Segvec;
00265 
00266     
00267     
00268 
00269     Polyvec polyvec;
00270     polyvec.push_back(p1);
00271     polyvec.push_back(p2);
00272     
00273     Segvec segvec;
00274     segvec.push_back(seg1);
00275     segvec.push_back(seg2);
00276     
00277     Pxy p1n = reciprocal_poly(p1).subs(Pxy("x"));
00278     typedef typename P1::monom monom;
00279     for(typename Pxy::monom_iterator i = p1n.monoms_begin(); i != p1n.monoms_end(); ++i)
00280         i->coef() *= monom(unit<typename monom::coef_type>(), p1n.degree() - i->degree());
00281     
00282     
00283     P1 rslt = resultant(p1n, p2);
00284 
00285     algebraic_func_rslt
00286     (
00287         polyvec, segvec, rslt, p3, seg3,
00288         _Internal::vector_2_multiplies_algebraic_helper<Segvec>()
00289     );
00290 }
00291 
00292 
00293 
00294 template
00295 <
00296     typename P1, typename Seg1,
00297     typename P2, typename Seg2,
00298     typename P3, typename Seg3
00299 >
00300 void algebraic_divides
00301 (
00302     const P1& p1, const Seg1& seg1,
00303     const P2& p2, Seg2 seg2,
00304     P3& p3, Seg3& seg3
00305 )
00306 {
00307     typedef sparse_polynom<P1> Pxy;
00308     typedef vector<P1, false> Polyvec;
00309     typedef vector<Seg1, false> Segvec;
00310 
00311     
00312     
00313 
00314     Polyvec polyvec;
00315     polyvec.push_back(p1);
00316     polyvec.push_back(p2);
00317 
00318     if(sign(seg2.first())*sign(seg2.second()) <= 0)
00319     {
00320         ARAGELI_ASSERT_0(!is_null(p2.subs(null<typename Seg2::value_type>())));
00321         int lsign = sign(p2.subs(seg2.first()));
00322         
00323         do
00324         {
00325             interval_root_dichotomy(p2, lsign, seg2);
00326         }while(sign(seg2.first())*sign(seg2.second()) <= 0);
00327     }
00328     
00329     Segvec segvec;
00330     segvec.push_back(seg1);
00331     segvec.push_back(seg2);
00332     
00333     P1 rslt = resultant(p1.subs(Pxy("((x)*x)")), p2);
00334 
00335     algebraic_func_rslt
00336     (
00337         polyvec, segvec, rslt, p3, seg3,
00338         _Internal::vector_2_divides_algebraic_helper<Segvec>()
00339     );
00340 }
00341 
00342 
00343 
00344 }
00345 
00346 
00347 #endif  // #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || ...