source: git/factory/cf_map_ext.cc @ a723558

spielwiese
Last change on this file since a723558 was d3c6ce, checked in by Hans Schoenemann <hannes@…>, 4 years ago
factory: fix Short/bug_tr679.tst
  • Property mode set to 100644
File size: 13.8 KB
Line 
1// -*- c++ -*-
2//*****************************************************************************
3/** @file cf_map_ext.cc
4 *
5 * This file implements functions to map between extensions of finite fields
6 *
7 * @par Copyright:
8 *   (c) by The SINGULAR Team, see LICENSE file
9 *
10 * @author Martin Lee
11 * @date   16.11.2009
12**/
13//*****************************************************************************
14
15
16#include "config.h"
17
18
19#include "cf_assert.h"
20#include "debug.h"
21
22#include "canonicalform.h"
23#include "cf_util.h"
24#include "imm.h"
25#include "cf_iter.h"
26
27#ifdef HAVE_NTL
28#include "NTLconvert.h"
29#endif
30
31#ifdef HAVE_FLINT
32#include "FLINTconvert.h"
33#endif
34
35// cyclotomoic polys:
36#include "cf_cyclo.h"
37
38#include "cf_map_ext.h"
39
40/// helper function
41int findItem (const CFList& list, const CanonicalForm& item)
42{
43  int result= 1;
44  for (CFListIterator i= list; i.hasItem(); i++, result++)
45  {
46    if (i.getItem() == item)
47      return result;
48  }
49  return 0;
50}
51
52/// helper function
53CanonicalForm getItem (const CFList& list, const int& pos)
54{
55  int j= 1;
56  if ((pos > 0) && (pos <= list.length()))
57  {
58    for (CFListIterator i= list; j <= pos; i++, j++)
59    {
60      if (j == pos)
61        return i.getItem();
62    }
63  }
64  return 0;
65}
66
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$
69static inline
70CanonicalForm mapUp (const Variable& alpha, const Variable& beta)
71{
72  int p= getCharacteristic ();
73  #ifdef HAVE_FLINT
74    // convert mipo1
75    nmod_poly_t mipo1;
76    convertFacCF2nmod_poly_t(mipo1,getMipo(beta));
77    fq_nmod_ctx_t ctx;
78    fq_nmod_ctx_init_modulus(ctx,mipo1,"t");
79    nmod_poly_clear(mipo1);
80    // convert mipo2 (alpah)
81    fq_nmod_poly_t mipo2;
82    convertFacCF2Fq_nmod_poly_t(mipo2,getMipo(alpha),ctx);
83    fq_nmod_poly_factor_t fac;
84    fq_nmod_poly_factor_init(fac,ctx);
85    fq_nmod_poly_roots(fac, mipo2, 0, ctx);
86     // root of first factor:
87    fq_nmod_t r0;
88    fq_nmod_init(r0, ctx);
89    fq_nmod_poly_get_coeff(r0,fac->poly,0,ctx);
90    // convert
91    CanonicalForm r1=convertFq_nmod_t2FacCF(r0,beta);
92    // cleanup
93    fq_nmod_poly_factor_clear(fac,ctx);
94    fq_nmod_clear(r0, ctx);
95    fq_nmod_poly_clear(mipo2,ctx);
96    fq_nmod_ctx_clear(ctx);
97    return r1;
98  #elif defined(HAVE_NTL)
99  if (fac_NTL_char != p)
100  {
101    fac_NTL_char= p;
102    zz_p::init (p);
103  }
104  zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta));
105  zz_pE::init (NTL_mipo);
106  zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo);
107  zz_pE root= FindRoot (NTL_alpha_mipo);
108  return convertNTLzzpE2CF (root, beta);
109  #endif
110}
111
112
113/// the CanonicalForm G is the output of map_up, returns F considered as an
114/// element over \f$ F_{p}(\alpha ) \f$, WARNING: make sure coefficients of F
115/// are really elements of a subfield of \f$ F_{p}(\beta ) \f$ which is
116/// isomorphic to \f$ F_{p}(\alpha ) \f$
117static inline
118CanonicalForm
119mapDown (const CanonicalForm& F, const Variable& alpha, const
120          CanonicalForm& G, CFList& source, CFList& dest)
121{
122  CanonicalForm buf, buf2;
123  int counter= 0;
124  int pos;
125  int p= getCharacteristic();
126  int d= degree(getMipo(alpha));
127  int bound= ipower(p, d);
128  CanonicalForm result= 0;
129  CanonicalForm remainder;
130  CanonicalForm alpha_power;
131  if (degree(F) == 0) return F;
132  if (F.level() < 0 && F.isUnivariate())
133  {
134    buf= F;
135    remainder= mod (buf, G);
136    ASSERT (remainder.isZero(), "alpha is not primitive");
137    pos= findItem (source, buf);
138    if (pos == 0)
139      source.append (buf);
140    buf2= buf;
141    while (degree (buf) != 0 && counter < bound)
142    {
143      buf /= G;
144      counter++;
145      if (buf == buf2) break;
146    }
147    ASSERT (counter >= bound, "alpha is not primitive");
148    if (pos == 0)
149    {
150      alpha_power= power (alpha, counter);
151      dest.append (alpha_power);
152    }
153    else
154      alpha_power= getItem (dest, pos);
155    result = alpha_power;
156    return result;
157  }
158  else
159  {
160    for (CFIterator i= F; i.hasTerms(); i++)
161    {
162      buf= mapDown (i.coeff(), alpha, G, source, dest);
163      result += buf*power(F.mvar(), i.exp());
164    }
165    return result;
166  }
167}
168
169/// helper function
170static inline
171CanonicalForm GF2FalphaHelper (const CanonicalForm& F, const Variable& alpha)
172{
173  if (F.isZero())
174    return 0;
175  int exp;
176  CanonicalForm result= 0;
177  InternalCF* buf;
178  if (F.inBaseDomain())
179  {
180    if (F.isOne()) return 1;
181    buf= F.getval();
182    exp= imm2int(buf);
183    result= power (alpha, exp).mapinto();
184    return result;
185  }
186  for (CFIterator i= F; i.hasTerms(); i++)
187    result += GF2FalphaHelper (i.coeff(), alpha)*power (F.mvar(), i.exp());
188  return result;
189}
190
191CanonicalForm GF2FalphaRep (const CanonicalForm& F, const Variable& alpha)
192{
193  Variable beta= rootOf (gf_mipo);
194  CanonicalForm result= GF2FalphaHelper (F, beta) (alpha, beta);
195  prune (beta);
196  return result;
197}
198
199CanonicalForm Falpha2GFRep (const CanonicalForm& F)
200{
201  CanonicalForm result= 0;
202  InternalCF* buf;
203
204  if (F.inCoeffDomain())
205  {
206    if (F.inBaseDomain())
207      return F.mapinto();
208    else
209    {
210      for (CFIterator i= F; i.hasTerms(); i++)
211      {
212        buf= int2imm_gf (i.exp());
213        result += i.coeff().mapinto()*CanonicalForm (buf);
214      }
215    }
216    return result;
217  }
218  for (CFIterator i= F; i.hasTerms(); i++)
219    result += Falpha2GFRep (i.coeff())*power (F.mvar(), i.exp());
220  return result;
221}
222
223/// GF_map_up helper
224static inline
225CanonicalForm GFPowUp (const CanonicalForm & F, int k)
226{
227  if (F.isOne()) return F;
228  CanonicalForm result= 0;
229  if (F.inBaseDomain())
230    return power(F, k);
231  for (CFIterator i= F; i.hasTerms(); i++)
232    result += GFPowUp (i.coeff(), k)*power (F.mvar(), i.exp());
233  return result;
234}
235
236CanonicalForm GFMapUp (const CanonicalForm & F, int k)
237{
238  int d= getGFDegree();
239  ASSERT (d%k == 0, "multiple of GF degree expected");
240  int p= getCharacteristic();
241  int ext_field_size= ipower (p, d);
242  int field_size= ipower ( p, k);
243  int diff= (ext_field_size - 1)/(field_size - 1);
244  return GFPowUp (F, diff);
245}
246
247/// GFMapDown helper
248static inline
249CanonicalForm GFPowDown (const CanonicalForm & F, int k)
250{
251  if (F.isOne()) return F;
252  CanonicalForm result= 0;
253  int exp;
254  InternalCF* buf;
255  if (F.inBaseDomain())
256  {
257    buf= F.getval();
258    exp= imm2int (buf);
259    if ((exp % k) == 0)
260      exp= exp/k;
261    else
262      return -1;
263
264    buf= int2imm_gf (exp);
265    return CanonicalForm (buf);
266  }
267  for (CFIterator i= F; i.hasTerms(); i++)
268    result += GFPowDown (i.coeff(), k)*power (F.mvar(), i.exp());
269  return result;
270}
271
272CanonicalForm GFMapDown (const CanonicalForm & F, int k)
273{
274  int d= getGFDegree();
275  ASSERT (d % k == 0, "multiple of GF degree expected");
276  int p= getCharacteristic();
277  int ext_field_size= ipower (p, d);
278  int field_size= ipower ( p, k);
279  int diff= (ext_field_size - 1)/(field_size - 1);
280  return GFPowDown (F, diff);
281}
282
283/// map F in \f$ F_{p} (\alpha ) \f$ which is generated by G into some
284/// \f$ F_{p}(\beta ) \f$ which is generated by H
285static inline
286CanonicalForm mapUp (const CanonicalForm& F, const CanonicalForm& G,
287                      const Variable& alpha, const CanonicalForm& H,
288                      CFList& source, CFList& dest)
289{
290  CanonicalForm buf, buf2;
291  int counter= 0;
292  int pos;
293  int p= getCharacteristic();
294  int d= degree (getMipo(alpha));
295  int bound= ipower(p, d);
296  CanonicalForm result= 0;
297  CanonicalForm remainder;
298  CanonicalForm H_power;
299  if (degree(F) <= 0) return F;
300  if (F.level() < 0 && F.isUnivariate())
301  {
302    buf= F;
303    remainder= mod (buf, G);
304    ASSERT (remainder.isZero(), "alpha is not primitive");
305    pos= findItem (source, buf);
306    if (pos == 0)
307      source.append (buf);
308    buf2= buf;
309    while (degree (buf) != 0 && counter < bound)
310    {
311      buf /= G;
312      counter++;
313      if (buf == buf2) break;
314    }
315    ASSERT (counter <= bound, "alpha is not primitive");
316    if (pos == 0)
317    {
318      H_power= buf*power (H, counter);
319      dest.append (H_power);
320    }
321    else
322      H_power= getItem (dest, pos);
323    result = H_power;
324    return result;
325  }
326  else
327  {
328    for (CFIterator i= F; i.hasTerms(); i++)
329    {
330      buf= mapUp (i.coeff(), G, alpha, H, source, dest);
331      result += buf*power(F.mvar(), i.exp());
332    }
333    return result;
334  }
335}
336
337CanonicalForm
338primitiveElement (const Variable& alpha, Variable& beta, bool& fail)
339{
340  bool primitive= false;
341  fail= false;
342  primitive= isPrimitive (alpha, fail);
343  if (fail)
344    return 0;
345  if (primitive)
346  {
347    beta= alpha;
348    return alpha;
349  }
350  CanonicalForm mipo= getMipo (alpha);
351  int d= degree (mipo);
352  int p= getCharacteristic ();
353  #if !defined(HAVE_FLINT) && defined(HAVE_NTL)
354  if (fac_NTL_char != p)
355  {
356    fac_NTL_char= p;
357    zz_p::init (p);
358  }
359  zz_pX NTL_mipo;
360  #endif
361  CanonicalForm mipo2;
362  primitive= false;
363  fail= false;
364  bool initialized= false;
365  do
366  {
367    #ifdef HAVE_FLINT
368    nmod_poly_t Irredpoly;
369    nmod_poly_init(Irredpoly,p);
370    nmod_poly_randtest_monic_irreducible(Irredpoly, FLINTrandom, d+1);
371    mipo2=convertnmod_poly_t2FacCF(Irredpoly,Variable(1));
372    nmod_poly_clear(Irredpoly);
373    #elif defined(HAVE_NTL)
374    BuildIrred (NTL_mipo, d);
375    mipo2= convertNTLzzpX2CF (NTL_mipo, Variable (1));
376    #endif
377    if (!initialized)
378      beta= rootOf (mipo2);
379    else
380      setMipo (beta, mipo2);
381    primitive= isPrimitive (beta, fail);
382    if (primitive)
383      break;
384    if (fail)
385      return 0;
386  } while (1);
387  #ifdef HAVE_FLINT
388  // convert alpha_mipo
389  nmod_poly_t alpha_mipo;
390  convertFacCF2nmod_poly_t(alpha_mipo,mipo);
391  fq_nmod_ctx_t ctx;
392  fq_nmod_ctx_init_modulus(ctx,alpha_mipo,"t");
393  nmod_poly_clear(alpha_mipo);
394  // convert beta_mipo (mipo2)
395  fq_nmod_poly_t FLINT_beta_mipo;
396  convertFacCF2Fq_nmod_poly_t(FLINT_beta_mipo,mipo2,ctx);
397  fq_nmod_poly_factor_t fac;
398  fq_nmod_poly_factor_init(fac,ctx);
399  fq_nmod_poly_roots(fac, FLINT_beta_mipo, 0, ctx);
400  // root of first factor:
401  fq_nmod_t r0;
402  fq_nmod_init(r0, ctx);
403  fq_nmod_poly_get_coeff(r0,fac->poly,0,ctx);
404  // convert
405  CanonicalForm r1=convertFq_nmod_t2FacCF(r0,alpha);
406  // cleanup
407  fq_nmod_poly_factor_clear(fac,ctx);
408  fq_nmod_clear(r0, ctx);
409  fq_nmod_poly_clear(FLINT_beta_mipo,ctx);
410  fq_nmod_ctx_clear(ctx);
411  return r1;
412  #elif defined(NTL)
413  zz_pX alpha_mipo= convertFacCF2NTLzzpX (mipo);
414  zz_pE::init (alpha_mipo);
415  zz_pEX NTL_beta_mipo= to_zz_pEX (NTL_mipo);
416  zz_pE root= FindRoot (NTL_beta_mipo);
417  return convertNTLzzpE2CF (root, alpha);
418  #endif
419}
420
421CanonicalForm
422mapDown (const CanonicalForm& F, const CanonicalForm& prim_elem, const
423          CanonicalForm& im_prim_elem, const Variable& alpha, CFList& source,
424          CFList& dest)
425{
426  return mapUp (F, im_prim_elem, alpha, prim_elem, dest, source);
427}
428
429CanonicalForm
430mapUp (const CanonicalForm& F, const Variable& alpha, const Variable& /*beta*/,
431        const CanonicalForm& prim_elem, const CanonicalForm& im_prim_elem,
432        CFList& source, CFList& dest)
433{
434  if (prim_elem == alpha)
435    return F (im_prim_elem, alpha);
436  return mapUp (F, prim_elem, alpha, im_prim_elem, source, dest);
437}
438
439#ifdef HAVE_NTL // findMinPoly
440CanonicalForm
441mapPrimElem (const CanonicalForm& primElem, const Variable& alpha,
442             const Variable& beta)
443{
444  if (primElem == alpha)
445    return mapUp (alpha, beta);
446  else
447  {
448    CanonicalForm primElemMipo= findMinPoly (primElem, alpha);
449    int p= getCharacteristic ();
450    #ifdef HAVE_FLINT
451    // convert mipo1
452    nmod_poly_t mipo1;
453    convertFacCF2nmod_poly_t(mipo1,getMipo(beta));
454    fq_nmod_ctx_t ctx;
455    fq_nmod_ctx_init_modulus(ctx,mipo1,"t");
456    nmod_poly_clear(mipo1);
457    // convert mipo2 (primElemMipo)
458    fq_nmod_poly_t mipo2;
459    convertFacCF2Fq_nmod_poly_t(mipo2,primElemMipo,ctx);
460    fq_nmod_poly_factor_t fac;
461    fq_nmod_poly_factor_init(fac,ctx);
462    fq_nmod_poly_roots(fac, mipo2, 0, ctx);
463     // root of first factor:
464    fq_nmod_t r0;
465    fq_nmod_init(r0, ctx);
466    fq_nmod_poly_get_coeff(r0,fac->poly,0,ctx);
467    // convert
468    CanonicalForm r1=convertFq_nmod_t2FacCF(r0,beta);
469    // cleanup
470    fq_nmod_poly_factor_clear(fac,ctx);
471    fq_nmod_clear(r0, ctx);
472    fq_nmod_poly_clear(mipo2,ctx);
473    fq_nmod_ctx_clear(ctx);
474    return r1;
475    #elif defined(HAVE_NTL)
476    if (fac_NTL_char != p)
477    {
478      fac_NTL_char= p;
479      zz_p::init (p);
480    }
481    zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (beta));
482    zz_pE::init (NTLMipo);
483    zz_pEX NTLPrimElemMipo= convertFacCF2NTLzz_pEX (primElemMipo, NTLMipo);
484    zz_pE root= FindRoot (NTLPrimElemMipo);
485    return convertNTLzzpE2CF (root, beta);
486    #endif
487  }
488}
489#endif
490
491#ifdef HAVE_NTL
492CanonicalForm
493map (const CanonicalForm& primElem, const Variable& alpha,
494     const CanonicalForm& F, const Variable& beta)
495{
496  CanonicalForm G= F;
497  int order= 0;
498  while (!G.isOne())
499  {
500    G /= primElem;
501    order++;
502  }
503  int p= getCharacteristic ();
504  if (fac_NTL_char != p)
505  {
506    fac_NTL_char= p;
507    zz_p::init (p);
508  }
509  zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta));
510  zz_pE::init (NTL_mipo);
511  zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo);
512  zz_pE NTLBeta= to_zz_pE (convertFacCF2NTLzzpX (beta));
513  vec_zz_pE roots= FindRoots (NTL_alpha_mipo);
514  long ind=-1;
515  for (long i= 0; i < roots.length(); i++)
516  {
517    if (power (roots [i], order)== NTLBeta)
518    {
519      ind= i;
520      break;
521    }
522  }
523  return (convertNTLzzpE2CF (roots[ind], beta));
524}
525
526CanonicalForm
527findMinPoly (const CanonicalForm& F, const Variable& alpha)
528{
529  ASSERT (F.isUnivariate() && F.mvar()==alpha,"expected element of F_p(alpha)");
530
531  if (fac_NTL_char != getCharacteristic())
532  {
533    fac_NTL_char= getCharacteristic();
534    zz_p::init (getCharacteristic());
535  }
536  zz_pX NTLF= convertFacCF2NTLzzpX (F);
537  int d= degree (getMipo (alpha));
538
539  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo(alpha));
540  zz_pE::init (NTLMipo);
541  vec_zz_p pows;
542  pows.SetLength (2*d);
543
544  zz_pE powNTLF;
545  set (powNTLF);
546  zz_pE NTLFE= to_zz_pE (NTLF);
547  zz_pX buf;
548  for (int i= 0; i < 2*d; i++)
549  {
550    buf= rep (powNTLF);
551    buf.rep.SetLength (d);
552    pows [i]= buf.rep[0];
553    powNTLF *= NTLFE;
554  }
555
556  zz_pX NTLMinPoly;
557  MinPolySeq (NTLMinPoly, pows, d);
558
559  return convertNTLzzpX2CF (NTLMinPoly, Variable (1));
560}
561
562#endif
Note: See TracBrowser for help on using the repository browser.