source: git/factory/cf_map_ext.cc @ 51615d6

spielwiese
Last change on this file since 51615d6 was 51615d6, checked in by Martin Lee <martinlee84@…>, 14 years ago
deleted cf_cyclo.inc and cf_map_ext.inc, added cf_cyclo.cc,.h and cf_map_ext.cc, .h git-svn-id: file:///usr/local/Singular/svn/trunk@12776 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.5 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 * @internal
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"
25#include "cf_util.h"
26
27#ifdef HAVE_NTL
28#include <NTL/ZZ_pEXFactoring.h>
29#include "NTLconvert.h"
30#endif
31
32// cyclotomoic polys:
33#include "cf_cyclo.h"
34
35#ifdef HAVE_NTL
36
37/// helper function
38static inline
39int findItem (const CFList& list, const CanonicalForm& item) 
40{
41  int result= 1; 
42  for (CFListIterator i= list; i.hasItem(); i++, result++) 
43  {
44    if (i.getItem() == item)
45      return result;
46  }
47  return 0;
48}
49
50/// helper function
51static inline
52CanonicalForm getItem (const CFList& list, const int& pos) 
53{
54  int j= 1;
55  if (pos > list.length() || pos < 1) return 0;
56  for (CFListIterator i= list; j <= pos; i++, j++) 
57  {
58    if (j == pos) 
59      return i.getItem();
60  }
61} 
62
63
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  zz_p::init (p);
71  zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta)); 
72  zz_pE::init (NTL_mipo);
73  zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo);
74  zz_pE root= FindRoot (NTL_alpha_mipo);
75  return convertNTLzzpE2CF (root, beta);
76}
77
78/// the CanonicalForm G is the output of map_up, returns F considered as an
79/// element over \f$ F_{p}(\alpha ) \f$, WARNING: make sure coefficients of F
80/// are really elements of a subfield of \f$ F_{p}(\beta ) \f$ which is
81/// isomorphic to \f$ F_{p}(\alpha ) \f$
82static inline
83CanonicalForm
84mapDown (const CanonicalForm& F, const Variable& alpha, const
85          CanonicalForm& G, CFList& source, CFList& dest) 
86{   
87  CanonicalForm buf, buf2;
88  int counter= 0;
89  int pos;
90  int p= getCharacteristic();
91  int d= degree(getMipo(alpha));
92  int bound= ipower(p, d);
93  CanonicalForm result= 0;
94  CanonicalForm remainder;
95  CanonicalForm alpha_power;
96  if (degree(F) == 0) return F;
97  if (F.level() < 0 && F.isUnivariate()) 
98  {
99    buf= F;
100    remainder= mod (buf, G);
101    ASSERT (remainder.isZero(), "alpha is not primitive"); 
102    pos= findItem (source, buf);
103    if (pos == 0)
104      source.append (buf);
105    buf2= buf;
106    while (degree (buf) != 0 && counter < bound) 
107    {
108      buf /= G;
109      counter++;
110      if (buf == buf2) break;
111    } 
112    ASSERT (counter >= bound, "alpha is not primitive"); 
113    if (pos == 0) 
114    {
115      alpha_power= power (alpha, counter);
116      dest.append (alpha_power);
117    }
118    else
119      alpha_power= getItem (dest, pos);     
120    result = alpha_power*buf;
121    return result;
122  }
123  else 
124  {
125    for (CFIterator i= F; i.hasTerms(); i++) 
126    {
127      buf= mapDown (i.coeff(), alpha, G, source, dest);
128      result += buf*power(F.mvar(), i.exp());
129    }
130    return result;
131  }
132}
133
134/// helper function
135static inline
136CanonicalForm GF2FalphaHelper (const CanonicalForm& F, const Variable& alpha)
137{
138  int exp;
139  CanonicalForm result= 0;
140  char gf_name_buf= gf_name;
141  InternalCF* buf;
142  if (F.inBaseDomain()) 
143  {
144    if (F.isOne()) return 1;
145    buf= F.getval();
146    exp= imm2int(buf);
147    result= power (alpha, exp).mapinto();
148    return result;
149  } 
150  for (CFIterator i= F; i.hasTerms(); i++)
151    result += GF2FalphaHelper (i.coeff(), alpha)*power (F.mvar(), i.exp());
152  return result;
153}
154
155/// changes representation by primitive element to representation by residue
156/// classes modulo a Conway polynomial
157CanonicalForm GF2FalphaRep (const CanonicalForm& F, const Variable& alpha) 
158{
159  Variable beta= rootOf (gf_mipo);
160  return GF2FalphaHelper (F, beta) (alpha, beta);
161}
162
163/// change representation by residue classes modulo a Conway polynomial
164/// to representation by primitive element
165CanonicalForm Falpha2GFRep (const CanonicalForm& F) 
166{
167  CanonicalForm result= 0;
168  InternalCF* buf;
169
170  if (F.inCoeffDomain()) 
171  {
172    if (F.inBaseDomain())
173      return F.mapinto();
174    else 
175    {
176      for (CFIterator i= F; i.hasTerms(); i++) 
177      {
178        buf= int2imm_gf (i.exp());
179        result += i.coeff().mapinto()*CanonicalForm (buf);
180      }
181    }
182    return result;
183  } 
184  for (CFIterator i= F; i.hasTerms(); i++) 
185    result += Falpha2GFRep (i.coeff())*power (F.mvar(), i.exp());
186  return result;
187}
188
189/// GF_map_up helper
190static inline
191CanonicalForm GFPowUp (const CanonicalForm & F, int k) 
192{
193  if (F.isOne()) return F;
194  CanonicalForm result= 0;
195  if (F.inBaseDomain()) 
196    return power(F, k);
197  for (CFIterator i= F; i.hasTerms(); i++) 
198    result += GFPowUp (i.coeff(), k)*power (F.mvar(), i.exp());
199  return result;
200}
201
202/// maps a polynomial over \f$ GF(p^{k}) \f$ to a polynomial over
203/// \f$ GF(p^{d}) \f$ , d needs to be a multiple of k
204CanonicalForm GFMapUp (const CanonicalForm & F, int k) 
205{ 
206  int d= getGFDegree();
207  ASSERT (d%k == 0, "multiple of GF degree expected");
208  int p= getCharacteristic();
209  int ext_field_size= ipower (p, d);
210  int field_size= ipower ( p, k);
211  int diff= (ext_field_size - 1)/(field_size - 1);
212  return GFPowUp (F, diff);
213}
214
215/// GFMapDown helper
216static inline
217CanonicalForm GFPowDown (const CanonicalForm & F, int k) 
218{
219  if (F.isOne()) return F;
220  CanonicalForm result= 0;
221  int exp;
222  InternalCF* buf;
223  if (F.inBaseDomain()) 
224  {
225    buf= F.getval();
226    exp= imm2int (buf);
227    if ((exp % k) == 0)
228      exp= exp/k;
229    else 
230      return -1;
231
232    buf= int2imm_gf (exp);
233    return CanonicalForm (buf);
234  } 
235  for (CFIterator i= F; i.hasTerms(); i++) 
236    result += GFPowDown (i.coeff(), k)*power (F.mvar(), i.exp());
237  return result;
238}
239
240/// maps a polynomial over \f$ GF(p^{d}) \f$ to a polynomial over
241/// \f$ GF(p^{k})\f$ , d needs to be a multiple of k
242CanonicalForm GFMapDown (const CanonicalForm & F, int k) 
243{
244  int d= getGFDegree();
245  ASSERT (d % k == 0, "multiple of GF degree expected");
246  int p= getCharacteristic();
247  int ext_field_size= ipower (p, d);
248  int field_size= ipower ( p, k);
249  int diff= (ext_field_size - 1)/(field_size - 1);
250  return GFPowDown (F, diff);
251}
252
253static inline 
254CanonicalForm mapUp (const CanonicalForm& F, const CanonicalForm& G, 
255                      const Variable& alpha, const CanonicalForm& H, 
256                      CFList& source, CFList& dest)
257{ 
258  CanonicalForm buf, buf2;
259  int counter= 0;
260  int pos;
261  int p= getCharacteristic();
262  int d= degree (getMipo(alpha));
263  int bound= ipower(p, d);
264  CanonicalForm result= 0;
265  CanonicalForm remainder;
266  CanonicalForm H_power;
267  if (degree(F) <= 0) return F;
268  if (F.level() < 0 && F.isUnivariate()) 
269  {
270    buf= F;
271    remainder= mod (buf, G);
272    ASSERT (remainder.isZero(), "alpha is not primitive"); 
273    pos= findItem (source, buf);
274    if (pos == 0)
275      source.append (buf);
276    buf2= buf;
277    while (degree (buf) != 0 && counter < bound) 
278    {
279      buf /= G;
280      counter++;
281      if (buf == buf2) break;
282    } 
283    ASSERT (counter >= bound, "alpha is not primitive"); 
284    if (pos == 0) 
285    {
286      H_power= power (H, counter);
287      dest.append (H_power);
288    }
289    else
290      H_power= getItem (dest, pos);     
291    result = H_power*buf;
292    return result;
293  }
294  else 
295  {
296    for (CFIterator i= F; i.hasTerms(); i++) 
297    {
298      buf= mapUp (i.coeff(), G, alpha, H, source, dest);
299      result += buf*power(F.mvar(), i.exp());
300    }
301    return result;
302  }
303}
304
305/// determine a primitive element of \f$ F_{p} (\alpha ) \f$,
306/// \f$ \beta \f$ is a primitive element of a field which is isomorphic to
307/// \f$ F_{p}(\alpha ) \f$
308CanonicalForm
309primitiveElement (const Variable& alpha, Variable& beta, bool fail) 
310{
311  bool primitive= false;
312  fail= false;
313  primitive= isPrimitive (alpha, fail);
314  if (fail)
315    return 0;
316  if (primitive) 
317  {
318    beta= alpha;
319    return alpha;
320  }
321  CanonicalForm mipo= getMipo (alpha); 
322  int d= degree (mipo);
323  int p= getCharacteristic ();
324  zz_p::init (p);
325  zz_pX NTL_mipo;
326  CanonicalForm mipo2;
327  primitive= false;
328  fail= false;
329  do
330  {
331    BuildIrred (NTL_mipo, d); 
332    mipo2= convertNTLzzpX2CF (NTL_mipo, Variable (1));
333    beta= rootOf (mipo2);
334    primitive= isPrimitive (beta, fail);
335    if (primitive)
336      break; 
337    if (fail)
338      return 0;
339  } while (1);
340  zz_pE::init (NTL_mipo);
341  zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (mipo, NTL_mipo);
342  zz_pE root= FindRoot (NTL_alpha_mipo);
343  return convertNTLzzpE2CF (root, alpha);
344}
345
346CanonicalForm
347mapDown (const CanonicalForm& F, const CanonicalForm& prim_elem, const
348          CanonicalForm& im_prim_elem, const Variable& alpha, CFList& source, 
349          CFList& dest) 
350{   
351  return mapUp (F, im_prim_elem, alpha, prim_elem, dest, source);
352}
353
354CanonicalForm
355mapUp (const CanonicalForm& F, const Variable& alpha, const Variable& beta, 
356        const CanonicalForm& prim_elem, const CanonicalForm& im_prim_elem, 
357        CFList& source, CFList& dest) 
358{
359  if (prim_elem == alpha) 
360    return F (im_prim_elem, alpha);
361  return mapUp (F, prim_elem, alpha, im_prim_elem, source, dest);
362}
363
364CanonicalForm
365mapPrimElem (const CanonicalForm& prim_elem, const Variable& alpha, 
366             const Variable& beta)
367{
368  if (prim_elem == alpha)
369    return mapUp (alpha, beta);
370  else
371  {
372    CanonicalForm im_alpha= mapUp (alpha, beta);
373    CanonicalForm result= 0;
374    for (CFIterator i= prim_elem; i.hasTerms(); i++)
375      result += power (im_alpha, i.exp())*i.coeff();
376    return result;
377  } 
378}
379
380#endif
Note: See TracBrowser for help on using the repository browser.