source: git/libfac/factor/Truefactor.cc @ b87513c

spielwiese
Last change on this file since b87513c was b87513c, checked in by Hans Schönemann <hannes@…>, 23 years ago
* hannes: code cleanup git-svn-id: file:///usr/local/Singular/svn/trunk@5563 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.3 KB
Line 
1/* Copyright 1996 Michael Messollen. All rights reserved. */
2///////////////////////////////////////////////////////////////////////////////
3// emacs edit mode for this file is -*- C++ -*-
4//static char * rcsid = "@(#) $Id: Truefactor.cc,v 1.7 2001-08-06 08:32:54 Singular Exp $";
5///////////////////////////////////////////////////////////////////////////////
6// Factory - Includes
7#include <factory.h>
8// Factor - Includes
9#include "tmpl_inst.h"
10#include "helpstuff.h"
11// some CC's need this:
12#include "Truefactor.h"
13
14#ifdef SINGULAR
15#  define HAVE_SINGULAR
16   extern "C" { void WerrorS(char *); }
17#endif
18
19#ifdef TRUEFACTORDEBUG
20#  define DEBUGOUTPUT
21#else
22#  undef DEBUGOUTPUT
23#endif
24
25#include "debug.h"
26#include "timing.h"
27
28int hasAlgVar(const CanonicalForm &f, const Variable &v)
29{
30  if (f.inBaseDomain()) return 0;
31  if (f.inCoeffDomain())
32  {
33    if (f.mvar()==v) return 1;
34    return hasAlgVar(f.LC(),v);
35  }
36  if (f.inPolyDomain())
37  {
38    if (hasAlgVar(f.LC(),v)) return 1;
39    for( CFIterator i=f; i.hasTerms(); i++)
40    {
41      if (hasAlgVar(i.coeff(),v)) return 1;
42    }
43  }
44  return 0;
45}
46
47int hasVar(const CanonicalForm &f, const Variable &v)
48{
49  if (f.inBaseDomain()) return 0;
50  if (f.inCoeffDomain())
51  {
52    if (f.mvar()==v) return 1;
53    return hasAlgVar(f.LC(),v);
54  }
55  if (f.inPolyDomain())
56  {
57    if (f.mvar()==v) return 1;
58    if (hasVar(f.LC(),v)) return 1;
59    for( CFIterator i=f; i.hasTerms(); i++)
60    {
61      if (hasVar(i.coeff(),v)) return 1;
62    }
63  }
64  return 0;
65}
66
67int hasAlgVar(const CanonicalForm &f)
68{
69  if (f.inBaseDomain()) return 0;
70  if (f.inCoeffDomain())
71  {
72    if (f.level()!=0)
73    {
74      //cout << "hasAlgVar:" << f.mvar() <<endl;
75      return 1;
76    }
77    return hasAlgVar(f.LC());
78  }
79  if (f.inPolyDomain())
80  {
81    if (hasAlgVar(f.LC())) return 1;
82    for( CFIterator i=f; i.hasTerms(); i++)
83    {
84      if (hasAlgVar(i.coeff())) return 1;
85    }
86  }
87  return 0;
88}
89
90///////////////////////////////////////////////////////////////
91// generate all different k-subsets of the set with n        //
92// elements and return them in returnlist.                   //
93///////////////////////////////////////////////////////////////
94static void
95combinat( int k, int n, List<IntList> & returnlist ){
96  ListIntList ListofLists;
97  IntList intermediate,intermediate2;
98  int value,j;
99
100  if ( k == 1 ){                     // k=1
101    for ( j=1; j<=n; j++)
102      returnlist.append( IntList(j) );
103  }
104  else{                              // k-1 --> k
105    combinat(k-1,n,returnlist);  // generate (k-1,n)
106    for ( ListIntListIterator l=returnlist; l.hasItem(); l++ ){
107      intermediate = l.getItem();
108      value = intermediate.getLast();
109      if ( value != n )
110        for ( j=value+1; j<=n; j++ ){
111          intermediate2 = intermediate; intermediate2.append(j);
112          ListofLists.append( intermediate2 );
113        }
114    }
115    returnlist = ListofLists;
116  }
117}
118
119///////////////////////////////////////////////////////////////
120// Return the CanonicalForm number nr in  Factorlist.        //
121///////////////////////////////////////////////////////////////
122static CanonicalForm
123getItemNr(int nr, const CFFList & Factorlist ){
124  ListIterator<CFFactor> i=Factorlist;
125  int Nr=nr;
126
127  for ( Nr=1; Nr<nr; Nr++ ) i++;
128  return i.getItem().factor();
129}
130
131///////////////////////////////////////////////////////////////
132// Generate all sets of m factors out of LiftedFactors list. //
133///////////////////////////////////////////////////////////////
134static CFFList
135combine( int m, const CFFList & LiftedFactors ){
136  CFFList result;
137  ListIntList CombinatList;
138  CanonicalForm intermediate;
139
140  combinat(m, LiftedFactors.length(), CombinatList);
141  for ( ListIntListIterator j=CombinatList ; j.hasItem(); j++ ){
142    intermediate=1;
143    for ( IntListIterator k=j.getItem(); k.hasItem(); k++ )
144      intermediate *= getItemNr(k.getItem(), LiftedFactors);
145    if (!hasAlgVar(intermediate))
146    result.append(CFFactor(intermediate,1));
147  }
148  return result;
149}
150
151///////////////////////////////////////////////////////////////
152// Remove element elem from the list L.                      //
153///////////////////////////////////////////////////////////////
154static CFFList
155Remove_from_List( const CFFList & L, const CanonicalForm & elem ){
156  CFFList Returnlist;
157
158  DEBOUTLN(cout, "Remove_from_List called with L= ",L);
159  DEBOUTLN(cout, "                     and  elem= ",elem);
160  for ( ListIterator<CFFactor> i = L ; i.hasItem(); i++)
161    if ( i.getItem().factor() != elem )
162      Returnlist.append( i.getItem() );
163
164  return Returnlist;
165}
166
167///////////////////////////////////////////////////////////////
168// Here we solve:          G= F mod ( P, S^h )               //
169///////////////////////////////////////////////////////////////
170static CanonicalForm
171Multmod_power( const CanonicalForm & F, const SFormList & Substituionlist, int h, int levelF){
172  CanonicalForm G;
173
174  G= change_poly(F, Substituionlist, 0);
175  G= mod_power(G, h, levelF);
176  G= change_poly(G, Substituionlist, 1);
177
178  return G;
179}
180
181///////////////////////////////////////////////////////////////
182// Determine the right degree for the list of combinations   //
183// of factors, i.e. delete any element from list CombL which //
184// degree in the main variable levelU exceeeds degU.         //
185///////////////////////////////////////////////////////////////
186static CFFList
187Rightdegree( const CFFList & CombL, int degU, int levelU ){
188  CFFList Returnlist;
189  CFFactor factor;
190
191  for ( ListIterator<CFFactor> i= CombL; i.hasItem(); i++ ){
192    factor= i.getItem();
193    if ( degree(factor.factor(), levelU) <= degU )
194      Returnlist.append(factor);
195  }
196
197  return Returnlist;
198}
199
200///////////////////////////////////////////////////////////////
201// We have properly lifted all the specialized factors. See  //
202// which one works.                                          //
203// We use the (modified) algorithm TRUEFACTORS given by      //
204// Paul S. Wang and Linda Preiss Rothschild:                 //
205// Factoring Multivariate Polynomials Over the Integers      //
206// Math. Comp. V29 Nr131 (July 1975) p. 935-950              //
207///////////////////////////////////////////////////////////////
208CFFList
209Truefactors( const CanonicalForm Ua, int levelU, const SFormList & SubstitutionList, const CFFList & PiList){
210  CanonicalForm U=Ua,a,b,Y;
211  CFFactor factor;
212  CFFList L,FAC,E_all;
213  int c,r = PiList.length(),degU, onemore,M, h = subvardegree(Ua,levelU) + 1;
214  ListIterator<CFFactor> i;
215
216  //cout << "SubstitutionList="<< SubstitutionList<<endl;
217// step 1: simply test the generated factors alone
218  for ( i= PiList; i.hasItem();i++){
219    factor = i.getItem();
220    //CanonicalForm test_f=change_poly(factor.factor(),SubstitutionList,0);
221    CanonicalForm test_f=factor.factor();
222    //cout <<"f:" << factor.factor() << " -> test_f:"<<test_f <<endl;
223    //cout << "           1:" << change_poly(factor.factor(),SubstitutionList,1) <<endl;
224    c= mydivremt(U,test_f,a,b);
225    if (  c  && b == U.genZero() && !hasAlgVar(test_f))
226    // factor.getFactor() divides U
227    {
228      //cout << " teilt:" << test_f <<endl;
229      U= a;
230      FAC.append(factor);
231    }
232    else{
233      //cout << " teilt nicht:" << test_f <<endl;
234      L.append(factor);
235    }
236  }
237  DEBOUTLN(cout,"Truefactors: (step1) L  = ", L);
238  DEBOUTLN(cout,"                     FAC= ", FAC);
239
240// step 2: Do we have to check combinations?
241  degU = L.length();
242  if ( degU == 0 ) // No elements: Return
243    return FAC;
244  else
245    if ( degU < 4 ){ // Less then four elements: no combinations possible
246      FAC.append( CFFactor(U,1) );
247      return FAC;
248    }
249    else {
250      M = 1; r = r - FAC.length(); degU = degree(U, levelU)/2;
251    }
252
253  DEBOUTLN(cout,"Truefactors: (step2) M   = ", M);
254  DEBOUTLN(cout,"                     r   = ", r);
255  DEBOUTLN(cout,"                     degU= ", degU);
256
257// Now do the real work!
258// Test all the combinations of possible factors.
259
260  onemore=1;
261// steps 3 to 6
262  while (1){
263    // step 3 iff onemore == 1
264    if ( onemore ) M+= 1;  else onemore = 1;
265    // step 4
266    if ( U == U.genOne() ) break; // Return FAC
267    if ( ( r == 1 ) || ( M >= ( r-1 ) ) || ( M > degU ) ) {
268      FAC.append( CFFactor(U,1) );
269      break; // Return FAC union {U}
270    }
271    // step 5
272    E_all = combine(M, L); // generate all combinations of M elements from L
273    DEBOUTLN(cout,"Truefactors: (step5) E_all= ", E_all);
274    // select combinations with the degree not to exceed degU:
275    E_all = Rightdegree( E_all, degU, levelU );
276    DEBOUTLN(cout,"Truefactors: (step5) E_all(Rightdegree)= ", E_all);
277    if ( E_all.length() == 0 ){
278      FAC.append( CFFactor(U,1) );
279      break; // Return FAC union {U}
280    }
281    for ( i=E_all; i.hasItem(); i++){
282      factor = i.getItem();
283      Y = Multmod_power( factor.factor(), SubstitutionList, h, levelU);
284      DEBOUTLN(cout, "Truefactors: (step6) Testing Y  = ", Y);
285      c = mydivremt(U,Y,a,b);
286      //      if (  c  && b == U.genZero()) { // Y divides U
287      if ( c && b.isZero() ){
288        DEBOUT(cout,"Truefactors: (step6): ",Y );
289        DEBOUTLN(cout, "  divides  ",U);
290        U = a;
291        FAC.append(Y); // Y is a real factor
292        onemore = 0;
293        degU = degree(U, levelU)/2; // new degU
294        // L = L \ {factor}
295        // Hier ist noch etwas faul; wir muessen (f=prod(f_i)) die f_i
296        // entfernen und nicht f!
297        L = Remove_from_List( L, factor.factor() );
298        r -= 1;
299        // delete from L any element with degree greater than degU
300        L = Rightdegree( L, degU, levelU );
301      }
302    }
303  }
304
305  return FAC;
306}
307
308///////////////////////////////////////////////////////////////
309// Check if poly f is in Fp (returns true) or in Fp(a)       //
310///////////////////////////////////////////////////////////////
311static bool
312is_in_Fp( const CanonicalForm & f ){
313  if ( f.inCoeffDomain() )
314    return f.inBaseDomain() ;
315  else {
316    CFIterator i=f;
317    bool ok=true;
318    while ( ok && i.hasTerms() ){
319      ok = is_in_Fp( i.coeff() );
320      i++ ;
321    }
322    return ok;
323  }
324}
325
326///////////////////////////////////////////////////////////////
327// We have factors which possibly lie in an extension of the //
328// base field. If one of these is not over the base field,   //
329// find its norm by (the theoretically handicapped method    //
330// of) multiplying by other elements.                        //
331///////////////////////////////////////////////////////////////
332CFFList
333TakeNorms(const CFFList & PiList){
334  CFFList CopyPossibleFactors, PossibleFactors, TrueFactors;
335  CFFListIterator i;
336  CFFactor Factor;
337  CanonicalForm intermediate;
338  ListIntList CombinatList;
339  ListIntListIterator j;
340  IntListIterator k;
341
342  // First check if the factors in PiList already lie in Fp-Domain
343  for ( i=PiList; i.hasItem(); i++ ){
344    Factor = i.getItem();
345    if ( is_in_Fp( Factor.factor() ) )
346      TrueFactors.append(Factor);
347    else
348      PossibleFactors.append(Factor);
349  }
350  // Now we have to check if combinations of the remaining factors
351  // (now in PossibleFactors) do lie in Fp-Domain
352  if ( PossibleFactors.length() > 0 ){ // there are (at least two) items
353    int n=2;
354    if ( PossibleFactors.length() < n ) { // a little check
355#ifdef HAVE_SINGULAR
356      WerrorS("libfac: ERROR: TakeNorms less then two items remaining!");
357#else
358      cerr << "libfac: ERROR: TakeNorms less then two items remaining! "
359           << endl;
360#endif
361    }
362    while ( n < PossibleFactors.length() ){
363      // generate all combinations of n elements
364      combinat(n, PossibleFactors.length(), CombinatList);
365      for ( j=CombinatList ; j.hasItem(); j++ ){
366        intermediate=1;
367        for ( k=j.getItem(); k.hasItem(); k++ )
368          intermediate *= getItemNr( k.getItem(), PossibleFactors );
369        if ( is_in_Fp( intermediate ) ){
370          TrueFactors.append(intermediate); // found a true factor
371          CopyPossibleFactors=PossibleFactors; // save list
372          for ( k=j.getItem(); k.hasItem(); k++ )
373            //remove combined factors from PossibleFactors
374            PossibleFactors=Remove_from_List(PossibleFactors,
375                                getItemNr( k.getItem(), CopyPossibleFactors ));
376          n-=1; // look for the same number of combined factors:
377          break;
378        }
379        else {
380          //cout << "Schade!" << endl;
381        }
382        DEBOUT(cout, "Truefactor: Combined ", n);
383        DEBOUTLN(cout, " factors to: ", intermediate);
384      }
385      n += 1;
386    }
387  // All remaining factors in PossibleFactors multiplied
388  // should lie in Fp domain
389    if ( PossibleFactors.length() >=1 ){
390      for ( i=PossibleFactors; i.hasItem(); i++ )
391        intermediate *= i.getItem().factor();
392      // a last check:
393      if ( is_in_Fp(intermediate) ){
394        TrueFactors.append(CFFactor(intermediate,1));
395      }
396      else{
397#ifdef HAVE_SINGULAR
398        WerrorS("libfac: TakeNorms: somethings wrong with remaining factors!");
399#else
400        cerr << "libfac: TakeNorms: somethings wrong with remaining factors!"
401             << endl;
402#endif
403      }
404    }
405  }
406  return TrueFactors;
407}
408
409////////////////////////////////////////////////////////////
410/*
411$Log: not supported by cvs2svn $
412Revision 1.6  2001/06/27 13:58:06  Singular
413*hannes/GP: debug newfactoras, char_series, ...
414
415Revision 1.5  2001/06/21 14:57:06  Singular
416*hannes/GP: Factorize, newfactoras, ...
417
418Revision 1.4  1997/11/18 16:39:07  Singular
419* hannes: moved WerrorS from C++ to C
420     (Factor.cc MVMultiHensel.cc SqrFree.cc Truefactor.cc)
421
422Revision 1.3  1997/09/12 07:19:52  Singular
423* hannes/michael: libfac-0.3.0
424
425Revision 1.3  1997/04/25 22:39:11  michael
426changed cerr and cout messages for use with Singular
427Version for libfac-0.2.1
428
429*/
Note: See TracBrowser for help on using the repository browser.