[10af64] | 1 | // -*- c++ -*- |
---|
| 2 | //***************************************************************************** |
---|
[51615d6] | 3 | /** @file cf_map_ext.cc |
---|
[10af64] | 4 | * |
---|
[806c18] | 5 | * @author Martin Lee |
---|
[10af64] | 6 | * @date 16.11.2009 |
---|
| 7 | * |
---|
| 8 | * This file implements functions to map between extensions of finite fields |
---|
| 9 | * |
---|
| 10 | * @par Copyright: |
---|
| 11 | * (c) by The SINGULAR Team, see LICENSE file |
---|
| 12 | * |
---|
[806c18] | 13 | * @internal |
---|
[10af64] | 14 | * @version \$Id$ |
---|
| 15 | * |
---|
| 16 | **/ |
---|
| 17 | //***************************************************************************** |
---|
| 18 | |
---|
| 19 | #include <config.h> |
---|
| 20 | |
---|
| 21 | #include "assert.h" |
---|
| 22 | #include "debug.h" |
---|
| 23 | |
---|
| 24 | #include "canonicalform.h" |
---|
[9c115e1] | 25 | #include "cf_util.h" |
---|
[10af64] | 26 | |
---|
| 27 | #ifdef HAVE_NTL |
---|
| 28 | #include <NTL/ZZ_pEXFactoring.h> |
---|
| 29 | #include "NTLconvert.h" |
---|
| 30 | #endif |
---|
| 31 | |
---|
[0d020e] | 32 | // cyclotomoic polys: |
---|
[51615d6] | 33 | #include "cf_cyclo.h" |
---|
[0d020e] | 34 | |
---|
[963057] | 35 | #include "cf_map_ext.h" |
---|
| 36 | |
---|
[806c18] | 37 | #ifdef HAVE_NTL |
---|
[10af64] | 38 | |
---|
| 39 | /// helper function |
---|
[806c18] | 40 | int findItem (const CFList& list, const CanonicalForm& item) |
---|
[10af64] | 41 | { |
---|
[806c18] | 42 | int result= 1; |
---|
| 43 | for (CFListIterator i= list; i.hasItem(); i++, result++) |
---|
[10af64] | 44 | { |
---|
| 45 | if (i.getItem() == item) |
---|
| 46 | return result; |
---|
| 47 | } |
---|
| 48 | return 0; |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | /// helper function |
---|
[806c18] | 52 | CanonicalForm getItem (const CFList& list, const int& pos) |
---|
[10af64] | 53 | { |
---|
| 54 | int j= 1; |
---|
[c1b9927] | 55 | if ((pos > 0) && (pos <= list.length())) |
---|
[10af64] | 56 | { |
---|
[c1b9927] | 57 | for (CFListIterator i= list; j <= pos; i++, j++) |
---|
| 58 | { |
---|
| 59 | if (j == pos) |
---|
| 60 | return i.getItem(); |
---|
| 61 | } |
---|
[10af64] | 62 | } |
---|
[c1b9927] | 63 | return 0; |
---|
[806c18] | 64 | } |
---|
[10af64] | 65 | |
---|
| 66 | |
---|
[806c18] | 67 | /// \f$ F_{p} (\alpha ) \subset F_{p}(\beta ) \f$ and \f$ \alpha \f$ is a |
---|
| 68 | /// primitive element, returns the image of \f$ \alpha \f$ |
---|
| 69 | static inline |
---|
| 70 | CanonicalForm mapUp (const Variable& alpha, const Variable& beta) |
---|
[10af64] | 71 | { |
---|
| 72 | int p= getCharacteristic (); |
---|
| 73 | zz_p::init (p); |
---|
[806c18] | 74 | zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta)); |
---|
[10af64] | 75 | zz_pE::init (NTL_mipo); |
---|
| 76 | zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo); |
---|
| 77 | zz_pE root= FindRoot (NTL_alpha_mipo); |
---|
| 78 | return convertNTLzzpE2CF (root, beta); |
---|
| 79 | } |
---|
| 80 | |
---|
[806c18] | 81 | /// the CanonicalForm G is the output of map_up, returns F considered as an |
---|
[10af64] | 82 | /// element over \f$ F_{p}(\alpha ) \f$, WARNING: make sure coefficients of F |
---|
| 83 | /// are really elements of a subfield of \f$ F_{p}(\beta ) \f$ which is |
---|
[806c18] | 84 | /// isomorphic to \f$ F_{p}(\alpha ) \f$ |
---|
[51615d6] | 85 | static inline |
---|
[806c18] | 86 | CanonicalForm |
---|
[10af64] | 87 | mapDown (const CanonicalForm& F, const Variable& alpha, const |
---|
[806c18] | 88 | CanonicalForm& G, CFList& source, CFList& dest) |
---|
| 89 | { |
---|
[10af64] | 90 | CanonicalForm buf, buf2; |
---|
| 91 | int counter= 0; |
---|
| 92 | int pos; |
---|
| 93 | int p= getCharacteristic(); |
---|
| 94 | int d= degree(getMipo(alpha)); |
---|
[9c115e1] | 95 | int bound= ipower(p, d); |
---|
[10af64] | 96 | CanonicalForm result= 0; |
---|
| 97 | CanonicalForm remainder; |
---|
| 98 | CanonicalForm alpha_power; |
---|
| 99 | if (degree(F) == 0) return F; |
---|
[806c18] | 100 | if (F.level() < 0 && F.isUnivariate()) |
---|
[10af64] | 101 | { |
---|
| 102 | buf= F; |
---|
| 103 | remainder= mod (buf, G); |
---|
[806c18] | 104 | ASSERT (remainder.isZero(), "alpha is not primitive"); |
---|
[10af64] | 105 | pos= findItem (source, buf); |
---|
| 106 | if (pos == 0) |
---|
| 107 | source.append (buf); |
---|
| 108 | buf2= buf; |
---|
[806c18] | 109 | while (degree (buf) != 0 && counter < bound) |
---|
[10af64] | 110 | { |
---|
| 111 | buf /= G; |
---|
| 112 | counter++; |
---|
| 113 | if (buf == buf2) break; |
---|
[806c18] | 114 | } |
---|
| 115 | ASSERT (counter >= bound, "alpha is not primitive"); |
---|
| 116 | if (pos == 0) |
---|
[10af64] | 117 | { |
---|
[55608a7] | 118 | alpha_power= power (alpha, counter); |
---|
[10af64] | 119 | dest.append (alpha_power); |
---|
| 120 | } |
---|
| 121 | else |
---|
[806c18] | 122 | alpha_power= getItem (dest, pos); |
---|
[618da5] | 123 | result = alpha_power; |
---|
[10af64] | 124 | return result; |
---|
| 125 | } |
---|
[806c18] | 126 | else |
---|
[10af64] | 127 | { |
---|
[806c18] | 128 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 129 | { |
---|
| 130 | buf= mapDown (i.coeff(), alpha, G, source, dest); |
---|
| 131 | result += buf*power(F.mvar(), i.exp()); |
---|
| 132 | } |
---|
| 133 | return result; |
---|
| 134 | } |
---|
| 135 | } |
---|
| 136 | |
---|
| 137 | /// helper function |
---|
| 138 | static inline |
---|
| 139 | CanonicalForm GF2FalphaHelper (const CanonicalForm& F, const Variable& alpha) |
---|
| 140 | { |
---|
[55608a7] | 141 | if (F.isZero()) |
---|
| 142 | return 0; |
---|
[10af64] | 143 | int exp; |
---|
| 144 | CanonicalForm result= 0; |
---|
| 145 | InternalCF* buf; |
---|
[806c18] | 146 | if (F.inBaseDomain()) |
---|
[10af64] | 147 | { |
---|
| 148 | if (F.isOne()) return 1; |
---|
| 149 | buf= F.getval(); |
---|
| 150 | exp= imm2int(buf); |
---|
| 151 | result= power (alpha, exp).mapinto(); |
---|
| 152 | return result; |
---|
[806c18] | 153 | } |
---|
[10af64] | 154 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
| 155 | result += GF2FalphaHelper (i.coeff(), alpha)*power (F.mvar(), i.exp()); |
---|
| 156 | return result; |
---|
| 157 | } |
---|
| 158 | |
---|
[806c18] | 159 | /// changes representation by primitive element to representation by residue |
---|
| 160 | /// classes modulo a Conway polynomial |
---|
| 161 | CanonicalForm GF2FalphaRep (const CanonicalForm& F, const Variable& alpha) |
---|
[10af64] | 162 | { |
---|
| 163 | Variable beta= rootOf (gf_mipo); |
---|
| 164 | return GF2FalphaHelper (F, beta) (alpha, beta); |
---|
| 165 | } |
---|
| 166 | |
---|
[806c18] | 167 | /// change representation by residue classes modulo a Conway polynomial |
---|
[10af64] | 168 | /// to representation by primitive element |
---|
[806c18] | 169 | CanonicalForm Falpha2GFRep (const CanonicalForm& F) |
---|
[10af64] | 170 | { |
---|
| 171 | CanonicalForm result= 0; |
---|
| 172 | InternalCF* buf; |
---|
| 173 | |
---|
[806c18] | 174 | if (F.inCoeffDomain()) |
---|
[10af64] | 175 | { |
---|
| 176 | if (F.inBaseDomain()) |
---|
| 177 | return F.mapinto(); |
---|
[806c18] | 178 | else |
---|
[10af64] | 179 | { |
---|
[806c18] | 180 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 181 | { |
---|
| 182 | buf= int2imm_gf (i.exp()); |
---|
| 183 | result += i.coeff().mapinto()*CanonicalForm (buf); |
---|
| 184 | } |
---|
| 185 | } |
---|
| 186 | return result; |
---|
[806c18] | 187 | } |
---|
| 188 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 189 | result += Falpha2GFRep (i.coeff())*power (F.mvar(), i.exp()); |
---|
| 190 | return result; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | /// GF_map_up helper |
---|
| 194 | static inline |
---|
[806c18] | 195 | CanonicalForm GFPowUp (const CanonicalForm & F, int k) |
---|
[10af64] | 196 | { |
---|
| 197 | if (F.isOne()) return F; |
---|
| 198 | CanonicalForm result= 0; |
---|
[806c18] | 199 | if (F.inBaseDomain()) |
---|
[10af64] | 200 | return power(F, k); |
---|
[806c18] | 201 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 202 | result += GFPowUp (i.coeff(), k)*power (F.mvar(), i.exp()); |
---|
| 203 | return result; |
---|
| 204 | } |
---|
| 205 | |
---|
[806c18] | 206 | /// maps a polynomial over \f$ GF(p^{k}) \f$ to a polynomial over |
---|
[10af64] | 207 | /// \f$ GF(p^{d}) \f$ , d needs to be a multiple of k |
---|
[806c18] | 208 | CanonicalForm GFMapUp (const CanonicalForm & F, int k) |
---|
| 209 | { |
---|
[10af64] | 210 | int d= getGFDegree(); |
---|
| 211 | ASSERT (d%k == 0, "multiple of GF degree expected"); |
---|
| 212 | int p= getCharacteristic(); |
---|
[9c115e1] | 213 | int ext_field_size= ipower (p, d); |
---|
| 214 | int field_size= ipower ( p, k); |
---|
[10af64] | 215 | int diff= (ext_field_size - 1)/(field_size - 1); |
---|
| 216 | return GFPowUp (F, diff); |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | /// GFMapDown helper |
---|
| 220 | static inline |
---|
[806c18] | 221 | CanonicalForm GFPowDown (const CanonicalForm & F, int k) |
---|
[10af64] | 222 | { |
---|
| 223 | if (F.isOne()) return F; |
---|
| 224 | CanonicalForm result= 0; |
---|
| 225 | int exp; |
---|
| 226 | InternalCF* buf; |
---|
[806c18] | 227 | if (F.inBaseDomain()) |
---|
[10af64] | 228 | { |
---|
| 229 | buf= F.getval(); |
---|
| 230 | exp= imm2int (buf); |
---|
| 231 | if ((exp % k) == 0) |
---|
| 232 | exp= exp/k; |
---|
[806c18] | 233 | else |
---|
[10af64] | 234 | return -1; |
---|
| 235 | |
---|
| 236 | buf= int2imm_gf (exp); |
---|
| 237 | return CanonicalForm (buf); |
---|
[806c18] | 238 | } |
---|
| 239 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 240 | result += GFPowDown (i.coeff(), k)*power (F.mvar(), i.exp()); |
---|
| 241 | return result; |
---|
| 242 | } |
---|
| 243 | |
---|
[806c18] | 244 | /// maps a polynomial over \f$ GF(p^{d}) \f$ to a polynomial over |
---|
[10af64] | 245 | /// \f$ GF(p^{k})\f$ , d needs to be a multiple of k |
---|
[806c18] | 246 | CanonicalForm GFMapDown (const CanonicalForm & F, int k) |
---|
[10af64] | 247 | { |
---|
| 248 | int d= getGFDegree(); |
---|
| 249 | ASSERT (d % k == 0, "multiple of GF degree expected"); |
---|
| 250 | int p= getCharacteristic(); |
---|
[9c115e1] | 251 | int ext_field_size= ipower (p, d); |
---|
| 252 | int field_size= ipower ( p, k); |
---|
[10af64] | 253 | int diff= (ext_field_size - 1)/(field_size - 1); |
---|
| 254 | return GFPowDown (F, diff); |
---|
| 255 | } |
---|
| 256 | |
---|
[806c18] | 257 | static inline |
---|
| 258 | CanonicalForm mapUp (const CanonicalForm& F, const CanonicalForm& G, |
---|
| 259 | const Variable& alpha, const CanonicalForm& H, |
---|
[10af64] | 260 | CFList& source, CFList& dest) |
---|
[806c18] | 261 | { |
---|
[10af64] | 262 | CanonicalForm buf, buf2; |
---|
| 263 | int counter= 0; |
---|
| 264 | int pos; |
---|
| 265 | int p= getCharacteristic(); |
---|
| 266 | int d= degree (getMipo(alpha)); |
---|
[9c115e1] | 267 | int bound= ipower(p, d); |
---|
[10af64] | 268 | CanonicalForm result= 0; |
---|
| 269 | CanonicalForm remainder; |
---|
| 270 | CanonicalForm H_power; |
---|
| 271 | if (degree(F) <= 0) return F; |
---|
[806c18] | 272 | if (F.level() < 0 && F.isUnivariate()) |
---|
[10af64] | 273 | { |
---|
| 274 | buf= F; |
---|
| 275 | remainder= mod (buf, G); |
---|
[806c18] | 276 | ASSERT (remainder.isZero(), "alpha is not primitive"); |
---|
[10af64] | 277 | pos= findItem (source, buf); |
---|
| 278 | if (pos == 0) |
---|
| 279 | source.append (buf); |
---|
| 280 | buf2= buf; |
---|
[806c18] | 281 | while (degree (buf) != 0 && counter < bound) |
---|
[10af64] | 282 | { |
---|
| 283 | buf /= G; |
---|
| 284 | counter++; |
---|
| 285 | if (buf == buf2) break; |
---|
[806c18] | 286 | } |
---|
| 287 | ASSERT (counter >= bound, "alpha is not primitive"); |
---|
| 288 | if (pos == 0) |
---|
[10af64] | 289 | { |
---|
[618da5] | 290 | H_power= buf*power (H, counter); |
---|
[10af64] | 291 | dest.append (H_power); |
---|
| 292 | } |
---|
| 293 | else |
---|
[806c18] | 294 | H_power= getItem (dest, pos); |
---|
[618da5] | 295 | result = H_power; |
---|
[10af64] | 296 | return result; |
---|
| 297 | } |
---|
[806c18] | 298 | else |
---|
[10af64] | 299 | { |
---|
[806c18] | 300 | for (CFIterator i= F; i.hasTerms(); i++) |
---|
[10af64] | 301 | { |
---|
| 302 | buf= mapUp (i.coeff(), G, alpha, H, source, dest); |
---|
| 303 | result += buf*power(F.mvar(), i.exp()); |
---|
| 304 | } |
---|
| 305 | return result; |
---|
| 306 | } |
---|
| 307 | } |
---|
| 308 | |
---|
[806c18] | 309 | /// determine a primitive element of \f$ F_{p} (\alpha ) \f$, |
---|
| 310 | /// \f$ \beta \f$ is a primitive element of a field which is isomorphic to |
---|
[10af64] | 311 | /// \f$ F_{p}(\alpha ) \f$ |
---|
[806c18] | 312 | CanonicalForm |
---|
| 313 | primitiveElement (const Variable& alpha, Variable& beta, bool fail) |
---|
[10af64] | 314 | { |
---|
| 315 | bool primitive= false; |
---|
| 316 | fail= false; |
---|
| 317 | primitive= isPrimitive (alpha, fail); |
---|
| 318 | if (fail) |
---|
| 319 | return 0; |
---|
[806c18] | 320 | if (primitive) |
---|
[10af64] | 321 | { |
---|
| 322 | beta= alpha; |
---|
| 323 | return alpha; |
---|
| 324 | } |
---|
[806c18] | 325 | CanonicalForm mipo= getMipo (alpha); |
---|
[10af64] | 326 | int d= degree (mipo); |
---|
| 327 | int p= getCharacteristic (); |
---|
| 328 | zz_p::init (p); |
---|
| 329 | zz_pX NTL_mipo; |
---|
| 330 | CanonicalForm mipo2; |
---|
| 331 | primitive= false; |
---|
| 332 | fail= false; |
---|
| 333 | do |
---|
| 334 | { |
---|
[806c18] | 335 | BuildIrred (NTL_mipo, d); |
---|
[10af64] | 336 | mipo2= convertNTLzzpX2CF (NTL_mipo, Variable (1)); |
---|
| 337 | beta= rootOf (mipo2); |
---|
| 338 | primitive= isPrimitive (beta, fail); |
---|
| 339 | if (primitive) |
---|
[806c18] | 340 | break; |
---|
[10af64] | 341 | if (fail) |
---|
| 342 | return 0; |
---|
| 343 | } while (1); |
---|
[08daea] | 344 | zz_pX alpha_mipo= convertFacCF2NTLzzpX (mipo); |
---|
| 345 | zz_pE::init (alpha_mipo); |
---|
| 346 | zz_pEX NTL_beta_mipo= to_zz_pEX (NTL_mipo); |
---|
| 347 | zz_pE root= FindRoot (NTL_beta_mipo); |
---|
[10af64] | 348 | return convertNTLzzpE2CF (root, alpha); |
---|
| 349 | } |
---|
| 350 | |
---|
| 351 | CanonicalForm |
---|
| 352 | mapDown (const CanonicalForm& F, const CanonicalForm& prim_elem, const |
---|
[806c18] | 353 | CanonicalForm& im_prim_elem, const Variable& alpha, CFList& source, |
---|
| 354 | CFList& dest) |
---|
| 355 | { |
---|
[10af64] | 356 | return mapUp (F, im_prim_elem, alpha, prim_elem, dest, source); |
---|
| 357 | } |
---|
| 358 | |
---|
| 359 | CanonicalForm |
---|
[806c18] | 360 | mapUp (const CanonicalForm& F, const Variable& alpha, const Variable& beta, |
---|
| 361 | const CanonicalForm& prim_elem, const CanonicalForm& im_prim_elem, |
---|
| 362 | CFList& source, CFList& dest) |
---|
[10af64] | 363 | { |
---|
[806c18] | 364 | if (prim_elem == alpha) |
---|
[10af64] | 365 | return F (im_prim_elem, alpha); |
---|
| 366 | return mapUp (F, prim_elem, alpha, im_prim_elem, source, dest); |
---|
| 367 | } |
---|
| 368 | |
---|
[806c18] | 369 | CanonicalForm |
---|
[618da5] | 370 | mapPrimElem (const CanonicalForm& primElem, const Variable& alpha, |
---|
[51615d6] | 371 | const Variable& beta) |
---|
[10af64] | 372 | { |
---|
[618da5] | 373 | if (primElem == alpha) |
---|
[10af64] | 374 | return mapUp (alpha, beta); |
---|
| 375 | else |
---|
| 376 | { |
---|
[618da5] | 377 | CanonicalForm primElemMipo= findMinPoly (primElem, alpha); |
---|
| 378 | int p= getCharacteristic (); |
---|
| 379 | zz_p::init (p); |
---|
[c1b9927] | 380 | zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (beta)); |
---|
[618da5] | 381 | zz_pE::init (NTLMipo); |
---|
| 382 | zz_pEX NTLPrimElemMipo= convertFacCF2NTLzz_pEX (primElemMipo, NTLMipo); |
---|
| 383 | zz_pE root= FindRoot (NTLPrimElemMipo); |
---|
| 384 | return convertNTLzzpE2CF (root, beta); |
---|
[806c18] | 385 | } |
---|
[10af64] | 386 | } |
---|
| 387 | |
---|
[55608a7] | 388 | CanonicalForm |
---|
| 389 | map (const CanonicalForm& primElem, const Variable& alpha, |
---|
| 390 | const CanonicalForm& F, const Variable& beta) |
---|
| 391 | { |
---|
| 392 | CanonicalForm G= F; |
---|
| 393 | int order= 0; |
---|
| 394 | while (!G.isOne()) |
---|
| 395 | { |
---|
| 396 | G /= primElem; |
---|
| 397 | order++; |
---|
| 398 | } |
---|
| 399 | int p= getCharacteristic (); |
---|
| 400 | zz_p::init (p); |
---|
[c1b9927] | 401 | zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta)); |
---|
[55608a7] | 402 | zz_pE::init (NTL_mipo); |
---|
| 403 | zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo); |
---|
| 404 | zz_pE NTLBeta= to_zz_pE (convertFacCF2NTLzzpX (beta)); |
---|
| 405 | vec_zz_pE roots= FindRoots (NTL_alpha_mipo); |
---|
[c1b9927] | 406 | long ind=-1; |
---|
[55608a7] | 407 | for (long i= 0; i < roots.length(); i++) |
---|
| 408 | { |
---|
| 409 | if (power (roots [i], order)== NTLBeta) |
---|
| 410 | { |
---|
| 411 | ind= i; |
---|
| 412 | break; |
---|
| 413 | } |
---|
| 414 | } |
---|
| 415 | return (convertNTLzzpE2CF (roots[ind], beta)); |
---|
| 416 | } |
---|
| 417 | |
---|
[618da5] | 418 | CanonicalForm |
---|
| 419 | findMinPoly (const CanonicalForm& F, const Variable& alpha) |
---|
| 420 | { |
---|
| 421 | ASSERT (F.isUnivariate() && F.mvar()==alpha,"expected element of F_p(alpha)"); |
---|
| 422 | |
---|
| 423 | zz_p::init (getCharacteristic()); |
---|
| 424 | zz_pX NTLF= convertFacCF2NTLzzpX (F); |
---|
| 425 | int d= degree (getMipo (alpha)); |
---|
| 426 | |
---|
| 427 | zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo(alpha)); |
---|
| 428 | zz_pE::init (NTLMipo); |
---|
| 429 | vec_zz_p pows; |
---|
| 430 | pows.SetLength (2*d); |
---|
| 431 | |
---|
| 432 | zz_pE powNTLF; |
---|
| 433 | set (powNTLF); |
---|
| 434 | zz_pE NTLFE= to_zz_pE (NTLF); |
---|
| 435 | zz_pX buf; |
---|
| 436 | for (int i= 0; i < 2*d; i++) |
---|
| 437 | { |
---|
| 438 | buf= rep (powNTLF); |
---|
| 439 | buf.rep.SetLength (d); |
---|
| 440 | pows [i]= buf.rep[0]; |
---|
| 441 | powNTLF *= NTLFE; |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | zz_pX NTLMinPoly; |
---|
| 445 | MinPolySeq (NTLMinPoly, pows, d); |
---|
| 446 | |
---|
| 447 | return convertNTLzzpX2CF (NTLMinPoly, Variable (1)); |
---|
| 448 | } |
---|
| 449 | |
---|
[10af64] | 450 | #endif |
---|