source: git/factory/facAlgFuncUtil.cc @ 8d1432e

spielwiese
Last change on this file since 8d1432e was f8d2cd2, checked in by Martin Lee <martinlee84@…>, 9 years ago
fix bug in deflateDegree
  • Property mode set to 100644
File size: 14.9 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    CFIterator i= F;
206    int g= 0;
207    for (; i.hasTerms(); i++)
208        g= igcd (g, i.exp());
209
210    int count= 0;
211    int p= getCharacteristic();
212    while ((g >= p) && (g != 0) && (g % p == 0))
213    {
214      g /= p;
215      count++;
216    }
217    pExp= count;
218  }
219  else
220  {
221    CFIterator i= F;
222    deflateDegree (i.coeff(), pExp, n);
223    i++;
224    int tmp= pExp;
225    for (; i.hasTerms(); i++)
226    {
227      deflateDegree (i.coeff(), pExp, n);
228      if (tmp == -1)
229        tmp= pExp;
230      else if (tmp != -1 && pExp != -1)
231        pExp= (pExp < tmp) ? pExp : tmp;
232      else
233        pExp= tmp;
234    }
235  }
236}
237
238CanonicalForm deflatePoly (const CanonicalForm & F, int exp)
239{
240  if (exp == 0)
241    return F;
242  int p= getCharacteristic();
243  int pToExp= ipower (p, exp);
244  Variable x=F.mvar();
245  CanonicalForm result= 0;
246  for (CFIterator i= F; i.hasTerms(); i++)
247    result += i.coeff()*power (x, i.exp()/pToExp);
248  return result;
249}
250
251CanonicalForm deflatePoly (const CanonicalForm & F, int exps, int n)
252{
253  if (n == 0 || exps <= 0 || F.level() < n)
254    return F;
255  if (F.level() == n)
256    return deflatePoly (F, exps);
257  else
258  {
259    CanonicalForm result= 0;
260    for (CFIterator i= F; i.hasTerms(); i++)
261      result += deflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
262    return result;
263  }
264}
265
266CanonicalForm inflatePoly (const CanonicalForm & F, int exp)
267{
268  if (exp == 0)
269    return F;
270  int p= getCharacteristic();
271  int pToExp= ipower (p, exp);
272  Variable x=F.mvar();
273  CanonicalForm result= 0;
274  for (CFIterator i= F; i.hasTerms(); i++)
275    result += i.coeff()*power (x, i.exp()*pToExp);
276  return result;
277}
278
279CanonicalForm inflatePoly (const CanonicalForm & F, int exps, int n)
280{
281  if (n == 0 || exps <= 0 || F.level() < n)
282    return F;
283  if (F.level() == n)
284    return inflatePoly (F, exps);
285  else
286  {
287    CanonicalForm result= 0;
288    for (CFIterator i= F; i.hasTerms(); i++)
289      result += inflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
290    return result;
291  }
292}
293
294void
295multiplicity (CFFList& factors, const CanonicalForm& F, const CFList& as)
296{
297  CanonicalForm G= F;
298  Variable x= F.mvar();
299  CanonicalForm q, r;
300  int count= -1;
301  for (CFFListIterator iter=factors; iter.hasItem(); iter++)
302  {
303    count= -1;
304    if (iter.getItem().factor().inCoeffDomain())
305      continue;
306    while (1)
307    {
308      psqr (G, iter.getItem().factor(), q, r, x);
309
310      q= Prem (q, as);
311      r= Prem (r, as);
312      if (!r.isZero())
313        break;
314      count++;
315      G= q;
316    }
317    iter.getItem()= CFFactor (iter.getItem().factor(),
318                              iter.getItem().exp() + count);
319  }
320}
321
322int hasAlgVar (const CanonicalForm &f, const Variable &v)
323{
324  if (f.inBaseDomain())
325    return 0;
326  if (f.inCoeffDomain())
327  {
328    if (f.mvar() == v)
329      return 1;
330    return hasAlgVar (f.LC(), v);
331  }
332  if (f.inPolyDomain())
333  {
334    if (hasAlgVar(f.LC(), v))
335      return 1;
336    for (CFIterator i= f; i.hasTerms(); i++)
337    {
338      if (hasAlgVar (i.coeff(), v))
339        return 1;
340    }
341  }
342  return 0;
343}
344
345int hasVar (const CanonicalForm &f, const Variable &v)
346{
347  if (f.inBaseDomain())
348    return 0;
349  if (f.inCoeffDomain())
350  {
351    if (f.mvar() == v)
352      return 1;
353    return hasAlgVar (f.LC(), v);
354  }
355  if (f.inPolyDomain())
356  {
357    if (f.mvar() == v)
358      return 1;
359    if (hasVar (f.LC(), v))
360      return 1;
361    for (CFIterator i= f; i.hasTerms(); i++)
362    {
363      if (hasVar (i.coeff(), v))
364        return 1;
365    }
366  }
367  return 0;
368}
369
370int hasAlgVar (const CanonicalForm &f)
371{
372  if (f.inBaseDomain())
373    return 0;
374  if (f.inCoeffDomain())
375  {
376    if (f.level() != 0)
377      return 1;
378    return hasAlgVar(f.LC());
379  }
380  if (f.inPolyDomain())
381  {
382    if (hasAlgVar(f.LC()))
383      return 1;
384    for (CFIterator i= f; i.hasTerms(); i++)
385    {
386      if (hasAlgVar (i.coeff()))
387        return 1;
388    }
389  }
390  return 0;
391}
392
393/// pseudo division of f and g wrt. x s.t. multiplier*f=q*g+r
394void
395psqr (const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q,
396      CanonicalForm & r, CanonicalForm& multiplier, const Variable& x)
397{
398    ASSERT( x.level() > 0, "type error: polynomial variable expected" );
399    ASSERT( ! g.isZero(), "math error: division by zero" );
400
401    // swap variables such that x's level is larger or equal
402    // than both f's and g's levels.
403    Variable X;
404    if (f.level() > g.level())
405      X= f.mvar();
406    else
407      X= g.mvar();
408    if (X.level() < x.level())
409      X= x;
410    CanonicalForm F= swapvar (f, x, X);
411    CanonicalForm G= swapvar (g, x, X);
412
413    // now, we have to calculate the pseudo remainder of F and G
414    // w.r.t. X
415    int fDegree= degree (F, X);
416    int gDegree= degree (G, X);
417    if (fDegree < 0 || fDegree < gDegree)
418    {
419      q= 0;
420      r= f;
421    }
422    else
423    {
424      CanonicalForm LCG= LC (G, X);
425      multiplier= power (LCG, fDegree - gDegree + 1);
426      divrem (multiplier*F, G, q, r);
427      q= swapvar (q, x, X);
428      r= swapvar (r, x, X);
429    }
430}
431
432CanonicalForm
433Sprem (const CanonicalForm &f, const CanonicalForm &g, CanonicalForm & m,
434       CanonicalForm & q )
435{
436  CanonicalForm ff, gg, l, test, retvalue;
437  int df, dg,n;
438  bool reord;
439  Variable vf, vg, v;
440
441  if ((vf = f.mvar()) < (vg = g.mvar()))
442  {
443    m= 0;
444    q= 0;
445    return f;
446  }
447  else
448  {
449    if ( vf == vg )
450    {
451      ff= f;
452      gg= g;
453      reord= false;
454      v= vg; // == x
455    }
456    else
457    {
458      v= Variable (f.level() + 1);
459      ff= swapvar (f, vg, v); // == r
460      gg= swapvar (g, vg, v); // == v
461      reord=true;
462    }
463    dg= degree (gg, v); // == dv
464    df= degree (ff, v); // == dr
465    if (dg <= df)
466    {
467      l= LC (gg);
468      gg= gg - LC(gg)*power(v,dg);
469    }
470    else
471      l = 1;
472    n= 0;
473    while ((dg <= df) && (!ff.isZero()))
474    {
475      test= gg*LC (ff)*power (v, df - dg);
476      if (df == 0)
477        ff= 0;
478      else
479        ff= ff - LC(ff)*power(v,df);
480      ff= l*ff - test;
481      df= degree (ff, v);
482      n++;
483    }
484
485    if (reord)
486      retvalue= swapvar (ff, vg, v);
487    else
488      retvalue= ff;
489
490    m= power (l, n);
491    if (fdivides (g, m*f - retvalue))
492      q= (m*f - retvalue)/g;
493    else
494      q= 0;
495    return retvalue;
496  }
497}
498
499CanonicalForm
500divide (const CanonicalForm & ff, const CanonicalForm & f, const CFList & as)
501{
502  CanonicalForm r, m, q;
503
504  if (f.inCoeffDomain())
505  {
506    bool isRat= isOn(SW_RATIONAL);
507    if (getCharacteristic() == 0)
508      On(SW_RATIONAL);
509    q= ff/f;
510    if (!isRat && getCharacteristic() == 0)
511      Off(SW_RATIONAL);
512  }
513  else
514    r= Sprem (ff, f, m, q);
515
516  r= Prem (q, as);
517  return r;
518}
519
520// check if polynomials in Astar define a separable extension
521bool
522isInseparable (const CFList & Astar)
523{
524  CanonicalForm elem;
525
526  if (Astar.length() == 0)
527    return false;
528  for (CFListIterator i= Astar; i.hasItem(); i++)
529  {
530    elem= i.getItem();
531    if (elem.deriv().isZero())
532      return true;
533  }
534  return false;
535}
536
537// calculate big enough extension for finite fields
538// Idea: first calculate k, such that q^k > S (->thesis)
539// Second, search k with gcd(k,m_i)=1, where m_i is the degree of the i'th
540// minimal polynomial. Then the minpoly f_i remains irrd. over q^k and we
541// have enough elements to plug in.
542int
543getDegOfExt (IntList & degreelist, int n)
544{
545  int charac= getCharacteristic();
546  setCharacteristic(0); // need it for k !
547  int k= 1, m= 1, length= degreelist.length();
548  IntListIterator i;
549
550  for (i= degreelist; i.hasItem(); i++)
551     m= m*i.getItem();
552  int q= charac;
553  while (q <= ((n*m)*(n*m)/2))
554  {
555    k= k+1;
556    q= q*charac;
557  }
558  int l= 0;
559  do
560  {
561    for (i= degreelist; i.hasItem(); i++)
562    {
563      l= l + 1;
564      if (igcd (k, i.getItem()) == 1)
565      {
566        if (l == length)
567        {
568          setCharacteristic (charac);
569          return k;
570        }
571      }
572      else
573        break;
574    }
575    k= k + 1;
576    l= 0;
577  }
578  while (1);
579}
580
581CanonicalForm
582QuasiInverse (const CanonicalForm& f, const CanonicalForm& g,
583              const Variable& x)
584{
585  CanonicalForm pi, pi1, q, t0, t1, Hi, bi, pi2;
586  bool isRat= isOn (SW_RATIONAL);
587  pi= f;
588  pi1= g;
589  if (isRat)
590  {
591    pi *= bCommonDen (pi);
592    pi1 *= bCommonDen (pi1);
593  }
594  CanonicalForm m,tmp;
595  if (isRat && getCharacteristic() == 0)
596    Off (SW_RATIONAL);
597
598  pi= pi/content (pi,x);
599  pi1= pi1/content (pi1,x);
600
601  t0= 0;
602  t1= 1;
603  bi= 1;
604
605  int delta= degree (f, x) - degree (g, x);
606  Hi= power (LC (pi1, x), delta);
607  if ( (delta+1) % 2 )
608      bi = 1;
609  else
610      bi = -1;
611
612  while (degree (pi1,x) > 0)
613  {
614    psqr (pi, pi1, q, pi2, m, x);
615    pi2 /= bi;
616
617    tmp= t1;
618    t1= t0*m - t1*q;
619    t0= tmp;
620    t1 /= bi;
621    pi= pi1;
622    pi1= pi2;
623    if (degree (pi1, x) > 0)
624    {
625      delta= degree (pi, x) - degree (pi1, x);
626      if ((delta + 1) % 2)
627        bi= LC (pi, x)*power (Hi, delta);
628      else
629        bi= -LC (pi, x)*power (Hi, delta);
630      Hi= power (LC (pi1, x), delta)/power (Hi, delta - 1);
631    }
632  }
633  t1 /= gcd (pi1, t1);
634  if (isRat && getCharacteristic() == 0)
635    On (SW_RATIONAL);
636  return t1;
637}
638
639CanonicalForm
640evaluate (const CanonicalForm& f, const CanonicalForm& g,
641          const CanonicalForm& h, const CanonicalForm& powH)
642{
643  if (f.inCoeffDomain())
644    return f;
645  CFIterator i= f;
646  int lastExp = i.exp();
647  CanonicalForm result = i.coeff()*powH;
648  i++;
649  while (i.hasTerms())
650  {
651    int i_exp= i.exp();
652    if ((lastExp - i_exp) == 1)
653    {
654      result *= g;
655      result /= h;
656    }
657    else
658    {
659      result *= power (g, lastExp - i_exp);
660      result /= power (h, lastExp - i_exp);
661    }
662    result += i.coeff()*powH;
663    lastExp = i_exp;
664    i++;
665  }
666  if (lastExp != 0)
667  {
668    result *= power (g, lastExp);
669    result /= power (h, lastExp);
670  }
671  return result;
672}
673
674
675/// evaluate f at g/h at v such that powH*f is integral i.e. powH is assumed to be h^degree(f,v)
676CanonicalForm
677evaluate (const CanonicalForm& f, const CanonicalForm& g,
678          const CanonicalForm& h, const CanonicalForm& powH,
679          const Variable& v)
680{
681  if (f.inCoeffDomain())
682  {
683    return f*powH;
684  }
685
686  Variable x = f.mvar();
687  if ( v > x )
688    return f*powH;
689  else  if ( v == x )
690    return evaluate (f, g, h, powH);
691
692  // v is less than main variable of f
693  CanonicalForm result= 0;
694  for (CFIterator i= f; i.hasTerms(); i++)
695    result += evaluate (i.coeff(), g, h, powH, v)*power (x, i.exp());
696  return result;
697}
698
699
Note: See TracBrowser for help on using the repository browser.