source: git/factory/facAlgFuncUtil.cc @ 1d01eb

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