00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00023 #ifndef _ARAGELI_algebraic_hpp_
00024 #define _ARAGELI_algebraic_hpp_
00025
00026 #include "config.hpp"
00027
00028 #include <iostream>
00029 #include <sstream>
00030
00031 #include "_utility.hpp"
00032 #include "factory.hpp"
00033 #include "intalg.hpp"
00034 #include "polyalg.hpp"
00035 #include "sturm.hpp"
00036 #include "algebrslt.hpp"
00037 #include "sparse_polynom.hpp"
00038 #include "rational.hpp"
00039 #include "interval.hpp"
00040
00041 #include "std_import.hpp"
00042
00043
00044 namespace Arageli
00045 {
00046
00047
00048 template <typename TP, typename TS, typename Poly, typename Seg>
00049 struct algebraic_config_default
00050 {
00051 static void init (const Poly& poly, const Seg& seg) { normalize(poly, seg); }
00052 static void get_value (const Poly& poly, const Seg& seg) {}
00053 static void before_oper (const Poly& poly, const Seg& seg) {}
00054 static void after_oper (const Poly& poly, const Seg& seg) { normalize(poly, seg); }
00055
00056 static bool is_normal (const Poly& poly, const Seg& seg)
00057 {
00058 vector<Poly, false> ss;
00059 sturm_diff_sys(poly, ss);
00060 return sturm_number_roots(ss, seg) == 1;
00061
00062
00063
00064
00065
00066
00067
00068
00069 }
00070
00071 static void normalize (const Poly& poly, const Seg& seg)
00072 {
00073 ARAGELI_ASSERT_0(is_normal(poly, seg));
00074 }
00075 };
00076
00077
00079 template
00080 <
00081 typename TP = rational<>,
00082 typename TS = TP,
00083 typename Poly = sparse_polynom<TP>,
00084 typename Seg = interval<TS>,
00085 typename Config = algebraic_config_default<TP, TS, Poly, Seg>
00086 >
00087 class algebraic
00088 {
00089 Poly poly_m;
00090 Seg seg_m;
00091 Config config_m;
00092
00093 template <typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2>
00094 friend class algebraic;
00095
00096 public:
00097
00098 typedef TP base_type;
00099 typedef TS interval_limit_type;
00100 typedef Poly polynom_type;
00101 typedef Seg interval_type;
00102 typedef Config config_type;
00103
00105 algebraic () : poly_m(null<TP>()), seg_m(null<TS>()) {}
00106
00108 algebraic (const TS& x) : seg_m(x)
00109 {
00110 poly_m += typename Poly::monom(unit<TP>(), 1);
00111 poly_m -= TP(x);
00112 }
00113
00115 algebraic (const Poly& px) : poly_m(px)
00116 {
00117 vector<Seg, false> lims;
00118 sturm(px, lims);
00119 ARAGELI_ASSERT_0(!lims.is_empty());
00120 seg_m = lims.front();
00121 }
00122
00123
00124 algebraic (const Poly& px, const Seg& s) : poly_m(px), seg_m(s)
00125 { config_m.init(poly_m, seg_m); }
00126
00127
00128
00129
00130
00131 operator double () const
00132 {
00133
00134 interval<rational<> > fseg = seg_m;
00135 interval_root_precise(poly_m, fseg, rational<>("1/100000000000"));
00136 return fseg.first();
00137 }
00138
00139
00141 const Poly& polynom () const
00142 {
00143 config_m.get_value(poly_m, seg_m);
00144 return poly_m;
00145 }
00146
00148 const Seg& segment () const { return seg_m; }
00149
00151 Poly& polynom ()
00152 {
00153 config_m.get_value(poly_m, seg_m);
00154 return poly_m;
00155 }
00156
00158 Seg& segment () { return seg_m; }
00159
00160
00162 bool is_normal () const { return config_m.is_normal(poly_m, seg_m); }
00163
00165 void normalize () const { config_m.normalize(poly_m, seg_m); }
00166
00167
00168 algebraic operator- () const
00169 {
00170 if(is_null(poly_m) && is_null(seg_m))return *this;
00171
00172 ARAGELI_ASSERT_0(is_normal());
00173 Poly poly_res; Seg seg_res;
00174
00175 algebraic_minus
00176 (
00177 Poly(unit<TP>(), 1), seg(null<TS>()),
00178 poly_m, seg_m, poly_res, seg_res
00179 );
00180
00181 return algebraic(poly_res, seg_res);
00182 }
00183
00184 const algebraic& operator+ () const { return *this; }
00185
00186 algebraic& operator++ ()
00187 {
00188 *this += algebraic(unit<TP>());
00189 return *this;
00190 }
00191
00192 algebraic& operator-- ()
00193 {
00194 *this -= algebraic(unit<TP>());
00195 return *this;
00196 }
00197
00198 algebraic operator++ (int) { algebraic t = *this; operator++(); return t; }
00199 algebraic operator-- (int) { algebraic t = *this; operator--(); return t; }
00200
00201 template <typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2>
00202 algebraic& operator+= (const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& x)
00203 {
00204 ARAGELI_ASSERT_0(is_normal() && x.is_normal());
00205 algebraic_plus(poly_m, seg_m, x.poly_m, x.seg_m, poly_m, seg_m);
00206 ARAGELI_ASSERT_0(is_normal());
00207 return *this;
00208 }
00209
00210 template <typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2>
00211 algebraic& operator-= (const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& x)
00212 {
00213 ARAGELI_ASSERT_0(is_normal() && x.is_normal());
00214 algebraic_minus(poly_m, seg_m, x.poly_m, x.seg_m, poly_m, seg_m);
00215 ARAGELI_ASSERT_0(is_normal());
00216 return *this;
00217 }
00218
00219 template <typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2>
00220 algebraic& operator*= (const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& x)
00221 {
00222 ARAGELI_ASSERT_0(is_normal() && x.is_normal());
00223 algebraic_multiplies(poly_m, seg_m, x.poly_m, x.seg_m, poly_m, seg_m);
00224 ARAGELI_ASSERT_0(is_normal());
00225 return *this;
00226 }
00227
00228 template <typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2>
00229 algebraic& operator/= (const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& x)
00230 {
00231 ARAGELI_ASSERT_0(is_normal() && x.is_normal());
00232 algebraic_divides(poly_m, seg_m, x.poly_m, x.seg_m, poly_m, seg_m);
00233 ARAGELI_ASSERT_0(is_normal());
00234 return *this;
00235 }
00236
00237 bool is_null () const { return is_equal_const(null<TP>()); }
00238
00239 bool is_unit () const { return is_equal_const(unit<TP>()); }
00240 bool is_opposite_unit () const { return is_equal_const(opposite_unit<TP>()); }
00241
00242
00243 bool operator! () const { return is_null(); }
00244 operator bool () const { return !is_null(); }
00245
00246 private:
00247
00248 bool is_equal_const (const TP& x) const
00249 {
00250 ARAGELI_ASSERT_0(is_normal());
00251 return
00252 x >= seg_m.first() && x <= seg_m.second() &&
00253 Arageli::is_null(poly_m.subs(x));
00254 }
00255
00256
00257 };
00258
00259
00260 template <typename TP, typename TS, typename Poly, typename Seg, typename Cfg>
00261 struct factory<algebraic<TP, TS, Poly, Seg, Cfg> >
00262 {
00263 private:
00264
00265 typedef algebraic<TP, TS, Poly, Seg, Cfg> T;
00266
00267 public:
00268
00269 static const bool is_specialized = true;
00270
00272 static const T& unit ()
00273 {
00274 static const T unit_s = T(Arageli::unit<TS>());
00275 return unit_s;
00276 }
00277
00279 static const T& unit (const T& x)
00280 { return unit(); }
00281
00283 static const T& opposite_unit ()
00284 {
00285 static const T opposite_unit_s = T(Arageli::opposite_unit<TS>());
00286 return opposite_unit_s;
00287 }
00288
00290 static const T& opposite_unit (const T& x)
00291 { return opposite_unit(); }
00292
00294 static const T& null ()
00295 {
00296 static const T null_s = T(Arageli::null<TS>());
00297 return null_s;
00298 }
00299
00301 static const T& null (const T& x)
00302 { return null(); }
00303
00304 };
00305
00306
00307 #define ARAGELI_ALGEBRAIC_BINARY_OP(OP, OPASS) \
00308 template \
00309 < \
00310 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1, \
00311 typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2 \
00312 > \
00313 inline algebraic<TP1, TS1, Poly1, Seg1, Cfg1> operator OP \
00314 ( \
00315 algebraic<TP1, TS1, Poly1, Seg1, Cfg1> a, \
00316 const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& b \
00317 ) \
00318 { return a OPASS b; }
00319
00320 ARAGELI_ALGEBRAIC_BINARY_OP(+, +=)
00321 ARAGELI_ALGEBRAIC_BINARY_OP(-, -=)
00322 ARAGELI_ALGEBRAIC_BINARY_OP(*, *=)
00323 ARAGELI_ALGEBRAIC_BINARY_OP(/, /=)
00324 ARAGELI_ALGEBRAIC_BINARY_OP(%, %=)
00325
00326
00327 #define ARAGELI_ALGEBRAIC_LOGIC_OP(OP) \
00328 template \
00329 < \
00330 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1, \
00331 typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2 \
00332 > \
00333 inline bool operator OP \
00334 ( \
00335 const algebraic<TP1, TS1, Poly1, Seg1, Cfg1>& a, \
00336 const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& b \
00337 ) \
00338 { return cmp(a, b) OP 0; } \
00339 \
00340 template \
00341 < \
00342 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1, \
00343 typename TS2 \
00344 > \
00345 inline bool operator OP \
00346 ( \
00347 const algebraic<TP1, TS1, Poly1, Seg1, Cfg1>& a, \
00348 const TS2& b \
00349 ) \
00350 { return cmp(a, algebraic<TP1, TS2, Poly1, Seg1, Cfg1>(b)) OP 0; } \
00351 \
00352 template \
00353 < \
00354 typename TS1, \
00355 typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2 \
00356 > \
00357 inline bool operator OP \
00358 ( \
00359 const TS1& a, \
00360 const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& b \
00361 ) \
00362 { return cmp(algebraic<TP2, TS1, Poly2, Seg2, Cfg2>(a), b) OP 0; }
00363
00364
00365
00366 ARAGELI_ALGEBRAIC_LOGIC_OP(==)
00367 ARAGELI_ALGEBRAIC_LOGIC_OP(!=)
00368 ARAGELI_ALGEBRAIC_LOGIC_OP(<)
00369 ARAGELI_ALGEBRAIC_LOGIC_OP(<=)
00370 ARAGELI_ALGEBRAIC_LOGIC_OP(>)
00371 ARAGELI_ALGEBRAIC_LOGIC_OP(>=)
00372
00373
00374 template
00375 <
00376 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1,
00377 typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2
00378 >
00379 int cmp
00380 (
00381 const algebraic<TP1, TS1, Poly1, Seg1, Cfg1>& a,
00382 const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& b
00383 )
00384 {
00385 algebraic<TP1, TS1, Poly1, Seg1, Cfg1> c = a - b;
00386 if(c.is_null())return 0;
00387 int lsign = sign(c.polynom().subs(c.segment().first()));
00388 while(sign(c.segment().first())*sign(c.segment().second()) <= 0)
00389 interval_root_dichotomy(c.polynom(), lsign, c.segment());
00390 return sign(c.segment().first());
00391 }
00392
00393
00394 template
00395 <
00396 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1,
00397 typename TP2
00398 >
00399 inline int cmp
00400 (
00401 const algebraic<TP1, TS1, Poly1, Seg1, Cfg1>& a,
00402 const TP2& b
00403 )
00404 { return cmp(a, algebraic<TP2, TS1, Poly1, Seg1, Cfg1>(b)); }
00405
00406
00407 template
00408 <
00409 typename TP1,
00410 typename TP2, typename TS2, typename Poly2, typename Seg2, typename Cfg2
00411 >
00412 inline int cmp
00413 (
00414 const TP1& a,
00415 const algebraic<TP2, TS2, Poly2, Seg2, Cfg2>& b
00416 )
00417 { return cmp(algebraic<TP1, TS2, Poly2, Seg2, Cfg2>(a), b); }
00418
00419
00420 template
00421 <
00422 typename Out,
00423 typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1
00424 >
00425 inline Out& operator<< (Out& out, const algebraic<TP1, TS1, Poly1, Seg1, Cfg1>& x)
00426 {
00427 out << "(" << x.polynom() << ", " << x.segment() << ")";
00428 return out;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451 #endif