source: git/factory/fac_univar.cc @ 4d2aefb

fieker-DuValspielwiese
Last change on this file since 4d2aefb was 080943, checked in by Jens Schmidt <schmidt@…>, 27 years ago
o initHG(), ZFactorizeUnivariate(): calls to WARN changed to STICKYWARN. git-svn-id: file:///usr/local/Singular/svn/trunk@213 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.7 KB
Line 
1// emacs edit mode for this file is -*- C++ -*-
2// $Id: fac_univar.cc,v 1.8 1997-04-30 12:52:18 schmidt Exp $
3
4/*
5$Log: not supported by cvs2svn $
6Revision 1.7  1997/04/22 15:40:32  schmidt
7o some spurious preprocessr directives removed
8o #define MAX_FP_FAC changed to a const max_fp_fac
9o calls to hprint() changed to calls of a macro named
10  DEBOUTHPRINT()
11o initHG(): warning added because of some strange error in
12  the internals of factory.  we will wait for some example
13  to search for the error.
14o kBound(), UnivariatequadraticLift(): added cast to double
15  in the calculation of the bound.  at least one compiler
16  subjects an ambiguity at this point.
17o ZFactorizeUnivariate():
18  - spurious variable CFFList G removed
19  - sequence 'if ( D != 0 ) delete D;' changed to 'delete
20    D;'
21  - warning added because of some strange error in the
22    internals of factory.  we will wait for some example
23    to search for the error.
24o calls to macro DEBOUTLN changed to new calling syntax
25
26Revision 1.6  1997/04/08 10:33:19  schmidt
27#include <config.h> added
28
29Revision 1.5  1997/03/27 09:54:41  schmidt
30timing output changed to TIMING
31debug output rewritten
32debug output changed to DEBOUT
33
34Revision 1.4  1996/07/12 08:37:20  stobbe
35"ZFactorizeUnivariate: now handles constants of the squarefree decomposition
36"
37
38Revision 1.3  1996/06/26 13:17:03  stobbe
39"ZFactorizeUnivariate: now handles the sign of the argument right.
40"
41
42Revision 1.2  1996/06/13 10:43:49  stobbe
43"ZFactorizeUnivariate: fix to last bug fix (no assignment)
44"
45
46Revision 1.1  1996/06/13 10:34:04  stobbe
47"ZFactorizeUnivariate: do not use Berlekamp-Algorithm since there is a
48                      bug in the Factory-Implementation of Berlekamp
49"
50
51Revision 1.0  1996/05/17 10:59:45  stobbe
52Initial revision
53
54*/
55
56
57#include <config.h>
58
59#include <math.h>
60
61#include "assert.h"
62#include "debug.h"
63#include "timing.h"
64
65#include "cf_defs.h"
66#include "fac_util.h"
67#include "fac_univar.h"
68#include "fac_cantzass.h"
69#include "fac_berlekamp.h"
70#include "cf_iter.h"
71#include "cf_primes.h"
72#include "fac_sqrfree.h"
73
74TIMING_DEFINE_PRINT(fac_choosePrimes);
75TIMING_DEFINE_PRINT(fac_facModPrimes);
76TIMING_DEFINE_PRINT(fac_liftFactors);
77TIMING_DEFINE_PRINT(fac_combineFactors);
78
79
80const int max_fp_fac = 3;
81
82static modpk theModulus;
83
84// !!! this should be placed in cf_gcd.h
85CanonicalForm
86iextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b );
87
88
89#ifdef DEBUGOUTPUT
90#define DEBOUTHPRINT(stream, msg, hg) \
91{stream << deb_level_msg << msg, stream.flush(); hprint( hg ); stream << endl;}
92
93static void
94hprint ( int * a )
95{
96    int n = a[0];
97    cerr << "( " << n << ": ";
98    int i = 1;
99    while ( i < n ) {
100        if ( a[i] != 0 )
101            cerr << i << " ";
102        i++;
103    }
104    cerr << ")";
105}
106#else /* DEBUGOUTPUT */
107#define DEBOUTHPRINT(stream, msg, hg)
108#endif /* DEBUGOUTPUT */
109
110static void
111hgroup ( int * a )
112{
113    int n = a[0];
114    int i, j, k;
115    for ( i = 1; i < n; i++ )
116        if ( a[i] != 0 )
117            for ( j = 1; j <= i; j++ )
118                if ( a[j] != 0 )
119                    for ( k = i; k < n; k += j )
120                        a[k] = 1;
121}
122
123static void
124hintersect( int * a, const int * const b )
125{
126    int i, n, na = a[0], nb = b[0];
127    if ( nb < na )
128        n = nb;
129    else
130        n = na;
131    for ( i = 1; i < n; i++ )
132        if ( b[i] == 0 )
133            a[i] = 0;
134    a[0] = n;
135}
136
137/*
138static int
139hcount ( const int * const a )
140{
141    int n = a[0], sum = 0, i;
142    for ( i = 1; i < n; i++ )
143        if ( a[i] != 0 ) sum++;
144    return sum;
145}
146*/
147
148static void
149initHG ( int * a, const CFFList & F )
150{
151    ListIterator<CFFactor> i;
152
153    int n = a[0], k;
154    for ( int j = 1; j < n; j++ ) a[j] = 0;
155    for ( i = F; i.hasItem(); i++ )
156        if ( (k = i.getItem().factor().degree()) < n )
157            if ( k == -1 ) {
158                STICKYWARN( k == -1, "there occured an error.  factory was not able to factorize\n"
159                            "correctly mod p.  Please send the example which caused\n"
160                            "this error to the authors.  Nonetheless we will go on with the\n"
161                            "calculations hoping the result will be correct.  Thank you." );
162            }
163            else if ( k != 0 )
164                a[k] = 1;
165}
166
167static void
168initHG ( int * a, const Array<CanonicalForm> & F )
169{
170    int i, n = a[0], m = F.size(), k;
171    for ( i = 1; i < n; i++ ) a[i] = 0;
172    for ( i = 1; i < m; i++ )
173        if ( (k = F[i].degree()) < n )
174            if ( k == -1 ) {
175                STICKYWARN( k == -1, "there occured an error.  factory was not able to factorize\n"
176                            "correctly mod p.  Please send the example which caused\n"
177                            "this error to the authors.  Nonetheless we will go on with the\n"
178                            "calculations hoping the result will be correct.  Thank you." );
179            }
180            else if ( k != 0 )
181                a[k] = 1;
182}
183
184static int
185cmpFactor( const CFFactor & a, const CFFactor & b )
186{
187    CFFactor A( a ), B( b );
188    return degree( A.factor() ) > degree( B.factor() );
189}
190
191static double
192cf2double ( const CanonicalForm & f )
193{
194    CanonicalForm a = f, q, r;
195    double m = 1, res = 0;
196    if ( a.sign() < 0 ) a = -a;
197    while ( ! a.isZero() ) {
198        divrem( a, 10, q, r );
199        res += m * (double)(r.intval());
200        m *= 10;
201        a = q;
202    }
203    if ( f.sign() < 0 ) res = -res;
204    return res;
205}
206
207static double
208dnorm ( const CanonicalForm & f )
209{
210    CFIterator i;
211    CanonicalForm sum = 0;
212    for ( i = f; i.hasTerms(); i++ ) sum += i.coeff() * i.coeff();
213    DEBOUTLN( cerr, "sum = " << sum );
214    return sqrt( cf2double( sum ) );
215}
216
217static int
218kBound ( const CanonicalForm & f, int p )
219{
220    DEBOUTLN( cerr, "lc(f) = " << lc(f) );
221    return (int)((f.degree()*log(2)+log( fabs(cf2double(lc(f))) )+log( dnorm( f ) )) / log( (double)p ) + 0.5) + 1;
222}
223
224modpk
225getZFacModulus()
226{
227    return theModulus;
228}
229
230static bool
231liftDegreeFactRec( CFArray & theFactors, CanonicalForm & F, const CanonicalForm & recip_lf, const CanonicalForm & f, const modpk & pk, int i, int d, CFFList & ZF, int exp )
232{
233    if ( i >= theFactors.size() )
234        return false;
235    else  if ( degree( f ) + degree( theFactors[i] ) == d ) {
236        DEBOUTLN( cerr, "ldfr (f) = " << f );
237        DEBOUTLN( cerr, "ldfr (g) = " << theFactors[i] );
238        CanonicalForm g = pp( pk( recip_lf * f * theFactors[i] ) );
239        DEBOUTLN( cerr, "ldfr (pk(f*g)) = " << g );
240        CanonicalForm gg, hh;
241        DEBOUTLN( cerr, "F = " << F );
242        DEBOUTLN( cerr, "g = " << g );
243        if ( divremt( F, g, gg, hh ) && hh.isZero() ) {
244            ZF.append( CFFactor( g, exp ) );
245            F = gg;
246            theFactors[i] = 1;
247            return true;
248        }
249        else {
250            return liftDegreeFactRec( theFactors, F, recip_lf, f, pk, i+1, d, ZF, exp );
251        }
252    }
253    else  if ( degree( f ) + degree( theFactors[i] ) > d )
254        return false;
255    else {
256        bool ok = liftDegreeFactRec( theFactors, F, recip_lf, pk( recip_lf * f * theFactors[i] ), pk, i+1, d, ZF, exp );
257        if ( ok )
258            theFactors[i] = 1;
259        else
260            ok = liftDegreeFactRec( theFactors, F, recip_lf, f, pk, i+1, d, ZF, exp );
261        return ok;
262    }
263}
264
265
266static int
267choosePrimes ( int * p, const CanonicalForm & f )
268{
269    int ptr = 0;
270    int i = 0;
271    int maxp = cf_getNumPrimes();
272    int prime;
273
274    while ( ptr < maxp && i < max_fp_fac ) {
275        prime = cf_getPrime( ptr );
276        if ( mod( lc( f ), prime ) != 0 ) {
277            setCharacteristic( prime );
278            if ( isSqrFreeFp( mapinto( f ) ) ) {
279                p[i] = prime;
280                i++;
281            }
282            setCharacteristic( 0 );
283        }
284        ptr++;
285    }
286    return ( i == max_fp_fac );
287}
288
289
290static int
291UnivariateQuadraticLift ( const CanonicalForm &F, const  CanonicalForm & G, const CanonicalForm &H, const modpk & pk, const CanonicalForm & Gamma, CanonicalForm & gk, CanonicalForm & hk )
292{
293    CanonicalForm lf, f, gamma;
294    CanonicalForm a, b, aa, bb, c, g, h, g1, h1, e, modulus, tmp, q, r;
295    int i, j, save;
296    int p = pk.getp(), k = pk.getk();
297    int no_iter = (int)(log( (double)k )/log(2)+2);
298    int * kvals = new int[no_iter];
299
300    DEBOUTLN( cerr, "quadratic lift called with p = " << p << "  and k = " << k );
301    for ( j = 0, i = k; i > 1; i = ( i+1 ) / 2, j++ ) kvals[j] = i;
302    kvals[j] = 1;
303
304    save = getCharacteristic(); setCharacteristic( 0 );
305
306    lf = lc( F );
307    f = lf * F;
308    {
309        setCharacteristic( p );
310        g1 = mapinto( lf ) / lc( G ) * G;
311        h1 = mapinto( lf ) / lc( H ) * H;
312        (void)extgcd( g1, h1, a, b );
313        setCharacteristic( 0 );
314    }
315    a = mapinto( a ); b = mapinto( b );
316    g = mapinto( g1 ); h = mapinto( h1 );
317    g = replaceLc( g, lf ); h = replaceLc( h, lf );
318    e = f - g * h;
319    modulus = p;
320    i = 1;
321
322    while ( ! e.isZero() && j > 0 ) {
323        c = div( e, modulus );
324        {
325            j--;
326            setCharacteristic( p, kvals[j+1] );
327            DEBOUTLN( cerr, "lifting from p^" << kvals[j+1] << " to p^" << kvals[j] );
328            c = mapinto( c );
329            DEBOUTLN( cerr, " !!! g = " << mapinto( g ) );
330            g1 = mapinto( lf ) / mapinto( lc( g ) ) * mapinto( g );
331            h1 = mapinto( lf ) / mapinto( lc( h ) ) * mapinto( h );
332//          (void)extgcd( g1, h1, a, b );
333//          DEBOUTLN( cerr, " a = " << aa );
334//          DEBOUTLN( cerr, " b = " << bb );
335            a = mapinto( a ); b = mapinto( b );
336            a += ( ( 1 - a * g1 ) *  a ) % h1;
337            b += ( ( 1 - b * h1 ) *  b ) % g1;
338            DEBOUTLN( cerr, " a = " << a );
339            DEBOUTLN( cerr, " b = " << b );
340            divrem( a * c, h1, q, r );
341            tmp = b * c + q * g1;
342            setCharacteristic( 0 );
343        }
344        a = mapinto( a ); b = mapinto( b );
345        g += mapinto( tmp ) * modulus;
346        h += mapinto( r ) * modulus;
347//      g = replaceLc( g, lf ); h = replaceLc( h, lf );
348        e = f - g * h;
349        modulus = power( CanonicalForm(p), kvals[j] );
350        if ( mod( f - g * h, modulus ) != 0 )
351            DEBOUTLN( cerr, "error at lift stage " << i );
352        i++;
353    }
354    if ( e.isZero() ) {
355        tmp = content( g );
356        gk = g / tmp; hk = h / ( lf / tmp );
357    }
358    else {
359        gk = pk(g); hk = pk(h);
360    }
361    setCharacteristic( save );
362    return e.isZero();
363}
364
365static int
366UnivariateLinearLift ( const CanonicalForm &F, const  CanonicalForm & G, const CanonicalForm &H, const modpk & pk, const CanonicalForm & Gamma, CanonicalForm & gk, CanonicalForm & hk )
367{
368    CanonicalForm lf, f, gamma;
369    CanonicalForm a, b, c, g, h, g1, h1, e, modulus, tmp, q, r;
370    int i, save;
371    int p = pk.getp(), k = pk.getk();
372    save = getCharacteristic(); setCharacteristic( 0 );
373
374    lf = lc( F );
375    f = lf * F;
376    {
377        setCharacteristic( p );
378        g1 = mapinto( lf ) / lc( G ) * G;
379        h1 = mapinto( lf ) / lc( H ) * H;
380        (void)extgcd( g1, h1, a, b );
381        setCharacteristic( 0 );
382    }
383    g = mapinto( g1 ); h = mapinto( h1 );
384    g = replaceLc( g, lf ); h = replaceLc( h, lf );
385    e = f - g * h;
386    modulus = p;
387    i = 1;
388
389    while ( ! e.isZero() && i <= k ) {
390        c = div( e, modulus );
391        {
392            setCharacteristic( p );
393            c = mapinto( c );
394            divrem( a * c, h1, q, r );
395            tmp = b * c + q * g1;
396            setCharacteristic( 0 );
397        }
398        g += mapinto( tmp ) * modulus;
399        h += mapinto( r ) * modulus;
400//      g = replaceLc( g, lf ); h = replaceLc( h, lf );
401        e = f - g * h;
402        modulus *= p;
403        ASSERT( mod( f - g * h, modulus ) == 0, "error at lift stage" );
404        i++;
405    }
406    if ( e.isZero() ) {
407        tmp = content( g );
408        gk = g / tmp; hk = h / ( lf / tmp );
409    }
410    else {
411        gk = pk(g); hk = pk(h);
412    }
413    setCharacteristic( save );
414//    return e.isZero();
415    return (F-gk*hk).isZero();
416}
417
418
419CFFList
420ZFactorizeUnivariate( const CanonicalForm& ff, bool issqrfree )
421{
422    bool symmsave = isOn( SW_SYMMETRIC_FF );
423    CanonicalForm cont = content( ff );
424    CanonicalForm lf, recip_lf, fp, f, g = ff / cont, dummy1, dummy2;
425    int i, k, exp, n;
426    bool ok;
427    CFFList H, F[max_fp_fac];
428    CFFList ZF;
429    int * p = new int [max_fp_fac];
430    int * D = 0;
431    int * Dh = 0;
432    ListIterator<CFFactor> J, I;
433
434    DEBINCLEVEL( cerr, "ZFactorizeUnivariate" );
435    On( SW_SYMMETRIC_FF );
436
437    // get squarefree decomposition of f
438    if ( issqrfree )
439        H.append( CFFactor( g, 1 ) );
440    else
441        H = sqrFree( g );
442
443    DEBOUTLN( cerr, "H = " << H );
444
445    // cycle through squarefree factors of f
446    for ( J = H; J.hasItem(); ++J ) {
447        f = J.getItem().factor();
448        if ( f.inCoeffDomain() ) continue;
449        n = f.degree() / 2 + 1;
450        delete [] D;
451        delete [] Dh;
452        D = new int [n]; D[0] = n;
453        Dh = new int [n]; Dh[0] = n;
454        exp = J.getItem().exp();
455
456        // choose primes to factor f
457        TIMING_START(fac_choosePrimes);
458        ok = choosePrimes( p, f );
459        TIMING_END_AND_PRINT(fac_choosePrimes, "time to choose the primes: ");
460        if ( ! ok ) {
461            DEBOUTLN( cerr, "warning: no good prime found to factorize " << f );
462            STICKYWARN( ok, "there occured an error.  We went out of primes p\n"
463                        "to factorize mod p.  Please send the example which caused\n"
464                        "this error to the authors.  Nonetheless we will go on with the\n"
465                        "calculations hoping the result will be correct.  Thank you.");
466            ZF.append( CFFactor( f, exp ) );
467            continue;
468        }
469
470        // factorize f modulo certain primes
471        TIMING_START(fac_facModPrimes);
472        for ( i = 0; i < max_fp_fac; i++ ) {
473            setCharacteristic( p[i] );
474            fp = mapinto( f );
475            F[i] = FpFactorizeUnivariateCZ( fp, true );
476//              if ( p[i] < 23 && fp.degree() < 10 )
477//                  F[i] = FpFactorizeUnivariateB( fp, true );
478//              else
479//                  F[i] = FpFactorizeUnivariateCZ( fp, true );
480            DEBOUTLN( cerr, "F[i] = " << F[i] << ", p = " << p[i] );
481        }
482        TIMING_END_AND_PRINT(fac_facModPrimes, "time to factorize mod primes: ");
483        setCharacteristic( 0 );
484
485        // do some strange things with the D's
486        initHG( D, F[0] );
487        hgroup( D );
488        DEBOUTHPRINT( cerr, "D = ", D );
489        for ( i = 1; i < max_fp_fac; i++ ) {
490            initHG( Dh, F[i] );
491            hgroup( Dh );
492            DEBOUTHPRINT( cerr, "Dh = ", Dh );
493            hintersect( D, Dh );
494            DEBOUTHPRINT( cerr, "D = ", D );
495        }
496
497        // look which p gives the shortest factorization of f mod p
498        // j: index of that p in p[]
499        int min, j;
500        min = F[0].length(), j = 0;
501        for ( i = 1; i < max_fp_fac; i++ ) {
502            if ( min >= F[i].length() ) {
503                j = i; min = F[i].length();
504            }
505        }
506        k = kBound( f, p[j] );
507        CFArray theFactors( F[j].length() );
508//          pk = power( CanonicalForm( p[j] ), k );
509//          pkhalf = pk / 2;
510        modpk pk( p[j], k );
511        DEBOUTLN( cerr, "coeff bound = " << pk.getpk() );
512        theModulus = pk;
513        setCharacteristic( p[j] );
514        fp = mapinto( f );
515        F[j].sort( cmpFactor );
516        I = F[j]; i = 0;
517        TIMING_START(fac_liftFactors);
518        while ( I.hasItem() ) {
519            DEBOUTLN( cerr, "factor to lift = " << I.getItem().factor() );
520            if ( isOn( SW_FAC_QUADRATICLIFT ) )
521                ok = UnivariateQuadraticLift( f, I.getItem().factor(), fp / I.getItem().factor(), pk, lc( f ), dummy1, dummy2 );
522            else
523                ok = UnivariateLinearLift( f, I.getItem().factor(), fp / I.getItem().factor(), pk, lc( f ), dummy1, dummy2 );
524            if ( ok ) {
525                // should be done in a more efficient way
526                DEBOUTLN( cerr, "dummy1 = " << dummy1 );
527                DEBOUTLN( cerr, "dummy2 = " << dummy2 );
528                f = dummy2;
529                fp /= I.getItem().factor();
530                ZF.append( CFFactor( dummy1, exp ) );
531                I.remove( 0 );
532                I = F[j];
533                i = 0;
534                DEBOUTLN( cerr, "F[j] = " << F[j] );
535            }
536            else {
537                DEBOUTLN( cerr, "i = " << i );
538                DEBOUTLN( cerr, "dummy1 = " << dummy1 );
539                setCharacteristic( 0 );
540//                  theFactors[i] = pk( dummy1 * pk.inverse( lc( dummy1 ) ) );
541                theFactors[i] = pk( dummy1 );
542                setCharacteristic( p[j] );
543                i++;
544                I++;
545            }
546        }
547        TIMING_END_AND_PRINT(fac_liftFactors, "time to lift the factors: ");
548        DEBOUTLN( cerr, "ZF = " << ZF );
549        initHG( Dh, theFactors );
550        hgroup( Dh );
551        DEBOUTHPRINT( cerr, "Dh = ", Dh );
552        hintersect( D, Dh );
553        setCharacteristic( 0 );
554        for ( int l = i; l < F[j].length(); l++ )
555            theFactors[l] = 1;
556        DEBOUTLN( cerr, "theFactors = " << theFactors );
557        DEBOUTLN( cerr, "f = " << f );
558        DEBOUTLN( cerr, "p = " << pk.getp() << ", k = " << pk.getk() );
559        DEBOUTHPRINT( cerr, "D = ", D );
560        lf = lc( f );
561        (void)iextgcd( pk.getpk(), lf, dummy1, recip_lf );
562        DEBOUTLN( cerr, "recip_lf = " << recip_lf );
563        TIMING_START(fac_combineFactors);
564        for ( i = 1; i < D[0]; i++ )
565            if ( D[i] != 0 )
566                while ( liftDegreeFactRec( theFactors, f, recip_lf, lf, pk, 0, i, ZF, exp ) );
567        if ( degree( f ) > 0 )
568            ZF.append( CFFactor( f, exp ) );
569        TIMING_END_AND_PRINT(fac_combineFactors, "time to combine the factors: ");
570    }
571
572    // brush up our result
573    if ( ZF.getFirst().factor().inCoeffDomain() )
574        ZF.removeFirst();
575    if ( lc( ff ).sign() < 0 )
576        ZF.insert( CFFactor( -cont, 1 ) );
577    else
578        ZF.insert( CFFactor( cont, 1 ) );
579    delete [] D;
580    delete [] Dh;
581    if ( ! symmsave )
582        Off( SW_SYMMETRIC_FF );
583
584    DEBDECLEVEL( cerr, "ZFactorizeUnivariate" );
585    return ZF;
586}
Note: See TracBrowser for help on using the repository browser.