source: git/factory/cf_map_ext.cc @ 53e6c3

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