source: git/libfac/factor/Truefactor.cc @ 4a81ec

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