source: git/libfac/factor/Truefactor.cc @ 3e55bc

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