algebraic.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     algebraic.hpp -- Algebraic number declaration.
00004 
00005     This file is a part of the Arageli library.
00006 
00007     Copyright (C) Nikolai Yu. Zolotykh, 1999--2006
00008     Copyright (C) Sergey S. Lyalin, 2006
00009     University of Nizhni Novgorod, Russia
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         //if(seg.is_point())
00062         //  return is_null(poly.subs(seg.first()));
00063         //else
00064         //{
00065         //  vector<Seg, false> lims;
00066         //  sturm<TS>(poly, lims, seg);
00067         //  return lims.size() == 1;
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;    // polynomial with one root in seg segment that identifies the number
00090     Seg seg_m;  // segment where the number located
00091     Config config_m;    // configurator
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     // Creates number as the root of px in segment s.
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     //algebraic (const char* s);
00129 
00130 
00131     operator double () const
00132     {
00133         // WARNING! TEMPORARY!
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 //template <typename TP1, typename TS1, typename Poly1, typename Seg1, typename Cfg1>
00433 //algebraic<TP1, TS1, Poly1, Seg1, Cfg1>::algebraic (const char* s)
00434 //{
00435 //  std::istringstream buf(s);
00436 //  buf >> *this;
00437 //}
00438 
00439 
00440 
00441 
00442 } // namesapce Arageli
00443 
00444 
00445 //#ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00446 //  #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_ALGEBRAIC
00447 //  #include "algebraic.cpp"
00448 //  #undef  ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_ALGEBRAIC
00449 //#endif
00450 
00451 #endif

Generated on Thu Aug 31 17:38:04 2006 for Arageli by  doxygen 1.4.7