00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX_ALGEBRAIC_EXTENSION_HPP
00014 #define __MMX_ALGEBRAIC_EXTENSION_HPP
00015 #include <algebramix/polynomial_rational.hpp>
00016 #include <algebramix/matrix_quotient.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
00028
00029
00030 TMPL_DEF
00031 class algebraic_extension {
00032 MMX_ALLOCATORS;
00033 public:
00034 Polynomial mp;
00035 typedef Polynomial El;
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
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
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
00137
00138
00139 TMPL vector<C>
00140 shift1 (const Extension& ext1, const Extension& ext2, const vector<C>& v) {
00141
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
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
00174
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
00203
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
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
00240
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
00281
00282
00283 TMPL Element
00284 compose (const Extension& ext, const Polynomial& p, const Element& q) {
00285
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
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 }
00346 #endif // __MMX_ALGEBRAIC_EXTENSION_HPP