algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : algebraic_extension.hpp 00004 * DESCRIPTION: Algebraic extensions based on a primitive element 00005 * COPYRIGHT : (C) 2011 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_EXTENSION_HPP 00014 #define __MMX_ALGEBRAIC_EXTENSION_HPP 00015 #include <algebramix/polynomial.hpp> 00016 #include <algebramix/matrix.hpp> 00017 #include <basix/symbol.hpp> 00018 namespace mmx { 00019 #define TMPL_DEF template<typename C> 00020 #define TMPL template<typename C> 00021 #define Polynomial polynomial<C> 00022 #define Extension algebraic_extension<C> 00023 #define Element typename algebraic_extension<C>::El 00024 TMPL class algebraic_extension; 00025 00026 /****************************************************************************** 00027 * The algebraic_extension type 00028 ******************************************************************************/ 00029 00030 TMPL_DEF 00031 class algebraic_extension { 00032 MMX_ALLOCATORS; 00033 public: 00034 Polynomial mp; // minimal polynomial 00035 typedef Polynomial El; // representation of elements 00036 00037 public: 00038 inline algebraic_extension (): 00039 mp () {} 00040 inline algebraic_extension (const format<C>& fm): 00041 mp (vec<C> (promote (0, fm), promote (1, fm))) {} 00042 inline algebraic_extension (const Polynomial& mp2): 00043 mp (mp2) {} 00044 template<typename C2> inline 00045 algebraic_extension (const algebraic_extension<C2>& ext2): 00046 mp (as<Polynomial > (ext2.mp)) {} 00047 inline Polynomial operator * () const { return mp; } 00048 }; 00049 00050 /****************************************************************************** 00051 * Basic operations 00052 ******************************************************************************/ 00053 00054 TMPL inline format<C> CF (const Extension& x) { return CF(*x); } 00055 TMPL inline nat hash (const Extension& x) { return hash (*x); } 00056 TMPL inline nat exact_hash (const Extension& x) { return exact_hash (*x); } 00057 TMPL inline nat hard_hash (const Extension& x) { return hard_hash (*x); } 00058 TMPL inline bool operator == (const Extension& x, const Extension& y) { 00059 return (*x) == (*y); } 00060 TMPL inline bool operator != (const Extension& x, const Extension& y) { 00061 return (*x) != (*y); } 00062 TMPL inline bool exact_eq (const Extension& x, const Extension& y) { 00063 return exact_eq (*x, *y); } 00064 TMPL inline bool exact_neq (const Extension& x, const Extension& y) { 00065 return exact_neq (*x, *y); } 00066 TMPL inline bool hard_eq (const Extension& x, const Extension& y) { 00067 return hard_eq (*x, *y); } 00068 TMPL inline bool hard_neq (const Extension& x, const Extension& y) { 00069 return hard_neq (*x, *y); } 00070 00071 TMPL inline syntactic flatten (const Extension& x) { 00072 return syn ("Extension", flatten (x.mp)); } 00073 00074 TMPL 00075 struct binary_helper<Extension >: public void_binary_helper<Extension > { 00076 typedef Polynomial R; 00077 typedef binary_helper<R> H; 00078 static inline string short_type_name () { 00079 return "Algext" * Short_type_name (C); } 00080 static inline generic full_type_name () { 00081 return gen ("Algebraic_extension", Full_type_name (C)); } 00082 static inline generic disassemble (const Extension& x) { 00083 return binary_disassemble<R> (*x); } 00084 static inline Extension assemble (const generic& x) { 00085 return Extension (binary_assemble<R> (x)); } 00086 static inline void write (const port& out, const Extension& x) { 00087 return H::write (out, *x); } 00088 static inline Extension read (const port& in) { 00089 return H::read (in); } 00090 }; 00091 00092 /****************************************************************************** 00093 * Basic arithmetic 00094 ******************************************************************************/ 00095 00096 TMPL inline Element 00097 square (const Extension& ext, const Element& p1) { 00098 return rem (square (p1), ext.mp); 00099 } 00100 00101 TMPL inline Element 00102 mul (const Extension& ext, const Element& p1, const Element& p2) { 00103 return rem (p1 * p2, ext.mp); 00104 } 00105 00106 TMPL Element 00107 invert (const Extension& ext, const Element& p1) { 00108 Element a= promote (0, p1), b= promote (0, p1), c= gcd (p1, ext.mp, a, b); 00109 return a; 00110 } 00111 00112 TMPL Element 00113 div (const Extension& ext, const C& c1, const Element& p2) { 00114 Element a= promote (0, p2), b= promote (0, p2), c= gcd (p2, ext.mp, a, b); 00115 return c1 * a; 00116 } 00117 00118 TMPL Element 00119 div (const Extension& ext, const Element& p1, const Element& p2) { 00120 Element a= promote (0, p2), b= promote (0, p2), c= gcd (p2, ext.mp, a, b); 00121 return rem (p1 * a, ext.mp); 00122 } 00123 00124 TMPL inline bool 00125 is_zero (const Extension& ext, const Element& p1) { 00126 return deg (p1) < 0; 00127 } 00128 00129 TMPL inline int 00130 sign (const Extension& ext, const Element& p1) { 00131 if (deg (p1) <= 0) return sign (p1[0]); 00132 ERROR ("cannot compute sign"); 00133 } 00134 00135 /****************************************************************************** 00136 * Joining algebraic extensions 00137 ******************************************************************************/ 00138 00139 TMPL vector<C> 00140 shift1 (const Extension& ext1, const Extension& ext2, const vector<C>& v) { 00141 // multiply the bivariate polynomial represented by v with x1 00142 nat d1= deg (ext1.mp), d2= deg (ext2.mp); 00143 vector<C> r= fill<C> (promote (0, CF(ext1)), d1*d2); 00144 for (nat i2=0; i2<d2; i2++) { 00145 vector<C> c= fill<C> (promote (0, CF(ext1)), d1); 00146 for (nat i1=0; i1<d1; i1++) 00147 c[i1]= v[i1*d2 + i2]; 00148 Element p= rem (lshiftz (Element (c), 1), ext1.mp); 00149 for (nat i1=0; i1<d1; i1++) 00150 r[i1*d2 + i2]= p[i1]; 00151 } 00152 return r; 00153 } 00154 00155 TMPL vector<C> 00156 shift2 (const Extension& ext1, const Extension& ext2, const vector<C>& v) { 00157 // multiply the bivariate polynomial represented by v with x2 00158 nat d1= deg (ext1.mp), d2= deg (ext2.mp); 00159 vector<C> r= fill<C> (promote (0, CF(ext1)), d1*d2); 00160 for (nat i1=0; i1<d1; i1++) { 00161 vector<C> c= fill<C> (promote (0, CF(ext1)), d2); 00162 for (nat i2=0; i2<d2; i2++) 00163 c[i2]= v[i1*d2 + i2]; 00164 Element p= rem (lshiftz (Element (c), 1), ext2.mp); 00165 for (nat i2=0; i2<d2; i2++) 00166 r[i1*d2 + i2]= p[i2]; 00167 } 00168 return r; 00169 } 00170 00171 TMPL matrix<C> 00172 mul_matrix (const Extension& ext1, const Extension& ext2, const vector<C>& v) { 00173 // let p (x1, x2) be the bivariate polynomial represented by v 00174 // return the matrix whose rows represent polynomials p (x1, x2) x1^i x2^j 00175 nat d1= deg (ext1.mp), d2= deg (ext2.mp); 00176 matrix<C> r (promote (0, CF(ext1)), d1*d2, d1*d2); 00177 vector<C> aux= fill<C> (promote (0, CF(ext1)), d1*d2); 00178 for (nat i1=0; i1<d1; i1++) { 00179 if (i1 == 0) 00180 for (nat k=0; k<d1*d2; k++) 00181 r (0, k)= v[k]; 00182 else { 00183 for (nat k=0; k<d1*d2; k++) 00184 aux[k]= r((i1-1)*d2, k); 00185 aux= shift1 (ext1, ext2, aux); 00186 for (nat k=0; k<d1*d2; k++) 00187 r(i1*d2, k)= aux[k]; 00188 } 00189 for (nat i2=1; i2<d2; i2++) { 00190 for (nat k=0; k<d1*d2; k++) 00191 aux[k]= r(i1*d2 + i2-1, k); 00192 aux= shift2 (ext1, ext2, aux); 00193 for (nat k=0; k<d1*d2; k++) 00194 r(i1*d2 + i2, k)= aux[k]; 00195 } 00196 } 00197 return r; 00198 } 00199 00200 TMPL matrix<C> 00201 pow_matrix (const Extension& ext1, const Extension& ext2, const vector<C>& v) { 00202 // let p (x1, x2) be the bivariate polynomial represented by v 00203 // return the matrix whose rows represent the powers p (x1, x2)^i 00204 nat d1= deg (ext1.mp), d2= deg (ext2.mp); 00205 matrix<C> m= mul_matrix (ext1, ext2, v); 00206 matrix<C> r (promote (0, CF(ext1)), d1*d2+1, d1*d2); 00207 vector<C> aux= fill<C> (promote (0, CF(ext1)), d1*d2); 00208 aux[0]= promote (1, CF(ext1)); 00209 for (nat i1=0; i1<=d1*d2; i1++) { 00210 for (nat i2=0; i2<d1*d2; i2++) 00211 r (i1, i2)= aux[i2]; 00212 aux= aux * m; 00213 } 00214 return r; 00215 } 00216 00217 TMPL matrix<C> 00218 pow_matrix (const Extension& ext1, const Extension& ext2) { 00219 // return matrix whose rows represent the powers of a primitive element 00220 nat d1= deg (ext1.mp), d2= deg (ext2.mp); 00221 vector<C> v= fill<C> (promote (0, CF(ext1)), d1*d2); 00222 for (nat i=1; i<1000; i++) { 00223 v[1]= promote (1, CF(ext1)); v[d2]= promote ((int) i, CF(ext1)); 00224 matrix<C> m= pow_matrix (ext1, ext2, v); 00225 if (rank (m) == d1*d2) return m; 00226 } 00227 ERROR ("unexpected situation"); 00228 } 00229 00230 template<typename C> polynomial<C> 00231 square_free (const polynomial<C>& p) { 00232 polynomial<C> g= gcd (p, derive (p)); 00233 if (deg (g) == 1) return p; 00234 else return quo (p, g); 00235 } 00236 00237 TMPL Extension 00238 join (const Extension& ext1, const Extension& ext2, Element& z1, Element& z2) { 00239 // Return the smallest common extension ext of ext1 and ext2 00240 // On exit, z1 and z2 contains the primitive els of ext1 and ext2 inside ext 00241 ASSERT (N(ext1.mp) > 0, "uninitialized algebraic extension"); 00242 ASSERT (N(ext2.mp) > 0, "uninitialized algebraic extension"); 00243 if (deg (ext1.mp) == 1) { 00244 z1= Polynomial (-ext1.mp[0]/ext1.mp[1]); 00245 z2= Polynomial (promote (1, CF(ext1)), (nat) 1); 00246 return ext2; 00247 } 00248 else if (deg (ext2.mp) == 1) { 00249 z1= Polynomial (promote (1, CF(ext1)), (nat) 1); 00250 z2= Polynomial (-ext2.mp[0]/ext2.mp[1]); 00251 return ext1; 00252 } 00253 else if (hard_eq (ext1, ext2)) { 00254 z1= Polynomial (promote (1, CF(ext1)), (nat) 1); 00255 z2= Polynomial (promote (1, CF(ext1)), (nat) 1); 00256 return ext1; 00257 } 00258 else { 00259 nat n= deg (ext1.mp) * deg (ext2.mp); 00260 matrix<C> m= transpose (pow_matrix (ext1, ext2)); 00261 matrix<C> u= invert (range (m, 0, 0, n, n)); 00262 vector<C> v= - (u * column (m, n)); 00263 v << promote (1, CF(ext1)); 00264 Polynomial mp= Polynomial (v); 00265 Polynomial sf= square_free (mp); 00266 Extension ext= Extension (sf); 00267 v= fill<C> (promote (0, CF(ext1)), n); 00268 v[deg(ext2.mp)]= promote (1, CF(ext1)); 00269 z1= Element (u * v); 00270 if (deg (sf) < deg (mp)) z1= rem (z1, sf); 00271 v= fill<C> (promote (0, CF(ext1)), n); 00272 v[1]= promote (1, CF(ext1)); 00273 z2= Element (u * v); 00274 if (deg (sf) < deg (mp)) z2= rem (z2, sf); 00275 return ext; 00276 } 00277 } 00278 00279 /****************************************************************************** 00280 * Upgrading to larger algebraic extensions 00281 ******************************************************************************/ 00282 00283 TMPL Element 00284 compose (const Extension& ext, const Polynomial& p, const Element& q) { 00285 // Evaluate p at q in a given extension 00286 Element sum= promote (0, q); 00287 for (int i= deg (p); i>=0; i--) { 00288 if (i != deg (p)) sum= rem (sum * q, ext.mp); 00289 sum += p[i]; 00290 } 00291 return sum; 00292 } 00293 00294 TMPL Extension 00295 upgrade (const Extension& ext1, const Extension& ext2, 00296 Element& p1, Element& p2) 00297 { 00298 if (hard_eq (ext1, ext2)) return ext1; 00299 Element z1= promote (0, CF(ext1)), z2= promote (0, CF(ext1)); 00300 Extension ext= join (ext1, ext2, z1, z2); 00301 if (!hard_eq (ext1, ext)) p1= compose (ext, p1, z1); 00302 if (!hard_eq (ext2, ext)) p2= compose (ext, p2, z2); 00303 return ext; 00304 } 00305 00306 /****************************************************************************** 00307 * Computing the minimal annihilator of an element 00308 ******************************************************************************/ 00309 00310 TMPL Polynomial 00311 annihilator (const Extension& ext, const Element& p) { 00312 nat n= deg (ext.mp); 00313 matrix<C> m (promote (0, CF(ext)), n+1, n); 00314 Element pp= promote (1, CF(ext)); 00315 for (nat i=0; i<=n; i++) { 00316 for (nat j=0; j<N(pp); j++) m (i, j)= pp[j]; 00317 pp= rem (p * pp, ext.mp); 00318 } 00319 matrix<C> e, k; 00320 e= row_echelon (m, k); 00321 for (nat i=0; i<=n; i++) { 00322 bool ok= true; 00323 for (nat j=0; j<n; j++) 00324 if (e (i, j) != 0) ok= false; 00325 if (ok) return square_free (Polynomial (row (k, i))); 00326 } 00327 ERROR ("unexpected situation"); 00328 } 00329 00330 TMPL Extension 00331 normalize (const Extension& ext, const Element& p) { 00332 return Extension (annihilator (ext, p)); 00333 } 00334 00335 TMPL Extension 00336 ramify (const Extension& ext, nat p) { 00337 return Extension (dilate (ext.mp, p)); 00338 } 00339 00340 #undef TMPL_DEF 00341 #undef TMPL 00342 #undef Polynomial 00343 #undef Extension 00344 #undef Element 00345 } // namespace mmx 00346 #endif // __MMX_ALGEBRAIC_EXTENSION_HPP