source: git/factory/fac_multivar.cc @ 362fc67

spielwiese
Last change on this file since 362fc67 was 362fc67, checked in by Martin Lee <martinlee84@…>, 12 years ago
chg: remove $Id$
  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[493c477]1/* emacs edit mode for this file is -*- C++ -*- */
[2dd068]2
[e4fe2b]3#include "config.h"
[173e86]4
[650f2d8]5#include "cf_assert.h"
[043814]6#include "debug.h"
[125195]7#include "timing.h"
[2dd068]8
9#include "cf_defs.h"
[f58e95]10#include "cf_algorithm.h"
[2dd068]11#include "fac_multivar.h"
12#include "fac_univar.h"
13#include "cf_reval.h"
14#include "cf_map.h"
15#include "fac_util.h"
16#include "cf_binom.h"
17#include "cf_iter.h"
[cae0b6]18#include "cf_primes.h"
[e074407]19#include "fac_distrib.h"
[2dd068]20
[3a7ee74]21void out_cf(const char *s1,const CanonicalForm &f,const char *s2);
[c6d3744]22void out_cff(CFFList &L);
[2dd068]23
[e76d7a6]24TIMING_DEFINE_PRINT(fac_content)
25TIMING_DEFINE_PRINT(fac_findeval)
26TIMING_DEFINE_PRINT(fac_distrib)
27TIMING_DEFINE_PRINT(fac_hensel)
[2dd068]28
29static CFArray
30conv_to_factor_array( const CFFList & L )
31{
32    int n;
33    CFFListIterator I = L;
[125195]34    bool negate = false;
35
[2dd068]36    if ( ! I.hasItem() )
[cae0b6]37        n = 0;
[2dd068]38    else  if ( I.getItem().factor().inBaseDomain() ) {
[cae0b6]39        negate = I.getItem().factor().sign() < 0;
40        I++;
41        n = L.length();
[2dd068]42    }
43    else
[cae0b6]44        n = L.length() + 1;
[2dd068]45    CFFListIterator J = I;
46    while ( J.hasItem() ) {
[cae0b6]47        n += J.getItem().exp() - 1;
48        J++;
[2dd068]49    }
50    CFArray result( 1, n-1 );
51    int i, j, k;
52    i = 1;
53    while ( I.hasItem() ) {
[cae0b6]54        k = I.getItem().exp();
55        for ( j = 1; j <= k; j++ ) {
56            result[i] = I.getItem().factor();
57            i++;
58        }
59        I++;
[2dd068]60    }
[125195]61    if ( negate )
[cae0b6]62        result[1] = -result[1];
[2dd068]63    return result;
64}
65
[125195]66static modpk
[2dd068]67coeffBound ( const CanonicalForm & f, int p )
68{
69    int * degs = degrees( f );
70    int M = 0, i, k = f.level();
71    for ( i = 1; i <= k; i++ )
[cae0b6]72        M += degs[i];
[c6caf1]73    CanonicalForm b = 2 * maxNorm( f ) * power( CanonicalForm( 3 ), M );
[2dd068]74    CanonicalForm B = p;
75    k = 1;
76    while ( B < b ) {
[cae0b6]77        B *= p;
78        k++;
[2dd068]79    }
80    return modpk( p, k );
81}
82
[e074407]83// static bool
84// nonDivisors ( CanonicalForm omega, CanonicalForm delta, const CFArray & F, CFArray & d )
85// {
[d81ed62]86//     DEBOUTLN( cerr, "nondivisors omega = " << omega );
87//     DEBOUTLN( cerr, "nondivisors delta = " << delta );
88//     DEBOUTLN( cerr, "nondivisors F = " << F );
[e074407]89//     CanonicalForm q, r;
90//     int k = F.size();
91//     d = CFArray( 0, k );
92//     d[0] = delta * omega;
93//     for ( int i = 1; i <= k; i++ ) {
[cae0b6]94//         q = abs(F[i]);
95//         for ( int j = i-1; j >= 0; j-- ) {
96//             r = d[j];
97//             do {
98//                 r = gcd( r, q );
99//                 q = q / r;
100//             } while ( r != 1 );
101//             if ( q == 1 )
102//                 return false;
103//         }
104//         d[i] = q;
[e074407]105//     }
106//     return true;
107// }
[2dd068]108
109static void
[125195]110findEvaluation ( const CanonicalForm & U, const CanonicalForm & V, const CanonicalForm & omega, const CFFList & F, Evaluation & A, CanonicalForm & U0, CanonicalForm & delta, CFArray & D, int r )
[2dd068]111{
[e074407]112    DEBINCLEVEL( cerr, "findEvaluation" );
[2dd068]113    CanonicalForm Vn;
114    CFFListIterator I;
115    int j;
116    bool found = false;
[125195]117    CFArray FF = CFArray( 1, F.length() );
[2dd068]118    if ( r > 0 )
[cae0b6]119        A.nextpoint();
[c6d3744]120    while ( ! found )
121    {
[cae0b6]122        Vn = A( V );
[c6d3744]123        if ( Vn != 0 )
124        {
[cae0b6]125            U0 = A( U );
126            DEBOUTLN( cerr, "U0 = " << U0 );
[c6d3744]127            if ( isSqrFree( U0 ) )
128            {
[cae0b6]129                delta = content( U0 );
130                DEBOUTLN( cerr, "content( U0 ) = " << delta );
131                for ( I = F, j = 1; I.hasItem(); I++, j++ )
132                    FF[j] = A( I.getItem().factor() );
133                found = nonDivisors( omega, delta, FF, D );
134            }
[c6d3744]135            else
136            {
[cae0b6]137                DEBOUTLN( cerr, "not sqrfree : " << sqrFree( U0 ) );
138            }
139        }
140        if ( ! found )
141            A.nextpoint();
[2dd068]142    }
[e074407]143    DEBDECLEVEL( cerr, "findEvaluation" );
[2dd068]144}
145
[cae0b6]146#ifdef HAVE_NTL
147int prime_number=0;
[77f483]148void find_good_prime(const CanonicalForm &f, int &start)
[cae0b6]149{
150  if (! f.inBaseDomain() )
151  {
[77f483]152    CFIterator i = f;
153    for(;;)
[cae0b6]154    {
[77f483]155      if  ( i.hasTerms() )
[ec989c]156      {
[77f483]157        find_good_prime(i.coeff(),start);
[493225]158        if (0==cf_getSmallPrime(start)) return;
[77f483]159        if((i.exp()!=0) && ((i.exp() % cf_getSmallPrime(start))==0))
160        {
161          start++;
162          i=f;
163        }
164        else  i++;
[ec989c]165      }
[77f483]166      else break;
[cae0b6]167    }
168  }
169  else
170  {
[77f483]171    if (f.inZ())
[cae0b6]172    {
[493225]173      if (0==cf_getSmallPrime(start)) return;
174      while((!f.isZero()) && (mod(f,cf_getSmallPrime(start))==0))
[77f483]175      {
176        start++;
[493225]177        if (0==cf_getSmallPrime(start)) return;
[77f483]178      }
[cae0b6]179    }
[77f483]180/* should not happen!
181    else if (f.inQ())
182    {
183      while((f.den()!=0) && (mod(f.den(),cf_getSmallPrime(start))==0))
184      {
185        start++;
186      }
187      while((f.num()!=0) && (mod(f.num(),cf_getSmallPrime(start))==0))
188      {
189        start++;
190      }
191    }
192    else
193          cout <<"??"<< f <<"\n";
194*/
[cae0b6]195  }
196}
197#endif
198
[c6d3744]199static CFArray ZFactorizeMulti ( const CanonicalForm & arg )
[2dd068]200{
[e074407]201    DEBINCLEVEL( cerr, "ZFactorizeMulti" );
[2dd068]202    CFMap M;
203    CanonicalForm UU, U = compress( arg, M );
204    CanonicalForm delta, omega, V = LC( U, 1 );
205    int t = U.level();
206    CFFList F = factorize( V );
207    CFFListIterator I, J;
[125195]208    CFArray G, lcG, D;
[01e8874]209    int i, j, r, maxdeg;
[afd067]210    REvaluation A( 2, t, IntRandom( 50 ) );
[2dd068]211    CanonicalForm U0;
212    CanonicalForm ft, ut, gt, d;
213    modpk b;
214    bool negate = false;
215
[d81ed62]216    DEBOUTLN( cerr, "-----------------------------------------------------" );
217    DEBOUTLN( cerr, "trying to factorize U = " << U );
218    DEBOUTLN( cerr, "U is a polynomial of level = " << arg.level() );
219    DEBOUTLN( cerr, "U will be factorized with respect to variable " << Variable(1) );
220    DEBOUTLN( cerr, "the leading coefficient of U with respect to that variable is " << V );
221    DEBOUTLN( cerr, "which is factorized as " << F );
[e074407]222
[2dd068]223    maxdeg = 0;
[c6d3744]224    for ( i = 2; i <= t; i++ )
225    {
[cae0b6]226        j = U.degree( Variable( i ) );
227        if ( j > maxdeg ) maxdeg = j;
[2dd068]228    }
229
[c6d3744]230    if ( F.getFirst().factor().inCoeffDomain() )
231    {
[cae0b6]232        omega = F.getFirst().factor();
233        F.removeFirst();
[c6d3744]234        if ( omega < 0 )
235        {
[cae0b6]236            negate = true;
237            omega = -omega;
238            U = -U;
239        }
[2dd068]240    }
241    else
[cae0b6]242        omega = 1;
[2dd068]243
244    bool goodeval = false;
245    r = 0;
246
247//    for ( i = 0; i < 10*t; i++ )
[cae0b6]248//        A.nextpoint();
[2dd068]249
[c6d3744]250    while ( ! goodeval )
251    {
[cae0b6]252        TIMING_START(fac_findeval);
253        findEvaluation( U, V, omega, F, A, U0, delta, D, r );
254        TIMING_END(fac_findeval);
255        DEBOUTLN( cerr, "the evaluation point to reduce to an univariate problem is " << A );
256        DEBOUTLN( cerr, "corresponding delta = " << delta );
257        DEBOUTLN( cerr, "              omega = " << omega );
258        DEBOUTLN( cerr, "              D     = " << D );
259        DEBOUTLN( cerr, "now factorize the univariate polynomial " << U0 );
260        G = conv_to_factor_array( factorize( U0, false ) );
261        DEBOUTLN( cerr, "which factorizes into " << G );
262        #ifdef HAVE_NTL
263        {
264          int i=prime_number;
[c6d3744]265          find_good_prime(arg,i);
266          find_good_prime(U0,i);
267          find_good_prime(U,i);
268          int p=cf_getSmallPrime(i);
269          //printf("found:p=%d (%d)\n",p,i);
[493225]270          if (p==0)
[32c11f]271          {
272            return conv_to_factor_array(CFFactor(arg,1));
273            //printf("out of primes - switch ot non-NTL\n");
[493225]274          }
[32c11f]275          else if (((i==0)||(i!=prime_number)))
[c6d3744]276          {
[cae0b6]277            b = coeffBound( U, p );
[c6d3744]278            prime_number=i;
279          }
[32c11f]280          // p!=0:
281          modpk bb=coeffBound(U0,p);
282          if (bb.getk() > b.getk() ) b=bb;
283          bb=coeffBound(arg,p);
284          if (bb.getk() > b.getk() ) b=bb;
[cae0b6]285        }
286        #else
287        b = coeffBound( U, getZFacModulus().getp() );
288        if ( getZFacModulus().getpk() > b.getpk() )
289            b = getZFacModulus();
290        #endif
[c6d3744]291        //printf("p=%d, k=%d\n",b.getp(),b.getk());
[cae0b6]292        DEBOUTLN( cerr, "the coefficient bound of the factors of U is " << b.getpk() );
[e074407]293
[cae0b6]294        r = G.size();
295        lcG = CFArray( 1, r );
296        UU = U;
297        DEBOUTLN( cerr, "now trying to distribute the leading coefficients ..." );
298        TIMING_START(fac_distrib);
299        goodeval = distributeLeadingCoeffs( UU, G, lcG, F, D, delta, omega, A, r );
300        TIMING_END(fac_distrib);
[e074407]301#ifdef DEBUGOUTPUT
[c6d3744]302        if ( goodeval )
303        {
[cae0b6]304            DEBOUTLN( cerr, "the univariate factors after distribution are " << G );
305            DEBOUTLN( cerr, "the distributed leading coeffs are " << lcG );
306            DEBOUTLN( cerr, "U may have changed and is now " << UU );
307            DEBOUTLN( cerr, "which has leading coefficient " << LC( UU, Variable(1) ) );
[e074407]308
[c6d3744]309            if ( LC( UU, Variable(1) ) != prod( lcG ) || A(UU) != prod( G ) )
310            {
[cae0b6]311                DEBOUTLN( cerr, "!!! distribution was not correct !!!" );
312                DEBOUTLN( cerr, "product of leading coeffs is " << prod( lcG ) );
313                DEBOUTLN( cerr, "product of univariate factors is " << prod( G ) );
314                DEBOUTLN( cerr, "the new U is evaluated as " << A(UU) );
315            }
316            else
317                DEBOUTLN( cerr, "leading coeffs correct" );
318        }
[c6d3744]319        else
320        {
[cae0b6]321            DEBOUTLN( cerr, "we have found a bad evaluation point" );
322        }
[e074407]323#endif
[c6d3744]324        if ( goodeval )
325        {
[cae0b6]326            TIMING_START(fac_hensel);
327            goodeval = Hensel( UU, G, lcG, A, b, Variable(1) );
328            TIMING_END(fac_hensel);
329        }
[2dd068]330    }
[c6d3744]331    for ( i = 1; i <= r; i++ )
332    {
[cae0b6]333        G[i] /= icontent( G[i] );
334        G[i] = M(G[i]);
[e074407]335    }
[2dd068]336    // negate noch beachten !
337    if ( negate )
[cae0b6]338        G[1] = -G[1];
[e074407]339    DEBDECLEVEL( cerr, "ZFactorMulti" );
[2dd068]340    return G;
341}
342
[c6d3744]343CFFList ZFactorizeMultivariate ( const CanonicalForm & f, bool issqrfree )
[2dd068]344{
345    CFFList G, F, R;
346    CFArray GG;
347    CFFListIterator i, j;
348    CFMap M;
349    CanonicalForm g, cont;
350    Variable v1, vm;
351    int k, m, n;
352
353    v1 = Variable(1);
354    if ( issqrfree )
[cae0b6]355        F = CFFactor( f, 1 );
[2dd068]356    else
[e89e56]357        F = sqrFree( f );
[2dd068]358
[c6d3744]359    for ( i = F; i.hasItem(); i++ )
360    {
361        if ( i.getItem().factor().inCoeffDomain() )
[f78374]362            R.append( CFFactor( i.getItem().factor(), i.getItem().exp() ) );
[c6d3744]363        else
364        {
[cae0b6]365            TIMING_START(fac_content);
366            g = compress( i.getItem().factor(), M );
367            // now after compress g contains Variable(1)
368            vm = g.mvar();
369            g = swapvar( g, v1, vm );
370            cont = content( g );
371            g = swapvar( g / cont, v1, vm );
372            cont = swapvar( cont, v1, vm );
373            n = i.getItem().exp();
374            TIMING_END(fac_content);
375            DEBOUTLN( cerr, "now after content ..." );
[c6d3744]376            if ( g.isUnivariate() )
377            {
[cae0b6]378                G = factorize( g, true );
379                for ( j = G; j.hasItem(); j++ )
380                    if ( ! j.getItem().factor().isOne() )
381                        R.append( CFFactor( M( j.getItem().factor() ), n ) );
382            }
[c6d3744]383            else
384            {
[cae0b6]385                GG = ZFactorizeMulti( g );
386                m = GG.max();
387                for ( k = GG.min(); k <= m; k++ )
388                    if ( ! GG[k].isOne() )
389                        R.append( CFFactor( M( GG[k] ), n ) );
390            }
391            G = factorize( cont, true );
392            for ( j = G; j.hasItem(); j++ )
393                if ( ! j.getItem().factor().isOne() )
394                    R.append( CFFactor( M( j.getItem().factor() ), n ) );
395        }
[2dd068]396    }
397    return R;
398}
Note: See TracBrowser for help on using the repository browser.