algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/algebraic_extension.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines