source: git/factory/facAlgFuncUtil.cc @ d38762

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