source: git/factory/cf_map_ext.cc @ 16f511

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