source: git/factory/facFqSquarefree.cc @ 1a688ba

spielwiese
Last change on this file since 1a688ba was 1a688ba, checked in by Martin Lee <martinlee84@…>, 10 years ago
chg: use FLINT instead of NTL in squarefree factorization
  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file facFqSquarefree.cc
5 *
6 * This file provides functions for squarefrees factorizing over
7 * \f$ F_{p} \f$ , \f$ F_{p}(\alpha ) \f$ or GF, as decribed in "Factoring
8 * multivariate polynomials over a finite field" by L. Bernardin
9 *
10 * @author Martin Lee
11 *
12 **/
13/*****************************************************************************/
14
15#ifdef HAVE_CONFIG_H
16#include "config.h"
17#endif /* HAVE_CONFIG_H */
18
19#include "canonicalform.h"
20
21#include "cf_gcd_smallp.h"
22#include "cf_iter.h"
23#include "cf_map.h"
24#include "cf_util.h"
25#include "cf_factory.h"
26#include "facFqSquarefree.h"
27
28#ifdef HAVE_NTL
29#include "NTLconvert.h"
30#endif
31
32#ifdef HAVE_FLINT
33#include "FLINTconvert.h"
34#endif
35
36static inline
37CanonicalForm
38pthRoot (const CanonicalForm & F, const int & q)
39{
40  CanonicalForm A= F;
41  int p= getCharacteristic ();
42  if (A.inCoeffDomain())
43  {
44    A= power (A, q/p);
45    return A;
46  }
47  else
48  {
49    CanonicalForm buf= 0;
50    for (CFIterator i= A; i.hasTerms(); i++)
51      buf= buf + power(A.mvar(), i.exp()/p)*pthRoot (i.coeff(), q);
52    return buf;
53  }
54}
55
56#ifdef HAVE_NTL
57CanonicalForm
58pthRoot (const CanonicalForm & F, const ZZ& q, const Variable& alpha)
59{
60  CanonicalForm A= F;
61  int p= getCharacteristic ();
62  if (A.inCoeffDomain())
63  {
64    zz_p::init (p);
65    zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
66    zz_pE::init (NTLMipo);
67    zz_pX NTLA= convertFacCF2NTLzzpX (A);
68    zz_pE NTLA2= to_zz_pE (NTLA);
69    power (NTLA2, NTLA2, q/p);
70    A= convertNTLzzpE2CF (NTLA2, alpha);
71    return A;
72  }
73  else
74  {
75    CanonicalForm buf= 0;
76    for (CFIterator i= A; i.hasTerms(); i++)
77      buf= buf + power(A.mvar(), i.exp()/p)*pthRoot (i.coeff(), q, alpha);
78    return buf;
79  }
80}
81#endif
82
83#if (HAVE_FLINT && __FLINT_VERSION_MINOR >= 4)
84CanonicalForm
85pthRoot (const CanonicalForm & F, const fmpz_t& q, const Variable& alpha)
86{
87  CanonicalForm A= F;
88  int p= getCharacteristic ();
89  if (A.inCoeffDomain())
90  {
91    nmod_poly_t FLINTmipo;
92    fq_nmod_ctx_t fq_con;
93    fmpz_t qp;
94    fq_nmod_t FLINTA;
95
96    nmod_poly_init (FLINTmipo, p);
97    convertFacCF2nmod_poly_t (FLINTmipo, getMipo (alpha));
98
99    fq_nmod_ctx_init_modulus (fq_con, FLINTmipo, "Z");
100
101    fq_nmod_init2 (FLINTA, fq_con);
102
103    convertFacCF2Fq_nmod_t (FLINTA, A, fq_con);
104
105    fmpz_init_set (qp, q);
106    fmpz_divexact_si (qp, qp, p);
107
108    fq_nmod_pow (FLINTA, FLINTA, qp, fq_con);
109    A= convertFq_nmod_t2FacCF (FLINTA, alpha);
110
111    fmpz_clear (qp);
112    nmod_poly_clear (FLINTmipo);
113    fq_nmod_clear (FLINTA, fq_con);
114    fq_nmod_ctx_clear (fq_con);
115    return A;
116  }
117  else
118  {
119    CanonicalForm buf= 0;
120    for (CFIterator i= A; i.hasTerms(); i++)
121      buf= buf + power(A.mvar(), i.exp()/p)*pthRoot (i.coeff(), q, alpha);
122    return buf;
123  }
124}
125#endif
126
127CanonicalForm
128maxpthRoot (const CanonicalForm & F, const int & q, int& l)
129{
130  CanonicalForm result= F;
131  bool derivZero= true;
132  l= 0;
133  while (derivZero)
134  {
135    for (int i= 1; i <= result.level(); i++)
136    {
137      if (!deriv (result, Variable (i)).isZero())
138      {
139        derivZero= false;
140        break;
141      }
142    }
143    if (!derivZero)
144      break;
145    result= pthRoot (result, q);
146    l++;
147  }
148  return result;
149}
150
151static inline
152CFFList
153sqrfPosDer (const CanonicalForm & F, const Variable & x,
154            CanonicalForm & c)
155{
156  CanonicalForm b= deriv (F, x);
157  c= gcd (F, b);
158  CanonicalForm w= F/c;
159  CanonicalForm v= b/c;
160  CanonicalForm u= v - deriv (w, x);
161  int j= 1;
162  int p= getCharacteristic();
163  CanonicalForm g;
164  CFFList result;
165  while (j < p - 1 && degree(u) >= 0)
166  {
167    g= gcd (w, u);
168    if (!g.inCoeffDomain())
169      result.append (CFFactor (g, j));
170    w= w/g;
171    c= c/w;
172    v= u/g;
173    u= v - deriv (w, x);
174    j++;
175  }
176  if (!w.inCoeffDomain())
177    result.append (CFFactor (w, j));
178  return result;
179}
180
181CFFList
182squarefreeFactorization (const CanonicalForm & F, const Variable & alpha)
183{
184  int p= getCharacteristic();
185  CanonicalForm A= F;
186  CFMap M;
187  A= compress (A, M);
188  Variable x= A.mvar();
189  int l= x.level();
190  int k;
191  if (CFFactory::gettype() == GaloisFieldDomain)
192    k= getGFDegree();
193  else if (alpha.level() != 1)
194    k= degree (getMipo (alpha));
195  else
196    k= 1;
197  Variable buf, buf2;
198  CanonicalForm tmp;
199
200  CFFList tmp1, tmp2;
201  bool found;
202  for (int i= l; i > 0; i--)
203  {
204    buf= Variable (i);
205    if (degree (deriv (A, buf)) >= 0)
206    {
207      tmp1= sqrfPosDer (A, buf, tmp);
208      A= tmp;
209      for (CFFListIterator j= tmp1; j.hasItem(); j++)
210      {
211        found= false;
212        CFFListIterator k= tmp2;
213        if (!k.hasItem() && !j.getItem().factor().inCoeffDomain()) tmp2.append (j.getItem());
214        else
215        {
216          for (; k.hasItem(); k++)
217          {
218            if (k.getItem().exp() == j.getItem().exp())
219            {
220              k.getItem()= CFFactor (k.getItem().factor()*j.getItem().factor(),
221                                     j.getItem().exp());
222              found= true;
223            }
224          }
225          if (found == false && !j.getItem().factor().inCoeffDomain())
226            tmp2.append(j.getItem());
227        }
228      }
229    }
230  }
231
232  bool degcheck= false;;
233  for (int i= l; i > 0; i--)
234  if (degree (A, Variable(i)) >= p)
235    degcheck= true;
236
237  if (degcheck == false && tmp1.isEmpty() && tmp2.isEmpty())
238    return CFFList (CFFactor (F/Lc(F), 1));
239
240  CanonicalForm buffer;
241#ifdef HAVE_NTL
242  if (alpha.level() == 1)
243#endif
244    buffer= pthRoot (A, ipower (p, k));
245#if (HAVE_FLINT && __FLINT_VERSION_MINOR >= 4)
246  else
247  {
248    fmpz_t qq;
249    fmpz_init_set_ui (qq, p);
250    fmpz_pow_ui (qq, qq, k);
251    buffer= pthRoot (A, qq, alpha);
252    fmpz_clear (qq);
253  }
254#else
255  else
256  {
257    ZZ q;
258    power (q, p, k);
259    buffer= pthRoot (A, q, alpha);
260  }
261#endif
262
263  tmp1= squarefreeFactorization (buffer, alpha);
264
265  CFFList result;
266  buf= alpha;
267  for (CFFListIterator i= tmp2; i.hasItem(); i++)
268  {
269    for (CFFListIterator j= tmp1; j.hasItem(); j++)
270    {
271      tmp= gcd (i.getItem().factor(), j.getItem().factor());
272      i.getItem()= CFFactor (i.getItem().factor()/tmp, i.getItem().exp());
273      j.getItem()= CFFactor (j.getItem().factor()/tmp, j.getItem().exp());
274      if (!tmp.inCoeffDomain())
275      {
276        tmp= M (tmp);
277        result.append (CFFactor (tmp/Lc(tmp),
278                       j.getItem().exp()*p + i.getItem().exp()));
279      }
280    }
281  }
282  for (CFFListIterator i= tmp2; i.hasItem(); i++)
283  {
284    if (!i.getItem().factor().inCoeffDomain())
285    {
286      tmp= M (i.getItem().factor());
287      result.append (CFFactor (tmp/Lc(tmp), i.getItem().exp()));
288    }
289  }
290  for (CFFListIterator j= tmp1; j.hasItem(); j++)
291  {
292    if (!j.getItem().factor().inCoeffDomain())
293    {
294      tmp= M (j.getItem().factor());
295      result.append (CFFactor (tmp/Lc(tmp), j.getItem().exp()*p));
296    }
297  }
298  return result;
299}
300
301CanonicalForm
302sqrfPart (const CanonicalForm& F, CanonicalForm& pthPower,
303          const Variable& alpha)
304{
305  if (F.inCoeffDomain())
306  {
307    pthPower= 1;
308    return F;
309  }
310  CFMap M;
311  CanonicalForm A= compress (F, M);
312  Variable vBuf= alpha;
313  CanonicalForm w, v, b;
314  pthPower= 1;
315  CanonicalForm result;
316  int i= 1;
317  bool allZero= true;
318  for (; i <= A.level(); i++)
319  {
320    if (!deriv (A, Variable (i)).isZero())
321    {
322      allZero= false;
323      break;
324    }
325  }
326  if (allZero)
327  {
328    pthPower= F;
329    return 1;
330  }
331  w= gcd (A, deriv (A, Variable (i)));
332
333  b= A/w;
334  result= b;
335  if (degree (w) < 1)
336    return M (result);
337  i++;
338  for (; i <= A.level(); i++)
339  {
340    if (!deriv (w, Variable (i)).isZero())
341    {
342      b= w;
343      w= gcd (w, deriv (w, Variable (i)));
344      b /= w;
345      if (degree (b) < 1)
346        break;
347      CanonicalForm g;
348      g= gcd (b, result);
349      if (degree (g) > 0)
350        result *= b/g;
351      if (degree (g) <= 0)
352        result *= b;
353    }
354  }
355  result= M (result);
356  return result;
357}
358
Note: See TracBrowser for help on using the repository browser.