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

fieker-DuValspielwiese
Last change on this file since 8d8fef was 8dd7cd8, checked in by Hans Schoenemann <hannes@…>, 5 years ago
opt: hasAlgVar
  • Property mode set to 100644
File size: 14.8 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.inExtension())
375  {
376    return 1;
377  }
378  if (f.inPolyDomain())
379  {
380    for (CFIterator i= f; i.hasTerms(); i++)
381    {
382      if (hasAlgVar (i.coeff()))
383        return 1;
384    }
385  }
386  return 0;
387}
388
389/// pseudo division of f and g wrt. x s.t. multiplier*f=q*g+r
390void
391psqr (const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q,
392      CanonicalForm & r, CanonicalForm& multiplier, const Variable& x)
393{
394    ASSERT( x.level() > 0, "type error: polynomial variable expected" );
395    ASSERT( ! g.isZero(), "math error: division by zero" );
396
397    // swap variables such that x's level is larger or equal
398    // than both f's and g's levels.
399    Variable X;
400    if (f.level() > g.level())
401      X= f.mvar();
402    else
403      X= g.mvar();
404    if (X.level() < x.level())
405      X= x;
406    CanonicalForm F= swapvar (f, x, X);
407    CanonicalForm G= swapvar (g, x, X);
408
409    // now, we have to calculate the pseudo remainder of F and G
410    // w.r.t. X
411    int fDegree= degree (F, X);
412    int gDegree= degree (G, X);
413    if (fDegree < 0 || fDegree < gDegree)
414    {
415      q= 0;
416      r= f;
417    }
418    else
419    {
420      CanonicalForm LCG= LC (G, X);
421      multiplier= power (LCG, fDegree - gDegree + 1);
422      divrem (multiplier*F, G, q, r);
423      q= swapvar (q, x, X);
424      r= swapvar (r, x, X);
425    }
426}
427
428CanonicalForm
429Sprem (const CanonicalForm &f, const CanonicalForm &g, CanonicalForm & m,
430       CanonicalForm & q )
431{
432  CanonicalForm ff, gg, l, test, retvalue;
433  int df, dg,n;
434  bool reord;
435  Variable vf, vg, v;
436
437  if ((vf = f.mvar()) < (vg = g.mvar()))
438  {
439    m= 0;
440    q= 0;
441    return f;
442  }
443  else
444  {
445    if ( vf == vg )
446    {
447      ff= f;
448      gg= g;
449      reord= false;
450      v= vg; // == x
451    }
452    else
453    {
454      v= Variable (f.level() + 1);
455      ff= swapvar (f, vg, v); // == r
456      gg= swapvar (g, vg, v); // == v
457      reord=true;
458    }
459    dg= degree (gg, v); // == dv
460    df= degree (ff, v); // == dr
461    if (dg <= df)
462    {
463      l= LC (gg);
464      gg= gg - LC(gg)*power(v,dg);
465    }
466    else
467      l = 1;
468    n= 0;
469    while ((dg <= df) && (!ff.isZero()))
470    {
471      test= gg*LC (ff)*power (v, df - dg);
472      if (df == 0)
473        ff= 0;
474      else
475        ff= ff - LC(ff)*power(v,df);
476      ff= l*ff - test;
477      df= degree (ff, v);
478      n++;
479    }
480
481    if (reord)
482      retvalue= swapvar (ff, vg, v);
483    else
484      retvalue= ff;
485
486    m= power (l, n);
487    if (fdivides (g, m*f - retvalue))
488      q= (m*f - retvalue)/g;
489    else
490      q= 0;
491    return retvalue;
492  }
493}
494
495CanonicalForm
496divide (const CanonicalForm & ff, const CanonicalForm & f, const CFList & as)
497{
498  CanonicalForm r, m, q;
499
500  if (f.inCoeffDomain())
501  {
502    bool isRat= isOn(SW_RATIONAL);
503    if (getCharacteristic() == 0)
504      On(SW_RATIONAL);
505    q= ff/f;
506    if (!isRat && getCharacteristic() == 0)
507      Off(SW_RATIONAL);
508  }
509  else
510    r= Sprem (ff, f, m, q);
511
512  r= Prem (q, as);
513  return r;
514}
515
516// check if polynomials in Astar define a separable extension
517bool
518isInseparable (const CFList & Astar)
519{
520  CanonicalForm elem;
521
522  if (Astar.length() == 0)
523    return false;
524  for (CFListIterator i= Astar; i.hasItem(); i++)
525  {
526    elem= i.getItem();
527    if (elem.deriv().isZero())
528      return true;
529  }
530  return false;
531}
532
533// calculate big enough extension for finite fields
534// Idea: first calculate k, such that q^k > S (->thesis)
535// Second, search k with gcd(k,m_i)=1, where m_i is the degree of the i'th
536// minimal polynomial. Then the minpoly f_i remains irrd. over q^k and we
537// have enough elements to plug in.
538int
539getDegOfExt (IntList & degreelist, int n)
540{
541  int charac= getCharacteristic();
542  setCharacteristic(0); // need it for k !
543  int k= 1, m= 1, length= degreelist.length();
544  IntListIterator i;
545
546  for (i= degreelist; i.hasItem(); i++)
547     m= m*i.getItem();
548  int q= charac;
549  while (q <= ((n*m)*(n*m)/2))
550  {
551    k= k+1;
552    q= q*charac;
553  }
554  int l= 0;
555  do
556  {
557    for (i= degreelist; i.hasItem(); i++)
558    {
559      l= l + 1;
560      if (igcd (k, i.getItem()) == 1)
561      {
562        if (l == length)
563        {
564          setCharacteristic (charac);
565          return k;
566        }
567      }
568      else
569        break;
570    }
571    k= k + 1;
572    l= 0;
573  }
574  while (1);
575}
576
577CanonicalForm
578QuasiInverse (const CanonicalForm& f, const CanonicalForm& g,
579              const Variable& x)
580{
581  CanonicalForm pi, pi1, q, t0, t1, Hi, bi, pi2;
582  bool isRat= isOn (SW_RATIONAL);
583  pi= f;
584  pi1= g;
585  if (isRat)
586  {
587    pi *= bCommonDen (pi);
588    pi1 *= bCommonDen (pi1);
589  }
590  CanonicalForm m,tmp;
591  if (isRat && getCharacteristic() == 0)
592    Off (SW_RATIONAL);
593
594  pi= pi/content (pi,x);
595  pi1= pi1/content (pi1,x);
596
597  t0= 0;
598  t1= 1;
599  bi= 1;
600
601  int delta= degree (f, x) - degree (g, x);
602  Hi= power (LC (pi1, x), delta);
603  if ( (delta+1) % 2 )
604      bi = 1;
605  else
606      bi = -1;
607
608  while (degree (pi1,x) > 0)
609  {
610    psqr (pi, pi1, q, pi2, m, x);
611    pi2 /= bi;
612
613    tmp= t1;
614    t1= t0*m - t1*q;
615    t0= tmp;
616    t1 /= bi;
617    pi= pi1;
618    pi1= pi2;
619    if (degree (pi1, x) > 0)
620    {
621      delta= degree (pi, x) - degree (pi1, x);
622      if ((delta + 1) % 2)
623        bi= LC (pi, x)*power (Hi, delta);
624      else
625        bi= -LC (pi, x)*power (Hi, delta);
626      Hi= power (LC (pi1, x), delta)/power (Hi, delta - 1);
627    }
628  }
629  t1 /= gcd (pi1, t1);
630  if (isRat && getCharacteristic() == 0)
631    On (SW_RATIONAL);
632  return t1;
633}
634
635CanonicalForm
636evaluate (const CanonicalForm& f, const CanonicalForm& g,
637          const CanonicalForm& h, const CanonicalForm& powH)
638{
639  if (f.inCoeffDomain())
640    return f;
641  CFIterator i= f;
642  int lastExp = i.exp();
643  CanonicalForm result = i.coeff()*powH;
644  i++;
645  while (i.hasTerms())
646  {
647    int i_exp= i.exp();
648    if ((lastExp - i_exp) == 1)
649    {
650      result *= g;
651      result /= h;
652    }
653    else
654    {
655      result *= power (g, lastExp - i_exp);
656      result /= power (h, lastExp - i_exp);
657    }
658    result += i.coeff()*powH;
659    lastExp = i_exp;
660    i++;
661  }
662  if (lastExp != 0)
663  {
664    result *= power (g, lastExp);
665    result /= power (h, lastExp);
666  }
667  return result;
668}
669
670
671/// evaluate f at g/h at v such that powH*f is integral i.e. powH is assumed to be h^degree(f,v)
672CanonicalForm
673evaluate (const CanonicalForm& f, const CanonicalForm& g,
674          const CanonicalForm& h, const CanonicalForm& powH,
675          const Variable& v)
676{
677  if (f.inCoeffDomain())
678  {
679    return f*powH;
680  }
681
682  Variable x = f.mvar();
683  if ( v > x )
684    return f*powH;
685  else  if ( v == x )
686    return evaluate (f, g, h, powH);
687
688  // v is less than main variable of f
689  CanonicalForm result= 0;
690  for (CFIterator i= f; i.hasTerms(); i++)
691    result += evaluate (i.coeff(), g, h, powH, v)*power (x, i.exp());
692  return result;
693}
694
695
Note: See TracBrowser for help on using the repository browser.