algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/algebraic.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : algebraic.hpp
00004 * DESCRIPTION: Algebraic extensions based on a primitive element
00005 * COPYRIGHT  : (C) 2007  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX_ALGEBRAIC_HPP
00014 #define __MMX_ALGEBRAIC_HPP
00015 #include <algebramix/algebraic_extension.hpp>
00016 namespace mmx {
00017 #define TMPL_DEF template<typename C, typename Extension=algebraic_extension<C> >
00018 #define TMPL template<typename C, typename Extension>
00019 #define Polynomial polynomial<C>
00020 #define Algebraic algebraic<C,Extension>
00021 #define Element typename Extension::El
00022 TMPL class algebraic;
00023 TMPL class primitive_element;
00024 
00025 /******************************************************************************
00026 * Trivial extensions
00027 ******************************************************************************/
00028 
00029 template<typename FT, typename C, typename Extension>
00030 struct trivial_extension_helper {
00031   static inline Extension ext () {
00032     return Extension (); }
00033   static inline Extension ext (const format<C>& fm) {
00034     return Extension (fm); }
00035 };
00036 
00037 template<typename C, typename Extension>
00038 struct trivial_extension_helper<empty_format,C,Extension> {
00039   static inline Extension ext () {
00040     static Extension ext= Extension (format<C> ());
00041     return ext; }
00042   static inline Extension ext (const format<C>& fm) {
00043     static Extension ext= Extension (format<C> ());
00044     return ext; }
00045 };
00046 
00047 TMPL inline Extension
00048 trivial_extension () {
00049   typedef typename format<C>::FT FT;
00050   return trivial_extension_helper<FT,C,Extension>::ext ();
00051 }
00052 
00053 TMPL inline Extension
00054 trivial_extension (const format<C>& fm) {
00055   typedef typename format<C>::FT FT;
00056   return trivial_extension_helper<FT,C,Extension>::ext (fm);
00057 }
00058 
00059 /******************************************************************************
00060 * The algebraic type
00061 ******************************************************************************/
00062 
00063 TMPL_DEF
00064 class algebraic {
00065 MMX_ALLOCATORS;
00066 public:
00067   Extension ext;
00068   Element p;
00069 public:
00070   inline algebraic ():
00071     ext (trivial_extension<C,Extension> ()) {}
00072   template<typename T> inline algebraic (const T& c):
00073     ext (trivial_extension<C,Extension> (get_format (as<C> (c)))), p (c) {}
00074   inline algebraic (const Extension ext2, const Polynomial& p2):
00075     ext (ext2), p (p2) {}
00076   inline algebraic (const Polynomial& mp):
00077     ext (mp), p (vec<C> (promote (0, CF(mp)), promote (1, CF(mp)))) {}
00078   template<typename X> inline
00079   algebraic (const Polynomial& mp, const X& x):
00080     ext (mp, x), p (vec<C> (promote (0, CF(mp)), promote (1, CF(mp)))) {}
00081   inline algebraic (const Polynomial& mp, const Polynomial& p2):
00082     ext (mp), p (deg (p2) < deg (mp)? p2: rem (p2, mp)) {}
00083   template<typename X> inline
00084   algebraic (const Polynomial& mp, const Polynomial& p2, const X& x):
00085     ext (mp, x), p (deg (p2) < deg (mp)? p2: rem (p2, mp)) {}
00086   template<typename C2, typename Extension2> inline
00087   algebraic (const algebraic<C2,Extension2>& x2):
00088     ext (field (x2)), p (as<Element > (value (x2))) {}
00089 };
00090 
00091 STYPE_TO_TYPE(TMPL,scalar_type,Algebraic,C);
00092 
00093 TMPL inline format<C> CF (const Algebraic& x) { return CF(x.p); }
00094 TMPL inline Extension field (const Algebraic& x) { return x.ext; }
00095 TMPL inline Element value (const Algebraic& x) { return x.p; }
00096 TMPL inline Polynomial field_modulus (const Algebraic& x) { return x.ext.mp; }
00097 
00098 /******************************************************************************
00099 * Basic routines
00100 ******************************************************************************/
00101 
00102 TMPL inline nat hash (const Algebraic& x) {
00103   nat h= hash (value (x));
00104   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hash (field (x)); }
00105 TMPL inline nat exact_hash (const Algebraic& x) {
00106   nat h= exact_hash (value (x));
00107   return (h<<1) ^ (h<<5) ^ (h>>29) ^ exact_hash (field (x)); }
00108 TMPL inline nat hard_hash (const Algebraic& x) {
00109   nat h= hard_hash (value (x));
00110   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hard_hash (field (x)); }
00111 TMPL inline bool exact_eq (const Algebraic& x1, const Algebraic& x2) {
00112   return exact_eq (value (x1), value (x2)) &&
00113          exact_eq (field (x1), field (x2)); }
00114 TMPL inline bool exact_neq (const Algebraic& x1, const Algebraic& x2) {
00115   return !exact_eq (x1, x2); }
00116 TMPL inline bool hard_eq (const Algebraic& x1, const Algebraic& x2) {
00117   return hard_eq (value (x1), value (x2)) &&
00118          hard_eq (field (x1), field (x2)); }
00119 TMPL inline bool hard_neq (const Algebraic& x1, const Algebraic& x2) {
00120   return !hard_eq (x1, x2); }
00121 
00122 TMPL inline bool is_zero (const Algebraic& x) {
00123   return is_zero (field (x), value (x)); }
00124 TMPL inline int sign (const Algebraic& x) {
00125   return sign (field (x), value (x)); }
00126 TMPL inline bool operator == (const Algebraic& x1, const Algebraic& x2) {
00127   return is_zero (x1 - x2); }
00128 TMPL inline bool operator != (const Algebraic& x1, const Algebraic& x2) {
00129   return !is_zero (x1 - x2); }
00130 
00131 EQUAL_INT_SUGAR(TMPL,Algebraic);
00132 COMPARE_SUGAR(TMPL,Algebraic);
00133 COMPARE_INT_SUGAR(TMPL,Algebraic);
00134 
00135 TMPL syntactic
00136 flatten (const Algebraic& x) {
00137   return apply ("algebraic", flatten (value (x)), flatten (field (x)));
00138 }
00139 
00140 TMPL
00141 struct binary_helper<Algebraic >: public void_binary_helper<Algebraic > {
00142   static inline string short_type_name () {
00143     return "A" * Short_type_name (C); }
00144   static inline generic full_type_name () {
00145     return gen ("Algebraic", Full_type_name (C)); }
00146   static inline generic disassemble (const Algebraic& x) {
00147     return gen_vec (as<generic> (field (x)),
00148                     as<generic> (value (x))); }
00149   static inline Algebraic assemble (const generic& v) {
00150     return Algebraic (as<Extension > (vector_access (v, 0)),
00151                       as<Element > (vector_access (v, 1))); }
00152   static inline void write (const port& out, const Algebraic& p) {
00153     binary_write<Extension > (out, field (p));
00154     binary_write<Element > (out, value (p)); }
00155   static inline Algebraic read (const port& in) {
00156     Extension ext= binary_read<Extension > (in);
00157     Element p= binary_read<Element > (in);
00158     return Algebraic (ext, p); }
00159 };
00160 
00161 /******************************************************************************
00162 * Joining algebraic extensions and minimal annihilators
00163 ******************************************************************************/
00164 
00165 TMPL inline void
00166 upgrade (Algebraic& a1, Algebraic& a2) {
00167   if (hard_neq (field (a1), field (a2))) {
00168     Element p1= value (a1), p2= value (a2);
00169     Extension ext= upgrade (field (a1), field (a2), p1, p2);
00170     a1= Algebraic (ext, p1);
00171     a2= Algebraic (ext, p2);
00172   }
00173 }
00174 
00175 TMPL inline Polynomial
00176 annihilator (const Algebraic& a) {
00177   return annihilator (field (a), value (a));
00178 }
00179 
00180 TMPL inline Algebraic
00181 normalize (const Algebraic& a) {
00182   Extension  ext= normalize (field (a), value (a));
00183   Polynomial pri (vec<C> (promote (0, CF(a)), promote (1, CF(a))));
00184   return Algebraic (ext, pri);
00185 }
00186 
00187 /******************************************************************************
00188 * Basic arithmetic
00189 ******************************************************************************/
00190 
00191 TMPL Algebraic
00192 operator + (const Algebraic& x1b, const Algebraic& x2b) {
00193   Algebraic x1= x1b, x2= x2b;
00194   upgrade (x1, x2);
00195   return Algebraic (field (x1), value (x1) + value (x2));
00196 }
00197 
00198 TMPL inline Algebraic
00199 operator + (const Algebraic& x1, const C& x2) {
00200   return Algebraic (field (x1), value (x1) + x2);
00201 }
00202 
00203 TMPL inline Algebraic
00204 operator + (const C& x1, const Algebraic& x2) {
00205   return Algebraic (field (x2), x1 + value (x2));
00206 }
00207 
00208 TMPL inline Algebraic
00209 operator - (const Algebraic& x) {
00210   return Algebraic (field (x), -value (x));
00211 }
00212 
00213 TMPL Algebraic
00214 operator - (const Algebraic& x1b, const Algebraic& x2b) {
00215   Algebraic x1= x1b, x2= x2b;
00216   upgrade (x1, x2);
00217   return Algebraic (field (x1), value (x1) - value (x2));
00218 }
00219 
00220 TMPL inline Algebraic
00221 operator - (const Algebraic& x1, const C& x2) {
00222   return Algebraic (field (x1), value (x1) - x2);
00223 }
00224 
00225 TMPL inline Algebraic
00226 operator - (const C& x1, const Algebraic& x2) {
00227   return Algebraic (field (x2), x1 - value (x2));
00228 }
00229 
00230 TMPL inline Algebraic
00231 square (const Algebraic& x1) {
00232   return Algebraic (field (x1), square (field (x1), value (x1)));
00233 }
00234 
00235 TMPL Algebraic
00236 operator * (const Algebraic& x1b, const Algebraic& x2b) {
00237   Algebraic x1= x1b, x2= x2b;
00238   upgrade (x1, x2);
00239   return Algebraic (field (x1), mul (field (x1), value (x1), value (x2)));
00240 }
00241 
00242 TMPL inline Algebraic
00243 operator * (const Algebraic& x1, const C& x2) {
00244   return Algebraic (field (x1), value (x1) * x2);
00245 }
00246 
00247 TMPL inline Algebraic
00248 operator * (const C& x1, const Algebraic& x2) {
00249   return Algebraic (field (x2), x1 * value (x2));
00250 }
00251 
00252 TMPL inline Algebraic
00253 invert (const Algebraic& x1) {
00254   return Algebraic (field (x1), invert (field (x1), value (x1)));
00255 }
00256 
00257 TMPL Algebraic
00258 operator / (const C& x1, const Algebraic& x2) {
00259   return Algebraic (field (x2), div (field (x2), x1, value (x2)));
00260 }
00261 
00262 TMPL inline Algebraic
00263 operator / (const Algebraic& x1, const C& x2) {
00264   return Algebraic (field (x1), value (x1) / x2);
00265 }
00266 
00267 TMPL inline Algebraic
00268 operator / (const Algebraic& x1b, const Algebraic& x2b) {
00269   Algebraic x1= x1b, x2= x2b;
00270   upgrade (x1, x2);
00271   return Algebraic (field (x1), div (field (x1), value (x1), value (x2)));
00272 }
00273 
00274 ARITH_SCALAR_INT_SUGAR(TMPL,Algebraic);
00275 
00276 /******************************************************************************
00277 * Roots
00278 ******************************************************************************/
00279 
00280 TMPL inline Algebraic
00281 root (const Algebraic& x, const int& p) {
00282   if (p < 0) return 1 / root (x, -p);
00283   ASSERT (p != 0, "cannot take zero-th roots");
00284   Algebraic  y= normalize (x);
00285   Polynomial z (vec<C> (promote (0, CF(x)), promote (1, CF(x))));
00286   return Algebraic (ramify (field (y), p), z);
00287 }
00288 
00289 TMPL inline Algebraic
00290 sqrt (const Algebraic& x) {
00291   return root (x, 2);
00292 }
00293 
00294 #undef TMPL_DEF
00295 #undef TMPL
00296 #undef Polynomial
00297 #undef Algebraic
00298 #undef Element
00299 } // namespace mmx
00300 #endif // __MMX_ALGEBRAIC_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines