algebramix_doc 0.3
|
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