source: git/factory/facAlgFuncUtil.cc @ b17fa5

spielwiese
Last change on this file since b17fa5 was b17fa5, checked in by Martin Lee <martinlee84@…>, 10 years ago
chg: format
  • Property mode set to 100644
File size: 15.0 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 "facAlgFuncUtil.h"
23#include "cfCharSetsUtil.h"
24#include "cf_random.h"
25#include "cf_irred.h"
26#include "cf_algorithm.h"
27#include "cf_util.h"
28#include "cf_iter.h"
29
30CFFList
31append (const CFFList & Inputlist, const CFFactor & TheFactor)
32{
33  CFFList Outputlist;
34  CFFactor copy;
35  CFFListIterator i;
36  int exp=0;
37
38  for (i= Inputlist; i.hasItem() ; i++)
39  {
40    copy= i.getItem();
41    if (copy.factor() == TheFactor.factor())
42      exp += copy.exp();
43    else
44      Outputlist.append(copy);
45  }
46  Outputlist.append (CFFactor (TheFactor.factor(), exp + TheFactor.exp()));
47  return Outputlist;
48}
49
50CFFList
51merge (const CFFList & Inputlist1, const CFFList & Inputlist2)
52{
53  CFFList Outputlist;
54  CFFListIterator i;
55
56  for (i= Inputlist1; i.hasItem(); i++)
57    Outputlist= append (Outputlist, i.getItem());
58  for (i= Inputlist2; i.hasItem() ; i++)
59    Outputlist= append (Outputlist, i.getItem());
60
61  return Outputlist;
62}
63
64Varlist
65varsInAs (const Varlist & uord, const CFList & Astar)
66{
67  Varlist output;
68  CanonicalForm elem;
69  Variable x;
70
71  for (VarlistIterator i= uord; i.hasItem(); i++)
72  {
73    x= i.getItem();
74    for (CFListIterator j= Astar; j.hasItem(); j++ )
75    {
76      elem= j.getItem();
77      if (degree (elem, x) > 0) // x actually occures in Astar
78      {
79        output.append (x);
80        break;
81      }
82    }
83  }
84  return output;
85}
86
87///////////////////////////////////////////////////////////////
88// generate a minpoly of degree degree_of_Extension in the   //
89// field getCharacteristik()^Extension.                      //
90///////////////////////////////////////////////////////////////
91CanonicalForm
92generateMipo (int degOfExt)
93{
94  FFRandom gen;
95  return find_irreducible (degOfExt, gen, Variable (1));
96}
97
98////////////////////////////////////////////////////////////////////////
99// This implements the algorithm of Trager for factorization of
100// (multivariate) polynomials over algebraic extensions and so called
101// function field extensions.
102////////////////////////////////////////////////////////////////////////
103
104// // missing class: IntGenerator:
105bool IntGenerator::hasItems() const
106{
107    return 1;
108}
109
110CanonicalForm IntGenerator::item() const
111//int IntGenerator::item() const
112{
113  //return current; //CanonicalForm( current );
114  return mapinto (CanonicalForm (current));
115}
116
117void IntGenerator::next()
118{
119    current++;
120}
121
122CanonicalForm alg_lc (const CanonicalForm & f)
123{
124  if (f.level()>0)
125  {
126    return alg_lc(f.LC());
127  }
128
129  return f;
130}
131
132CanonicalForm alg_LC (const CanonicalForm& f, int lev)
133{
134  CanonicalForm result= f;
135  while (result.level() > lev)
136    result= LC (result);
137  return result;
138}
139
140
141CanonicalForm
142subst (const CanonicalForm& f, const CFList& a, const CFList& b,
143       const CanonicalForm& Rstar, bool isFunctionField)
144{
145  if (isFunctionField)
146    ASSERT (2*a.length() == b.length(), "wrong length of lists");
147  else
148    ASSERT (a.length() == b.length(), "lists of equal length expected");
149  CFListIterator j= b;
150  CanonicalForm result= f, tmp, powj;
151  for (CFListIterator i= a; i.hasItem() && j.hasItem(); i++, j++)
152  {
153    if (!isFunctionField)
154      result= result (j.getItem(), i.getItem().mvar());
155    else
156    {
157      tmp= j.getItem();
158      j++;
159      powj= power (j.getItem(), degree (result, i.getItem().mvar()));
160      result= evaluate (result, tmp, j.getItem(), powj, i.getItem().mvar());
161
162      if (fdivides (powj, result, tmp))
163        result= tmp;
164
165      result /= vcontent (result, Variable (i.getItem().level() + 1));
166    }
167  }
168  result= reduce (result, Rstar);
169  result /= vcontent (result, Variable (Rstar.level() + 1));
170  return result;
171}
172
173CanonicalForm
174backSubst (const CanonicalForm& F, const CFList& a, const CFList& b)
175{
176  ASSERT (a.length() == b.length() - 1, "wrong length of lists in backSubst");
177  CanonicalForm result= F;
178  Variable tmp;
179  CFList tmp2= b;
180  tmp= tmp2.getLast().mvar();
181  tmp2.removeLast();
182  for (CFListIterator iter= a; iter.hasItem(); iter++)
183  {
184    result= result (tmp+iter.getItem()*tmp2.getLast().mvar(), tmp);
185    tmp= tmp2.getLast().mvar();
186    tmp2.removeLast();
187  }
188  return result;
189}
190
191void deflateDegree (const CanonicalForm & F, int & pExp, int n)
192{
193  if (n == 0 || n > F.level())
194  {
195    pExp= -1;
196    return;
197  }
198  if (F.level() == n)
199  {
200    ASSERT (F.deriv().isZero(), "derivative of F is not zero");
201    int termCount=0;
202    CFIterator i= F;
203    for (; i.hasTerms(); i++)
204    {
205      if (i.exp() != 0)
206        termCount++;
207    }
208
209    int j= 1;
210    i= F;
211    for (;j < termCount; j++, i++)
212      ;
213
214    int exp= i.exp();
215    int count= 0;
216    int p= getCharacteristic();
217    while ((exp >= p) && (exp != 0) && (exp % p == 0))
218    {
219      exp /= p;
220      count++;
221    }
222    pExp= count;
223  }
224  else
225  {
226    CFIterator i= F;
227    deflateDegree (i.coeff(), pExp, n);
228    i++;
229    int tmp= pExp;
230    for (; i.hasTerms(); i++)
231    {
232      deflateDegree (i.coeff(), pExp, n);
233      if (tmp == -1)
234        tmp= pExp;
235      else if (tmp != -1 && pExp != -1)
236        pExp= (pExp < tmp) ? pExp : tmp;
237      else
238        pExp= tmp;
239    }
240  }
241}
242
243CanonicalForm deflatePoly (const CanonicalForm & F, int exp)
244{
245  if (exp == 0)
246    return F;
247  int p= getCharacteristic();
248  int pToExp= ipower (p, exp);
249  Variable x=F.mvar();
250  CanonicalForm result= 0;
251  for (CFIterator i= F; i.hasTerms(); i++)
252    result += i.coeff()*power (x, i.exp()/pToExp);
253  return result;
254}
255
256CanonicalForm deflatePoly (const CanonicalForm & F, int exps, int n)
257{
258  if (n == 0 || exps <= 0 || F.level() < n)
259    return F;
260  if (F.level() == n)
261    return deflatePoly (F, exps);
262  else
263  {
264    CanonicalForm result= 0;
265    for (CFIterator i= F; i.hasTerms(); i++)
266      result += deflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
267    return result;
268  }
269}
270
271CanonicalForm inflatePoly (const CanonicalForm & F, int exp)
272{
273  if (exp == 0)
274    return F;
275  int p= getCharacteristic();
276  int pToExp= ipower (p, exp);
277  Variable x=F.mvar();
278  CanonicalForm result= 0;
279  for (CFIterator i= F; i.hasTerms(); i++)
280    result += i.coeff()*power (x, i.exp()*pToExp);
281  return result;
282}
283
284CanonicalForm inflatePoly (const CanonicalForm & F, int exps, int n)
285{
286  if (n == 0 || exps <= 0 || F.level() < n)
287    return F;
288  if (F.level() == n)
289    return inflatePoly (F, exps);
290  else
291  {
292    CanonicalForm result= 0;
293    for (CFIterator i= F; i.hasTerms(); i++)
294      result += inflatePoly (i.coeff(), exps, n)*power(F.mvar(), i.exp());
295    return result;
296  }
297}
298
299void
300multiplicity (CFFList& factors, const CanonicalForm& F, const CFList& as)
301{
302  CanonicalForm G= F;
303  Variable x= F.mvar();
304  CanonicalForm q, r;
305  int count= -1;
306  for (CFFListIterator iter=factors; iter.hasItem(); iter++)
307  {
308    count= -1;
309    if (iter.getItem().factor().inCoeffDomain())
310      continue;
311    while (1)
312    {
313      psqr (G, iter.getItem().factor(), q, r, x);
314
315      q= Prem (q, as);
316      r= Prem (r, as);
317      if (!r.isZero())
318        break;
319      count++;
320      G= q;
321    }
322    iter.getItem()= CFFactor (iter.getItem().factor(),
323                              iter.getItem().exp() + count);
324  }
325}
326
327int hasAlgVar (const CanonicalForm &f, const Variable &v)
328{
329  if (f.inBaseDomain())
330    return 0;
331  if (f.inCoeffDomain())
332  {
333    if (f.mvar() == v)
334      return 1;
335    return hasAlgVar (f.LC(), v);
336  }
337  if (f.inPolyDomain())
338  {
339    if (hasAlgVar(f.LC(), v))
340      return 1;
341    for (CFIterator i= f; i.hasTerms(); i++)
342    {
343      if (hasAlgVar (i.coeff(), v))
344        return 1;
345    }
346  }
347  return 0;
348}
349
350int hasVar (const CanonicalForm &f, const Variable &v)
351{
352  if (f.inBaseDomain())
353    return 0;
354  if (f.inCoeffDomain())
355  {
356    if (f.mvar() == v)
357      return 1;
358    return hasAlgVar (f.LC(), v);
359  }
360  if (f.inPolyDomain())
361  {
362    if (f.mvar() == v)
363      return 1;
364    if (hasVar (f.LC(), v))
365      return 1;
366    for (CFIterator i= f; i.hasTerms(); i++)
367    {
368      if (hasVar (i.coeff(), v))
369        return 1;
370    }
371  }
372  return 0;
373}
374
375int hasAlgVar (const CanonicalForm &f)
376{
377  if (f.inBaseDomain())
378    return 0;
379  if (f.inCoeffDomain())
380  {
381    if (f.level() != 0)
382      return 1;
383    return hasAlgVar(f.LC());
384  }
385  if (f.inPolyDomain())
386  {
387    if (hasAlgVar(f.LC()))
388      return 1;
389    for (CFIterator i= f; i.hasTerms(); i++)
390    {
391      if (hasAlgVar (i.coeff()))
392        return 1;
393    }
394  }
395  return 0;
396}
397
398/// pseudo division of f and g wrt. x s.t. multiplier*f=q*g+r
399void
400psqr (const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, 
401      CanonicalForm & r, CanonicalForm& multiplier, const Variable& x)
402{
403    ASSERT( x.level() > 0, "type error: polynomial variable expected" );
404    ASSERT( ! g.isZero(), "math error: division by zero" );
405
406    // swap variables such that x's level is larger or equal
407    // than both f's and g's levels.
408    Variable X;
409    if (f.level() > g.level())
410      X= f.mvar();
411    else
412      X= g.mvar();
413    if (X.level() < x.level())
414      X= x;
415    CanonicalForm F= swapvar (f, x, X);
416    CanonicalForm G= swapvar (g, x, X);
417
418    // now, we have to calculate the pseudo remainder of F and G
419    // w.r.t. X
420    int fDegree= degree (F, X);
421    int gDegree= degree (G, X);
422    if (fDegree < 0 || fDegree < gDegree)
423    {
424      q= 0;
425      r= f;
426    }
427    else
428    {
429      CanonicalForm LCG= LC (G, X);
430      multiplier= power (LCG, fDegree - gDegree + 1);
431      divrem (multiplier*F, G, q, r);
432      q= swapvar (q, x, X);
433      r= swapvar (r, x, X);
434    }
435}
436
437CanonicalForm
438Sprem (const CanonicalForm &f, const CanonicalForm &g, CanonicalForm & m,
439       CanonicalForm & q )
440{
441  CanonicalForm ff, gg, l, test, retvalue;
442  int df, dg,n;
443  bool reord;
444  Variable vf, vg, v;
445
446  if ((vf = f.mvar()) < (vg = g.mvar()))
447  {
448    m= 0;
449    q= 0;
450    return f;
451  }
452  else
453  {
454    if ( vf == vg )
455    {
456      ff= f;
457      gg= g;
458      reord= false;
459      v= vg; // == x
460    }
461    else
462    {
463      v= Variable (f.level() + 1);
464      ff= swapvar (f, vg, v); // == r
465      gg= swapvar (g, vg, v); // == v
466      reord=true;
467    }
468    dg= degree (gg, v); // == dv
469    df= degree (ff, v); // == dr
470    if (dg <= df)
471    {
472      l= LC (gg);
473      gg= gg - LC(gg)*power(v,dg);
474    }
475    else
476      l = 1;
477    n= 0;
478    while ((dg <= df) && (!ff.isZero()))
479    {
480      test= gg*LC (ff)*power (v, df - dg);
481      if (df == 0)
482        ff= 0;
483      else
484        ff= ff - LC(ff)*power(v,df);
485      ff= l*ff - test;
486      df= degree (ff, v);
487      n++;
488    }
489
490    if (reord)
491      retvalue= swapvar (ff, vg, v);
492    else
493      retvalue= ff;
494
495    m= power (l, n);
496    if (fdivides (g, m*f - retvalue))
497      q= (m*f - retvalue)/g;
498    else
499      q= 0;
500    return retvalue;
501  }
502}
503
504CanonicalForm
505divide (const CanonicalForm & ff, const CanonicalForm & f, const CFList & as)
506{
507  CanonicalForm r, m, q;
508
509  if (f.inCoeffDomain())
510  {
511    bool isRat= isOn(SW_RATIONAL);
512    if (getCharacteristic() == 0)
513      On(SW_RATIONAL);
514    q= ff/f;
515    if (!isRat && getCharacteristic() == 0)
516      Off(SW_RATIONAL);
517  }
518  else
519    r= Sprem (ff, f, m, q);
520
521  r= Prem (q, as);
522  return r;
523}
524
525// Look if Minimalpolynomials in Astar define seperable Extensions
526// Must be a power of p: i.e. y^{p^e}-x
527bool
528isInseparable(const CFList & Astar)
529{
530  CanonicalForm elem;
531
532  if (Astar.length() == 0)
533    return false;
534  for (CFListIterator i= Astar; i.hasItem(); i++)
535  {
536    elem= i.getItem();
537    if (elem.deriv().isZero())
538      return true;
539  }
540  return false;
541}
542
543// calculate big enough extension for finite fields
544// Idea: first calculate k, such that q^k > S (->thesis, -> getextension)
545// Second, search k with gcd(k,m_i)=1, where m_i is the degree of the i'th
546// minimal polynomial. Then the minpoly f_i remains irrd. over q^k and we
547// have enough elements to plug in.
548int
549getDegOfExt (IntList & degreelist, int n)
550{
551  int charac= getCharacteristic();
552  setCharacteristic(0); // need it for k !
553  int k= 1, m= 1, length= degreelist.length();
554  IntListIterator i;
555
556  for (i= degreelist; i.hasItem(); i++)
557     m= m*i.getItem();
558  int q= charac;
559  while (q <= ((n*m)*(n*m)/2))
560  {
561    k= k+1;
562    q= q*charac;
563  }
564  int l= 0;
565  do
566  {
567    for (i= degreelist; i.hasItem(); i++)
568    {
569      l= l + 1;
570      if (igcd (k, i.getItem()) == 1)
571      {
572        if (l == length)
573        {
574          setCharacteristic (charac);
575          return k;
576        }
577      }
578      else
579        break;
580    }
581    k= k + 1;
582    l= 0;
583  }
584  while (1);
585}
586
587CanonicalForm
588QuasiInverse (const CanonicalForm& f, const CanonicalForm& g,
589              const Variable& x)
590{
591  CanonicalForm pi, pi1, q, t0, t1, Hi, bi, pi2;
592  bool isRat= isOn (SW_RATIONAL);
593  CanonicalForm m,tmp;
594  if (isRat && getCharacteristic() == 0)
595    Off (SW_RATIONAL);
596  pi= f/content (f,x);
597  pi1= g/content (g,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    Off (SW_RATIONAL);
634  return t1;
635}
636
637CanonicalForm
638evaluate (const CanonicalForm& f, const CanonicalForm& g, const CanonicalForm& h,
639          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.