source: git/factory/facAlgFuncUtil.cc @ ae8a3a

spielwiese
Last change on this file since ae8a3a was ae8a3a, checked in by Martin Lee <martinlee84@…>, 9 years ago
fix: bug in substitution
  • Property mode set to 100644
File size: 15.1 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file facAlgFuncUtil.cc
5 *
6 * This file provides utility functions to factorize polynomials over alg.
7 * function fields
8 *
9 * @note some of the code is code from libfac or derived from code from libfac.
10 * Libfac is written by M. Messollen. See also COPYING for license information
11 * and README for general information on characteristic sets.
12 *
13 * @author Martin Lee
14 *
15 **/
16/*****************************************************************************/
17
18#include "config.h"
19
20#include "cf_assert.h"
21
22#include "canonicalform.h"
23#include "facAlgFuncUtil.h"
24#include "cfCharSetsUtil.h"
25#include "cf_random.h"
26#include "cf_irred.h"
27#include "cf_algorithm.h"
28#include "cf_util.h"
29#include "cf_iter.h"
30
31CFFList
32append (const CFFList & Inputlist, const CFFactor & TheFactor)
33{
34  CFFList Outputlist;
35  CFFactor copy;
36  CFFListIterator i;
37  int exp=0;
38
39  for (i= Inputlist; i.hasItem() ; i++)
40  {
41    copy= i.getItem();
42    if (copy.factor() == TheFactor.factor())
43      exp += copy.exp();
44    else
45      Outputlist.append(copy);
46  }
47  Outputlist.append (CFFactor (TheFactor.factor(), exp + TheFactor.exp()));
48  return Outputlist;
49}
50
51CFFList
52merge (const CFFList & Inputlist1, const CFFList & Inputlist2)
53{
54  CFFList Outputlist;
55  CFFListIterator i;
56
57  for (i= Inputlist1; i.hasItem(); i++)
58    Outputlist= append (Outputlist, i.getItem());
59  for (i= Inputlist2; i.hasItem() ; i++)
60    Outputlist= append (Outputlist, i.getItem());
61
62  return Outputlist;
63}
64
65Varlist
66varsInAs (const Varlist & uord, const CFList & Astar)
67{
68  Varlist output;
69  CanonicalForm elem;
70  Variable x;
71
72  for (VarlistIterator i= uord; i.hasItem(); i++)
73  {
74    x= i.getItem();
75    for (CFListIterator j= Astar; j.hasItem(); j++ )
76    {
77      elem= j.getItem();
78      if (degree (elem, x) > 0) // x actually occures in Astar
79      {
80        output.append (x);
81        break;
82      }
83    }
84  }
85  return output;
86}
87
88// generate an irreducible poly of degree degOfExt over F_p
89CanonicalForm
90generateMipo (int degOfExt)
91{
92#ifndef HAVE_NTL
93  FFRandom gen;
94  return find_irreducible (degOfExt, gen, Variable (1));
95#else
96  return randomIrredpoly (degOfExt, Variable (1));
97#endif
98}
99
100CanonicalForm alg_lc (const CanonicalForm & f)
101{
102  if (f.level()>0)
103  {
104    return alg_lc(f.LC());
105  }
106
107  return f;
108}
109
110CanonicalForm alg_LC (const CanonicalForm& f, int lev)
111{
112  CanonicalForm result= f;
113  while (result.level() > lev)
114    result= LC (result);
115  return result;
116}
117
118
119CanonicalForm
120subst (const CanonicalForm& f, const CFList& a, const CFList& b,
121       const CanonicalForm& Rstar, bool isFunctionField)
122{
123  if (isFunctionField)
124    ASSERT ((a.length() - 1)*4 == b.length() || (a.length() == 1 && b.length() == 2), "wrong length of lists");
125  else
126    ASSERT ((a.length() - 1)*2 == b.length() || (a.length() == 1 && b.length() == 1), "lists of equal length expected");
127  CFListIterator j= b;
128  CanonicalForm result= f, tmp, powj, tmp3;
129  CFListIterator i= a;
130  CanonicalForm tmp1= i.getItem();
131  i++;
132  CanonicalForm tmp2= j.getItem();
133  j++;
134  for (;i.hasItem() && j.hasItem(); i++, j++)
135  {
136    if (!isFunctionField)
137    {
138      result= result (j.getItem(), i.getItem().mvar());
139      result= result (tmp2, tmp1.mvar());
140      tmp1= i.getItem();
141      j++;
142      if (j.hasItem())
143        tmp2= j.getItem();
144    }
145    else
146    {
147        tmp= j.getItem();
148        j++;
149        tmp3= j.getItem();
150        j++;
151        powj= power (j.getItem(), degree (result, i.getItem().mvar()));
152        result= evaluate (result, tmp3, j.getItem(), powj, i.getItem().mvar());
153
154        if (fdivides (powj, result, tmp3))
155          result= tmp3;
156
157        result /= vcontent (result, Variable (i.getItem().level() + 1));
158
159        powj= power (tmp, degree (result, tmp1.mvar()));
160        result= evaluate (result, tmp2, tmp, powj, tmp1.mvar());
161
162        if (fdivides (powj, result, tmp))
163          result= tmp;
164
165        result /= vcontent (result, Variable (tmp1.level() + 1));
166        tmp1= i.getItem();
167        j++;
168        if (j.hasItem())
169          tmp2= j.getItem();
170    }
171  }
172  result= Prem (result, CFList (Rstar));
173  result /= vcontent (result, Variable (Rstar.level() + 1));
174  return result;
175}
176
177CanonicalForm
178backSubst (const CanonicalForm& F, const CFList& a, const CFList& b)
179{
180  ASSERT (a.length() == b.length() - 1, "wrong length of lists in backSubst");
181  CanonicalForm result= F;
182  Variable tmp;
183  CFList tmp2= b;
184  tmp= tmp2.getLast().mvar();
185  tmp2.removeLast();
186  for (CFListIterator iter= a; iter.hasItem(); iter++)
187  {
188    result= result (tmp+iter.getItem()*tmp2.getLast().mvar(), tmp);
189    tmp= tmp2.getLast().mvar();
190    tmp2.removeLast();
191  }
192  return result;
193}
194
195void deflateDegree (const CanonicalForm & F, int & pExp, int n)
196{
197  if (n == 0 || n > F.level())
198  {
199    pExp= -1;
200    return;
201  }
202  if (F.level() == n)
203  {
204    ASSERT (F.deriv().isZero(), "derivative of F is not zero");
205    int termCount=0;
206    CFIterator i= F;
207    for (; i.hasTerms(); i++)
208    {
209      if (i.exp() != 0)
210        termCount++;
211    }
212
213    int j= 1;
214    i= F;
215    for (;j < termCount; j++, i++)
216      ;
217
218    int exp= i.exp();
219    int count= 0;
220    int p= getCharacteristic();
221    while ((exp >= p) && (exp != 0) && (exp % p == 0))
222    {
223      exp /= p;
224      count++;
225    }
226    pExp= count;
227  }
228  else
229  {
230    CFIterator i= F;
231    deflateDegree (i.coeff(), pExp, n);
232    i++;
233    int tmp= pExp;
234    for (; i.hasTerms(); i++)
235    {
236      deflateDegree (i.coeff(), pExp, n);
237      if (tmp == -1)
238        tmp= pExp;
239      else if (tmp != -1 && pExp != -1)
240        pExp= (pExp < tmp) ? pExp : tmp;
241      else
242        pExp= tmp;
243    }
244  }
245}
246
247CanonicalForm deflatePoly (const CanonicalForm & F, int exp)
248{
249  if (exp == 0)
250    return F;
251  int p= getCharacteristic();
252  int pToExp= ipower (p, exp);
253  Variable x=F.mvar();
254  CanonicalForm result= 0;
255  for (CFIterator i= F; i.hasTerms(); i++)
256    result += i.coeff()*power (x, i.exp()/pToExp);
257  return result;
258}
259
260CanonicalForm deflatePoly (const CanonicalForm & F, int exps, int n)
261{
262  if (n == 0 || exps <= 0 || F.level() < n)
263    return F;
264  if (F.level() == n)
265    return deflatePoly (F, exps);
266  else
267  {
268    CanonicalForm result= 0;
269    for (CFIterator i= F; i.hasTerms(); i++)
270      result += deflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
271    return result;
272  }
273}
274
275CanonicalForm inflatePoly (const CanonicalForm & F, int exp)
276{
277  if (exp == 0)
278    return F;
279  int p= getCharacteristic();
280  int pToExp= ipower (p, exp);
281  Variable x=F.mvar();
282  CanonicalForm result= 0;
283  for (CFIterator i= F; i.hasTerms(); i++)
284    result += i.coeff()*power (x, i.exp()*pToExp);
285  return result;
286}
287
288CanonicalForm inflatePoly (const CanonicalForm & F, int exps, int n)
289{
290  if (n == 0 || exps <= 0 || F.level() < n)
291    return F;
292  if (F.level() == n)
293    return inflatePoly (F, exps);
294  else
295  {
296    CanonicalForm result= 0;
297    for (CFIterator i= F; i.hasTerms(); i++)
298      result += inflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
299    return result;
300  }
301}
302
303void
304multiplicity (CFFList& factors, const CanonicalForm& F, const CFList& as)
305{
306  CanonicalForm G= F;
307  Variable x= F.mvar();
308  CanonicalForm q, r;
309  int count= -1;
310  for (CFFListIterator iter=factors; iter.hasItem(); iter++)
311  {
312    count= -1;
313    if (iter.getItem().factor().inCoeffDomain())
314      continue;
315    while (1)
316    {
317      psqr (G, iter.getItem().factor(), q, r, x);
318
319      q= Prem (q, as);
320      r= Prem (r, as);
321      if (!r.isZero())
322        break;
323      count++;
324      G= q;
325    }
326    iter.getItem()= CFFactor (iter.getItem().factor(),
327                              iter.getItem().exp() + count);
328  }
329}
330
331int hasAlgVar (const CanonicalForm &f, const Variable &v)
332{
333  if (f.inBaseDomain())
334    return 0;
335  if (f.inCoeffDomain())
336  {
337    if (f.mvar() == v)
338      return 1;
339    return hasAlgVar (f.LC(), v);
340  }
341  if (f.inPolyDomain())
342  {
343    if (hasAlgVar(f.LC(), v))
344      return 1;
345    for (CFIterator i= f; i.hasTerms(); i++)
346    {
347      if (hasAlgVar (i.coeff(), v))
348        return 1;
349    }
350  }
351  return 0;
352}
353
354int hasVar (const CanonicalForm &f, const Variable &v)
355{
356  if (f.inBaseDomain())
357    return 0;
358  if (f.inCoeffDomain())
359  {
360    if (f.mvar() == v)
361      return 1;
362    return hasAlgVar (f.LC(), v);
363  }
364  if (f.inPolyDomain())
365  {
366    if (f.mvar() == v)
367      return 1;
368    if (hasVar (f.LC(), v))
369      return 1;
370    for (CFIterator i= f; i.hasTerms(); i++)
371    {
372      if (hasVar (i.coeff(), v))
373        return 1;
374    }
375  }
376  return 0;
377}
378
379int hasAlgVar (const CanonicalForm &f)
380{
381  if (f.inBaseDomain())
382    return 0;
383  if (f.inCoeffDomain())
384  {
385    if (f.level() != 0)
386      return 1;
387    return hasAlgVar(f.LC());
388  }
389  if (f.inPolyDomain())
390  {
391    if (hasAlgVar(f.LC()))
392      return 1;
393    for (CFIterator i= f; i.hasTerms(); i++)
394    {
395      if (hasAlgVar (i.coeff()))
396        return 1;
397    }
398  }
399  return 0;
400}
401
402/// pseudo division of f and g wrt. x s.t. multiplier*f=q*g+r
403void
404psqr (const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q,
405      CanonicalForm & r, CanonicalForm& multiplier, const Variable& x)
406{
407    ASSERT( x.level() > 0, "type error: polynomial variable expected" );
408    ASSERT( ! g.isZero(), "math error: division by zero" );
409
410    // swap variables such that x's level is larger or equal
411    // than both f's and g's levels.
412    Variable X;
413    if (f.level() > g.level())
414      X= f.mvar();
415    else
416      X= g.mvar();
417    if (X.level() < x.level())
418      X= x;
419    CanonicalForm F= swapvar (f, x, X);
420    CanonicalForm G= swapvar (g, x, X);
421
422    // now, we have to calculate the pseudo remainder of F and G
423    // w.r.t. X
424    int fDegree= degree (F, X);
425    int gDegree= degree (G, X);
426    if (fDegree < 0 || fDegree < gDegree)
427    {
428      q= 0;
429      r= f;
430    }
431    else
432    {
433      CanonicalForm LCG= LC (G, X);
434      multiplier= power (LCG, fDegree - gDegree + 1);
435      divrem (multiplier*F, G, q, r);
436      q= swapvar (q, x, X);
437      r= swapvar (r, x, X);
438    }
439}
440
441CanonicalForm
442Sprem (const CanonicalForm &f, const CanonicalForm &g, CanonicalForm & m,
443       CanonicalForm & q )
444{
445  CanonicalForm ff, gg, l, test, retvalue;
446  int df, dg,n;
447  bool reord;
448  Variable vf, vg, v;
449
450  if ((vf = f.mvar()) < (vg = g.mvar()))
451  {
452    m= 0;
453    q= 0;
454    return f;
455  }
456  else
457  {
458    if ( vf == vg )
459    {
460      ff= f;
461      gg= g;
462      reord= false;
463      v= vg; // == x
464    }
465    else
466    {
467      v= Variable (f.level() + 1);
468      ff= swapvar (f, vg, v); // == r
469      gg= swapvar (g, vg, v); // == v
470      reord=true;
471    }
472    dg= degree (gg, v); // == dv
473    df= degree (ff, v); // == dr
474    if (dg <= df)
475    {
476      l= LC (gg);
477      gg= gg - LC(gg)*power(v,dg);
478    }
479    else
480      l = 1;
481    n= 0;
482    while ((dg <= df) && (!ff.isZero()))
483    {
484      test= gg*LC (ff)*power (v, df - dg);
485      if (df == 0)
486        ff= 0;
487      else
488        ff= ff - LC(ff)*power(v,df);
489      ff= l*ff - test;
490      df= degree (ff, v);
491      n++;
492    }
493
494    if (reord)
495      retvalue= swapvar (ff, vg, v);
496    else
497      retvalue= ff;
498
499    m= power (l, n);
500    if (fdivides (g, m*f - retvalue))
501      q= (m*f - retvalue)/g;
502    else
503      q= 0;
504    return retvalue;
505  }
506}
507
508CanonicalForm
509divide (const CanonicalForm & ff, const CanonicalForm & f, const CFList & as)
510{
511  CanonicalForm r, m, q;
512
513  if (f.inCoeffDomain())
514  {
515    bool isRat= isOn(SW_RATIONAL);
516    if (getCharacteristic() == 0)
517      On(SW_RATIONAL);
518    q= ff/f;
519    if (!isRat && getCharacteristic() == 0)
520      Off(SW_RATIONAL);
521  }
522  else
523    r= Sprem (ff, f, m, q);
524
525  r= Prem (q, as);
526  return r;
527}
528
529// check if polynomials in Astar define a separable extension
530bool
531isInseparable (const CFList & Astar)
532{
533  CanonicalForm elem;
534
535  if (Astar.length() == 0)
536    return false;
537  for (CFListIterator i= Astar; i.hasItem(); i++)
538  {
539    elem= i.getItem();
540    if (elem.deriv().isZero())
541      return true;
542  }
543  return false;
544}
545
546// calculate big enough extension for finite fields
547// Idea: first calculate k, such that q^k > S (->thesis)
548// Second, search k with gcd(k,m_i)=1, where m_i is the degree of the i'th
549// minimal polynomial. Then the minpoly f_i remains irrd. over q^k and we
550// have enough elements to plug in.
551int
552getDegOfExt (IntList & degreelist, int n)
553{
554  int charac= getCharacteristic();
555  setCharacteristic(0); // need it for k !
556  int k= 1, m= 1, length= degreelist.length();
557  IntListIterator i;
558
559  for (i= degreelist; i.hasItem(); i++)
560     m= m*i.getItem();
561  int q= charac;
562  while (q <= ((n*m)*(n*m)/2))
563  {
564    k= k+1;
565    q= q*charac;
566  }
567  int l= 0;
568  do
569  {
570    for (i= degreelist; i.hasItem(); i++)
571    {
572      l= l + 1;
573      if (igcd (k, i.getItem()) == 1)
574      {
575        if (l == length)
576        {
577          setCharacteristic (charac);
578          return k;
579        }
580      }
581      else
582        break;
583    }
584    k= k + 1;
585    l= 0;
586  }
587  while (1);
588}
589
590CanonicalForm
591QuasiInverse (const CanonicalForm& f, const CanonicalForm& g,
592              const Variable& x)
593{
594  CanonicalForm pi, pi1, q, t0, t1, Hi, bi, pi2;
595  bool isRat= isOn (SW_RATIONAL);
596  pi= f;
597  pi1= g;
598  if (isRat)
599  {
600    pi *= bCommonDen (pi);
601    pi1 *= bCommonDen (pi1);
602  }
603  CanonicalForm m,tmp;
604  if (isRat && getCharacteristic() == 0)
605    Off (SW_RATIONAL);
606
607  pi= pi/content (pi,x);
608  pi1= pi1/content (pi1,x);
609
610  t0= 0;
611  t1= 1;
612  bi= 1;
613
614  int delta= degree (f, x) - degree (g, x);
615  Hi= power (LC (pi1, x), delta);
616  if ( (delta+1) % 2 )
617      bi = 1;
618  else
619      bi = -1;
620
621  while (degree (pi1,x) > 0)
622  {
623    psqr (pi, pi1, q, pi2, m, x);
624    pi2 /= bi;
625
626    tmp= t1;
627    t1= t0*m - t1*q;
628    t0= tmp;
629    t1 /= bi;
630    pi= pi1;
631    pi1= pi2;
632    if (degree (pi1, x) > 0)
633    {
634      delta= degree (pi, x) - degree (pi1, x);
635      if ((delta + 1) % 2)
636        bi= LC (pi, x)*power (Hi, delta);
637      else
638        bi= -LC (pi, x)*power (Hi, delta);
639      Hi= power (LC (pi1, x), delta)/power (Hi, delta - 1);
640    }
641  }
642  t1 /= gcd (pi1, t1);
643  if (isRat && getCharacteristic() == 0)
644    On (SW_RATIONAL);
645  return t1;
646}
647
648CanonicalForm
649evaluate (const CanonicalForm& f, const CanonicalForm& g,
650          const CanonicalForm& h, const CanonicalForm& powH)
651{
652  if (f.inCoeffDomain())
653    return f;
654  CFIterator i= f;
655  int lastExp = i.exp();
656  CanonicalForm result = i.coeff()*powH;
657  i++;
658  while (i.hasTerms())
659  {
660    int i_exp= i.exp();
661    if ((lastExp - i_exp) == 1)
662    {
663      result *= g;
664      result /= h;
665    }
666    else
667    {
668      result *= power (g, lastExp - i_exp);
669      result /= power (h, lastExp - i_exp);
670    }
671    result += i.coeff()*powH;
672    lastExp = i_exp;
673    i++;
674  }
675  if (lastExp != 0)
676  {
677    result *= power (g, lastExp);
678    result /= power (h, lastExp);
679  }
680  return result;
681}
682
683
684/// evaluate f at g/h at v such that powH*f is integral i.e. powH is assumed to be h^degree(f,v)
685CanonicalForm
686evaluate (const CanonicalForm& f, const CanonicalForm& g,
687          const CanonicalForm& h, const CanonicalForm& powH,
688          const Variable& v)
689{
690  if (f.inCoeffDomain())
691  {
692    return f*powH;
693  }
694
695  Variable x = f.mvar();
696  if ( v > x )
697    return f*powH;
698  else  if ( v == x )
699    return evaluate (f, g, h, powH);
700
701  // v is less than main variable of f
702  CanonicalForm result= 0;
703  for (CFIterator i= f; i.hasTerms(); i++)
704    result += evaluate (i.coeff(), g, h, powH, v)*power (x, i.exp());
705  return result;
706}
707
708
Note: See TracBrowser for help on using the repository browser.