source: git/libfac/factor/Truefactor.cc @ 6f801b

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