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) || ...