Changeset ad8e1b in git for factory/algext.cc
- Timestamp:
- Aug 6, 2008, 3:53:15 PM (16 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- e8a0aaf34722c3d93f882019f7622c3419ed764d
- Parents:
- 69b66ef25238d635e8046b0a178b0552b57b23c3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
factory/algext.cc
r69b66ef rad8e1b 13 13 #include "cf_generator.h" 14 14 15 void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm M, CanonicalForm & result, bool & fail ) 16 { 17 CanonicalForm P; 18 if( degree(A) > degree(B) ) 19 { 20 P = A; result = B; 21 } 22 else 23 { 24 P = B; result = A; 25 } 26 if( P.isZero() ) // then result is zero, too 27 return; 28 CanonicalForm inv; 29 if( result.isZero() ) 30 { 31 tryInvert( Lc(P), M, inv, fail ); 32 if(fail) 33 return; 34 result = inv*P; // monify result 35 return; 36 } 37 CanonicalForm rem; 38 // here: degree(P) >= degree(result) 39 while(true) 40 { 41 tryInvert( Lc(result), M, inv, fail ); 42 if(fail) 43 return; 44 // here: Lc(result) is invertible modulo M 45 rem = P - Lc(P)*inv*result * power( P.mvar(), degree(P)-degree(result) ); 46 if( rem.isZero() ) 47 { 48 result *= inv; // monify result 49 return; 50 } 51 P = result; 52 result = rem; 53 } 54 } 55 15 CanonicalForm reduce(const CanonicalForm & f, const CanonicalForm & M) 16 { // polynomials in M.mvar() are considered coefficients 17 // M univariate monic polynomial 18 // the coefficients of f are reduced modulo M 19 if(f.inBaseDomain() || f.level() < M.level()) 20 return f; 21 if(f.level() == M.level()) 22 { 23 if(f.degree() < M.degree()) 24 return f; 25 CanonicalForm tmp = f; 26 do 27 tmp -= lc(tmp)*M*power(M.mvar(),tmp.degree()-M.degree()); 28 while(tmp.degree() >= M.degree()); 29 return tmp; 30 } 31 // here: f.level() > M.level() 32 CanonicalForm result = 0; 33 for(CFIterator i=f; i.hasTerms(); i++) 34 result += reduce(i.coeff(),M) * power(f.mvar(),i.exp()); 35 return result; 36 } 56 37 57 38 void tryInvert( const CanonicalForm & F, const CanonicalForm & M, CanonicalForm & inv, bool & fail ) 58 { 59 // F, M are required to be "univariate" polynomials in an algebraic variable 39 { // F, M are required to be "univariate" polynomials in an algebraic variable 60 40 // we try to invert F modulo M 41 if(F.inBaseDomain()) 42 { 43 if(F.isZero()) 44 { 45 fail = true; 46 return; 47 } 48 inv = 1/F; 49 return; 50 } 61 51 CanonicalForm b; 62 52 Variable a = M.mvar(); 63 53 Variable x = Variable(1); 64 54 if(!extgcd( replacevar( F, a, x ), replacevar( M, a, x ), inv, b ).isOne()) 65 {66 printf("failed ");67 55 fail = true; 68 }69 56 else 70 inv = replacevar( inv, a, x); // change back to alg var 71 } 72 57 inv = replacevar( inv, x, a ); // change back to alg var 58 } 59 60 void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm & M, CanonicalForm & result, bool & fail ) 61 { 62 CanonicalForm P; 63 if(A.inCoeffDomain()) 64 { 65 tryInvert( A, M, P, fail ); 66 if(fail) 67 return; 68 result = 1; 69 return; 70 } 71 if(B.inCoeffDomain()) 72 { 73 tryInvert( B, M, P, fail ); 74 if(fail) 75 return; 76 result = 1; 77 return; 78 } 79 // here: both not inCoeffDomain 80 if( A.degree() > B.degree() ) 81 { 82 P = A; result = B; 83 } 84 else 85 { 86 P = B; result = A; 87 } 88 CanonicalForm inv; 89 if( result.isZero() ) 90 { 91 tryInvert( Lc(P), M, inv, fail ); 92 if(fail) 93 return; 94 result = inv*P; // monify result (not reduced, yet) 95 return; 96 } 97 Variable x = P.mvar(); 98 CanonicalForm rem; 99 // here: degree(P) >= degree(result) 100 while(true) 101 { 102 tryInvert( Lc(result), M, inv, fail ); 103 if(fail) 104 return; 105 // here: Lc(result) is invertible modulo M 106 rem = reduce( P - Lc(P)*inv*result*power( x, P.degree(x)-result.degree(x) ), M ); 107 if( rem.isZero() ) 108 { 109 result *= inv; 110 return; 111 } 112 if(result.degree(x) >= rem.degree(x)) 113 { 114 P = result; 115 result = rem; 116 } 117 else 118 P = rem; 119 } 120 } 73 121 74 122 bool hasFirstAlgVar( const CanonicalForm & f, Variable & a ) … … 76 124 if( f.inBaseDomain() ) // f has NO alg. variable 77 125 return false; 78 79 126 if( f.level()<0 ) // f has only alg. vars, so take the first one 80 127 { … … 85 132 if( hasFirstAlgVar( i.coeff(), a )) 86 133 return true; // 'a' is already set 87 88 134 return false; 89 135 } … … 183 229 184 230 185 CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G ) 186 { // F,G in Q(a)[x1,...,xn] 231 232 CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G ); 233 int * leadDeg(const CanonicalForm & f, int *degs); 234 bool isLess(int *a, int *b, int lower, int upper); 235 bool isEqual(int *a, int *b, int lower, int upper); 236 CanonicalForm firstLC(const CanonicalForm & f); 237 void tryCRA( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, const CanonicalForm & M, CanonicalForm & xnew, CanonicalForm & qnew, bool & fail ); 238 void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail ); 239 static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ); 240 static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ); 241 static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail ); 242 static void tryDivide( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, CanonicalForm & result, bool & divides, bool & fail ); 243 244 245 void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail ) 246 { // assume F,G are multivariate polys over Z/p(a) for big prime p, M "univariate" polynomial in an algebraic variable 247 // M is assumed to be monic 187 248 if(F.isZero()) 188 249 { 189 250 if(G.isZero()) 190 return G; // G is zero 251 { 252 result = G; // G is zero 253 return; 254 } 191 255 if(G.inCoeffDomain()) 192 return CanonicalForm(1);193 return G/Lc(G); // return monic G194 }195 if(G.isZero()) // F is non-zero196 {197 if(F.inCoeffDomain())198 return CanonicalForm(1);199 return F/Lc(F); // return monic F200 }201 if(F.inCoeffDomain() || G.inCoeffDomain())202 return CanonicalForm(1);203 204 CanonicalForm D;205 if (getCharacteristic()==0)206 {207 CanonicalForm f,g,tmp, M, q, Dp, cl, newD, newq;208 int p, i;209 int *bound, *other; // degree vectors210 bool fail;211 On(SW_RATIONAL);212 f = F * bCommonDen(F);213 g = G * bCommonDen(G);214 Variable a,b;215 if( !hasFirstAlgVar( f, a ) && !hasFirstAlgVar( g, b ))216 {217 // F and G are in Q[x1,...,xn], call...218 return gcd_poly_0( f, g );219 }220 if( b.level() > a.level() )221 a = b;222 // here: a is the biggest alg. var in f and g223 tmp = getMipo(a);224 M = tmp * bCommonDen(tmp);225 Off( SW_RATIONAL );226 // here: f, g in Z[y][x1,...,xn], M in Z[y] not necessarily monic227 // calculate upper bound for degree of gcd228 int mv = f.level();229 if(g.level() > mv)230 mv = g.level();231 // here: mv is level of the largest variable in f, g232 bound = new int[mv+1];233 other = new int[mv+1];234 for(int i=1; i<=mv; i++)235 bound[i] = other[i] = 0;236 bound = leadDeg(f,bound);237 other = leadDeg(g,other);238 for(int i=1; i<=mv; i++) // entry at i=0 is not visited239 if(other[i] < bound[i])240 bound[i] = other[i];241 // now bound points on the smaller vector242 cl = lc(M) * lc(f) * lc(g);243 q = 1;244 D = 0;245 for(int i=cf_getNumBigPrimes()-1; i>-1; i--)246 {247 p = cf_getBigPrime(i);248 if( mod( cl, p ).isZero() ) // skip lc-bad primes249 continue;250 251 fail = false;252 setCharacteristic(p);253 tryBrownGCD( mapinto(f), mapinto(g), mapinto(M), Dp, fail );254 setCharacteristic(0);255 if( fail ) // M splits in char p256 continue;257 258 for(int i=1; i<=mv; i++)259 other[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)260 other = leadDeg(Dp,other);261 262 if( other==0 ) // early termination263 {264 // Dp is in coeff domain265 CanonicalForm inv;266 tryInvert(Dp,M,inv,fail); // check if zero-divisor267 if(fail)268 continue;269 return CanonicalForm(1);270 }271 272 if( isLess(bound, other, 1, mv) ) // current prime unlucky273 continue;274 275 if( isLess(other, bound, 1, mv) ) // all previous primes unlucky276 {277 q = p;278 D = mapinto(Dp); // shortcut CRA279 for(int i=1; i<=mv; i++) // tighten bound280 bound[i] = other[i];281 continue;282 }283 chineseRemainder( D, q, mapinto(Dp), p, newD, newq );284 // newD = Dp mod p285 // newD = D mod q286 // newq = p*q287 q = newq;288 if( D != newD )289 {290 D = newD;291 continue;292 }293 On( SW_RATIONAL );294 tmp = Farey( D, q );295 if( fdivides( tmp, f ) && fdivides( tmp, g )) // trial division296 {297 Off( SW_RATIONAL );298 return tmp;299 }300 Off( SW_RATIONAL );301 }302 }303 // hopefully, we never reach this point304 Off( SW_USE_QGCD );305 D = gcd( F, G );306 On( SW_USE_QGCD );307 return D;308 }309 310 void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail )311 {// assume F,G are multivariate polys over Z/p(a) for big prime p, M "univariate" polynomial in an algebraic variable312 printf("Brown ");313 if(F.isZero())314 {315 if(G.isZero())316 {317 result = G; // G is zero318 return;319 }320 if(G.inCoeffDomain())321 256 { 322 257 tryInvert(G,M,result,fail); 258 if(fail) 259 return; 260 result = 1; 323 261 return; 324 262 } … … 336 274 { 337 275 tryInvert(F,M,result,fail); 276 if(fail) 277 return; 278 result = 1; 338 279 return; 339 280 } … … 346 287 return; 347 288 } 289 // here: F,G both nonzero 348 290 if(F.inCoeffDomain()) 349 291 { 350 292 tryInvert(F,M,result,fail); 293 if(fail) 294 return; 295 result = 1; 351 296 return; 352 297 } … … 354 299 { 355 300 tryInvert(G,M,result,fail); 301 if(fail) 302 return; 303 result = 1; 356 304 return; 357 305 } … … 363 311 CanonicalForm f=MM(F); 364 312 CanonicalForm g=MM(G); 365 // here: f, 313 // here: f,g are compressed 366 314 // compute largest variable in f or g (least one is Variable(1)) 367 315 int mv = f.level(); … … 378 326 } 379 327 // here: mv > 1 380 CanonicalForm cf = vcontent(f, Variable(2)); // cf is univariate poly in var(1) 381 CanonicalForm cg = vcontent(g, Variable(2)); 328 CanonicalForm cf = tryvcontent(f, Variable(2), M, fail); // cf is univariate poly in var(1) 329 if(fail) 330 return; 331 CanonicalForm cg = tryvcontent(g, Variable(2), M, fail); 332 if(fail) 333 return; 382 334 CanonicalForm c; 383 335 tryEuclid(cf,cg,M,c,fail); 384 336 if(fail) 385 337 return; 386 f/=cf; 387 g/=cg; 338 bool divides = true; 339 CanonicalForm tmp; 340 // f /= cf 341 tryDivide(f,cf,M,tmp,divides,fail); // 'divides' is not checked 342 if(fail) 343 return; 344 f = tmp; 345 // g /= cg 346 tryDivide(g,cg,M,tmp,divides,fail); // 'divides' is not checked 347 if(fail) 348 return; 349 g = tmp; 388 350 if(f.inCoeffDomain()) 389 351 { … … 391 353 if(fail) 392 354 return; 393 result = NN( result);355 result = NN(c); 394 356 return; 395 357 } … … 399 361 if(fail) 400 362 return; 401 result = NN( result);363 result = NN(c); 402 364 return; 403 365 } … … 412 374 if(fail) 413 375 return; 414 for(int i=2; i<=mv; i++) // entr y at i=1 isnot visited376 for(int i=2; i<=mv; i++) // entries at i=0,1 not visited 415 377 if(N[i] < L[i]) 416 378 L[i] = N[i]; … … 426 388 { 427 389 alpha = gen.item(); 428 gamma_image = gamma(alpha, Variable(1)); // plug in alpha for var(1)390 gamma_image = reduce(gamma(alpha, Variable(1)),M); // plug in alpha for var(1) 429 391 if(gamma_image.isZero()) // skip lc-bad points var(1)-alpha 430 392 continue; … … 432 394 if(fail) 433 395 return; 396 g_image = reduce(g_image, M); 434 397 if(g_image.inCoeffDomain()) // early termination 435 398 { … … 447 410 g_image /= lc(g_image); // make g_image monic over Z/p 448 411 g_image *= gamma_image; // multiply by multiple of image lc(gcd) 449 tryCRA( g_image, Variable(1)-alpha, gm, m, gnew, mnew, fail );412 tryCRA( g_image, Variable(1)-alpha, gm, m, M, gnew, mnew, fail ); 450 413 // gnew = gm mod m 451 414 // gnew = g_image mod var(1)-alpha … … 456 419 if(gnew == gm) // gnew did not change 457 420 { 458 g_image = gm / vcontent(gm, Variable(2)); 459 if(fdivides(g_image,f) && fdivides(g_image,g)) // trial division 421 cf = tryvcontent(gm, Variable(2), M, fail); 422 if(fail) 423 return; 424 divides = true; 425 tryDivide(gm,cf,M,g_image,divides,fail); // 'divides' is ignored 426 if(fail) 427 return; 428 tryDivide(f,g_image,M,tmp,divides,fail); // trial division (f) 429 if(fail) 430 return; 431 if(divides) 460 432 { 461 result = NN(c*g_image); 462 return; 433 tryDivide(g,g_image,M,tmp,divides,fail); // trial division (g) 434 if(fail) 435 return; 436 if(divides) 437 { 438 result = NN(c*g_image); 439 return; 440 } 463 441 } 464 442 } … … 470 448 continue; 471 449 472 if(isLess(dg_im, L, 2, mv)) // dg_im < L --> all previous points were unlucky 473 { 474 m = CanonicalForm(1); // reset 475 gm = 0; // reset 476 for(int i=2; i<=mv; i++) // tighten bound 477 L[i] = dg_im[i]; 478 } 450 // here: isLess(dg_im, L, 2, mv) --> all previous points were unlucky 451 m = CanonicalForm(1); // reset 452 gm = 0; // reset 453 for(int i=2; i<=mv; i++) // tighten bound 454 L[i] = dg_im[i]; 479 455 } 480 456 // we are out of evaluation points 481 457 fail = true; 482 458 } 459 460 CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G ) 461 { // f,g in Q(a)[x1,...,xn] 462 if(F.isZero()) 463 { 464 if(G.isZero()) 465 return G; // G is zero 466 if(G.inCoeffDomain()) 467 return CanonicalForm(1); 468 return G/Lc(G); // return monic G 469 } 470 if(G.isZero()) // F is non-zero 471 { 472 if(F.inCoeffDomain()) 473 return CanonicalForm(1); 474 return F/Lc(F); // return monic F 475 } 476 if(F.inCoeffDomain() || G.inCoeffDomain()) 477 return CanonicalForm(1); 478 // here: both NOT inCoeffDomain 479 CanonicalForm f, g, tmp, M, q, D, Dp, cl, newq, mipo; 480 int p, i; 481 int *bound, *other; // degree vectors 482 bool fail; 483 On( SW_RATIONAL ); // needed by bCommonDen 484 f = F * bCommonDen(F); 485 g = G * bCommonDen(G); 486 Variable a, b; 487 if(hasFirstAlgVar(f,a)) 488 { 489 if(hasFirstAlgVar(g,b)) 490 { 491 if(b.level() > a.level()) 492 a = b; 493 } 494 } 495 else 496 { 497 if(!hasFirstAlgVar(g,a))// both not in extension 498 { 499 Off( SW_RATIONAL ); 500 Off( SW_USE_QGCD ); 501 tmp = gcd( F, G ); 502 On( SW_USE_QGCD ); 503 return tmp; 504 } 505 } 506 // here: a is the biggest alg. var in f and g AND some of f,g is in extension 507 // (in the sequel b is used to swap alg/poly vars) 508 setReduce(a,false); // do not reduce expressions modulo mipo 509 tmp = getMipo(a); 510 M = tmp * bCommonDen(tmp); 511 // here: f, g in Z[a][x1,...,xn], M in Z[a] not necessarily monic 512 Off( SW_RATIONAL ); // needed by mod 513 // calculate upper bound for degree vector of gcd 514 int mv = f.level(); i = g.level(); 515 if(i > mv) 516 mv = i; 517 // here: mv is level of the largest variable in f, g 518 b = Variable(mv+1); 519 bound = new int[mv+1]; // 'bound' could be indexed from 0 to mv, but we will only use from 1 to mv 520 other = new int[mv+1]; 521 for(int i=1; i<=mv; i++) // initialize 'bound', 'other' with zeros 522 bound[i] = other[i] = 0; 523 bound = leadDeg(f,bound); // 'bound' is set the leading degree vector of f 524 other = leadDeg(g,other); 525 for(int i=1; i<=mv; i++) // entry at i=0 not visited 526 if(other[i] < bound[i]) 527 bound[i] = other[i]; 528 // now 'bound' is the smaller vector 529 cl = lc(M) * lc(f) * lc(g); 530 q = 1; 531 D = 0; 532 for( i=cf_getNumBigPrimes()-1; i>-1; i-- ) 533 { 534 p = cf_getBigPrime(i); 535 if( mod( cl, p ).isZero() ) // skip lc-bad primes 536 continue; 537 fail = false; 538 setCharacteristic(p); 539 mipo = mapinto(M); 540 mipo /= mipo.lc(); 541 // here: mipo is monic 542 tryBrownGCD( mapinto(f), mapinto(g), mipo, Dp, fail ); 543 Dp = reduce( Dp, mipo ); 544 setCharacteristic(0); 545 if( fail ) // mipo splits in char p 546 continue; 547 if( Dp.inCoeffDomain() ) // early termination 548 { 549 tryInvert(Dp,mipo,tmp,fail); // check if zero divisor 550 if(fail) 551 continue; 552 setReduce(a,true); 553 return CanonicalForm(1); 554 } 555 // here: Dp NOT inCoeffDomain 556 for(int i=1; i<=mv; i++) 557 other[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg) 558 other = leadDeg(Dp,other); 559 560 if(isEqual(bound, other, 1, mv)) // equal 561 { 562 chineseRemainder( D, q, replacevar( mapinto(Dp), a, b ), p, tmp, newq ); 563 // tmp = Dp mod p 564 // tmp = D mod q 565 // newq = p*q 566 q = newq; 567 if( D != tmp ) 568 D = tmp; 569 On( SW_RATIONAL ); 570 tmp = replacevar( Farey( D, q ), b, a ); // Farey and switch back to alg var 571 setReduce(a,true); // reduce expressions modulo mipo 572 On( SW_RATIONAL ); // needed by fdivides 573 if( fdivides( tmp, f ) && fdivides( tmp, g )) // trial division 574 { 575 Off( SW_RATIONAL ); 576 setReduce(a,true); 577 return tmp; 578 } 579 Off( SW_RATIONAL ); 580 setReduce(a,false); // do not reduce expressions modulo mipo 581 continue; 582 } 583 if( isLess(bound, other, 1, mv) ) // current prime unlucky 584 continue; 585 // here: isLess(other, bound, 1, mv) ) ==> all previous primes unlucky 586 q = p; 587 D = replacevar( mapinto(Dp), a, b ); // shortcut CRA // shortcut CRA 588 for(int i=1; i<=mv; i++) // tighten bound 589 bound[i] = other[i]; 590 } 591 // hopefully, we never reach this point 592 setReduce(a,true); 593 Off( SW_USE_QGCD ); 594 D = gcd( f, g ); 595 On( SW_USE_QGCD ); 596 return D; 597 } 598 599 600 int * leadDeg(const CanonicalForm & f, int *degs) 601 { // leading degree vector w.r.t. lex. monomial order x(i+1) > x(i) 602 // if f is in a coeff domain, the zero pointer is returned 603 // 'a' should point to an array of sufficient size level(f)+1 604 if(f.inCoeffDomain()) 605 return 0; 606 CanonicalForm tmp = f; 607 do 608 { 609 degs[tmp.level()] = tmp.degree(); 610 tmp = LC(tmp); 611 } 612 while(!tmp.inCoeffDomain()); 613 return degs; 614 } 615 616 617 bool isLess(int *a, int *b, int lower, int upper) 618 { // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i) 619 for(int i=upper; i>=lower; i--) 620 if(a[i] == b[i]) 621 continue; 622 else 623 return a[i] < b[i]; 624 return true; 625 } 626 627 628 bool isEqual(int *a, int *b, int lower, int upper) 629 { // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i) 630 for(int i=lower; i<=upper; i++) 631 if(a[i] != b[i]) 632 return false; 633 return true; 634 } 635 636 637 CanonicalForm firstLC(const CanonicalForm & f) 638 { // returns the leading coefficient (LC) of level <= 1 639 CanonicalForm ret = f; 640 while(ret.level() > 1) 641 ret = LC(ret); 642 return ret; 643 } 644 645 646 void tryCRA( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, const CanonicalForm & M, CanonicalForm & xnew, CanonicalForm & qnew, bool & fail ) 647 { // as CRA, but takes care of zero divisors 648 CanonicalForm tmp; 649 if(x1.level() <= 1 && x2.level() <= 1) // base case 650 { 651 tryExtgcd(q1,q2,M,tmp,xnew,qnew,fail); 652 if(fail) 653 return; 654 xnew = x1 + (x2-x1) * xnew * q1; 655 qnew = q1*q2; 656 xnew = mod(xnew,qnew); 657 return; 658 } 659 CanonicalForm tmp2; 660 xnew = 0; 661 qnew = q1 * q2; 662 // here: x1.level() > 1 || x2.level() > 1 663 if(x1.level() > x2.level()) 664 { 665 for(CFIterator i=x1; i.hasTerms(); i++) 666 { 667 if(i.exp() == 0) // const. term 668 { 669 tryCRA(i.coeff(),q1,x2,q2,M,tmp,tmp2,fail); 670 if(fail) 671 return; 672 xnew += tmp; 673 } 674 else 675 { 676 tryCRA(i.coeff(),q1,0,q2,M,tmp,tmp2,fail); 677 if(fail) 678 return; 679 xnew += tmp * power(x1.mvar(),i.exp()); 680 } 681 } 682 return; 683 } 684 // here: x1.level() <= x2.level() && ( x1.level() > 1 || x2.level() > 1 ) 685 if(x2.level() > x1.level()) 686 { 687 for(CFIterator j=x2; j.hasTerms(); j++) 688 { 689 if(j.exp() == 0) // const. term 690 { 691 tryCRA(x1,q1,j.coeff(),q2,M,tmp,tmp2,fail); 692 if(fail) 693 return; 694 xnew += tmp; 695 } 696 else 697 { 698 tryCRA(0,q1,j.coeff(),q2,M,tmp,tmp2,fail); 699 if(fail) 700 return; 701 xnew += tmp * power(x2.mvar(),j.exp()); 702 } 703 } 704 return; 705 } 706 // here: x1.level() == x2.level() && x1.level() > 1 && x2.level() > 1 707 CFIterator i = x1; 708 CFIterator j = x2; 709 while(i.hasTerms() || j.hasTerms()) 710 { 711 if(i.hasTerms()) 712 { 713 if(j.hasTerms()) 714 { 715 if(i.exp() == j.exp()) 716 { 717 tryCRA(i.coeff(),q1,j.coeff(),q2,M,tmp,tmp2,fail); 718 if(fail) 719 return; 720 xnew += tmp * power(x1.mvar(),i.exp()); 721 i++; j++; 722 } 723 else 724 { 725 if(i.exp() < j.exp()) 726 { 727 tryCRA(i.coeff(),q1,0,q2,M,tmp,tmp2,fail); 728 if(fail) 729 return; 730 xnew += tmp * power(x1.mvar(),i.exp()); 731 i++; 732 } 733 else // i.exp() > j.exp() 734 { 735 tryCRA(0,q1,j.coeff(),q2,M,tmp,tmp2,fail); 736 if(fail) 737 return; 738 xnew += tmp * power(x1.mvar(),j.exp()); 739 j++; 740 } 741 } 742 } 743 else // j is out of terms 744 { 745 tryCRA(i.coeff(),q1,0,q2,M,tmp,tmp2,fail); 746 if(fail) 747 return; 748 xnew += tmp * power(x1.mvar(),i.exp()); 749 i++; 750 } 751 } 752 else // i is out of terms 753 { 754 tryCRA(0,q1,j.coeff(),q2,M,tmp,tmp2,fail); 755 if(fail) 756 return; 757 xnew += tmp * power(x1.mvar(),j.exp()); 758 j++; 759 } 760 } 761 } 762 763 764 void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail ) 765 { // F, G are univariate polynomials (i.e. they have exactly one polynomial variable) 766 // F and G must have the same level AND level > 0 767 // we try to calculate gcd(F,G) = s*F + t*G 768 // if a zero divisor is encontered, 'fail' is set to one 769 // M is assumed to be monic 770 CanonicalForm P; 771 if(F.inCoeffDomain()) 772 { 773 tryInvert( F, M, P, fail ); 774 if(fail) 775 return; 776 result = 1; 777 s = P; t = 0; 778 return; 779 } 780 if(G.inCoeffDomain()) 781 { 782 tryInvert( G, M, P, fail ); 783 if(fail) 784 return; 785 result = 1; 786 s = 0; t = P; 787 return; 788 } 789 // here: both not inCoeffDomain 790 CanonicalForm inv, rem, tmp, u, v, q, sum=0; 791 if( F.degree() > G.degree() ) 792 { 793 P = F; result = G; s=v=0; t=u=1; 794 } 795 else 796 { 797 P = G; result = F; s=v=1; t=u=0; 798 } 799 Variable x = P.mvar(); 800 // here: degree(P) >= degree(result) 801 while(true) 802 { 803 tryInvert( Lc(result), M, inv, fail ); 804 if(fail) 805 return; 806 // here: Lc(result) is invertible modulo M 807 q = Lc(P)*inv*power( x, P.degree(x)-result.degree(x) ); 808 rem = reduce( P - q*result, M ); 809 if( rem.isZero() ) 810 { 811 s*=inv; 812 t*=inv; 813 result *= inv; // monify result 814 return; 815 } 816 sum += q; 817 if(result.degree(x) >= rem.degree(x)) 818 { 819 P=result; 820 result=rem; 821 tmp=u-sum*s; 822 u=s; 823 s=tmp; 824 tmp=v-sum*t; 825 v=t; 826 t=tmp; 827 sum = 0; // reset 828 } 829 else 830 P = rem; 831 } 832 } 833 834 835 static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ) 836 { // as 'content', but takes care of zero divisors 837 ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" ); 838 Variable y = f.mvar(); 839 if ( y == x ) 840 return trycf_content( f, 0, M, fail ); 841 if ( y < x ) 842 return f; 843 return swapvar( trycontent( swapvar( f, y, x ), y, M, fail ), y, x ); 844 } 845 846 847 static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ) 848 { // as vcontent, but takes care of zero divisors 849 ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" ); 850 if ( f.mvar() <= x ) 851 return trycontent( f, x, M, fail ); 852 CFIterator i; 853 CanonicalForm d = 0, e, ret; 854 for ( i = f; i.hasTerms() && ! d.isOne() && ! fail; i++ ) 855 { 856 e = tryvcontent( i.coeff(), x, M, fail ); 857 if(fail) 858 break; 859 tryBrownGCD( d, e, M, ret, fail ); 860 d = ret; 861 } 862 return d; 863 } 864 865 866 static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail ) 867 { // as cf_content, but takes care of zero divisors 868 if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) ) 869 { 870 CFIterator i = f; 871 CanonicalForm tmp = g, result; 872 while ( i.hasTerms() && ! tmp.isOne() && ! fail ) 873 { 874 tryBrownGCD( i.coeff(), tmp, M, result, fail ); 875 tmp = result; 876 i++; 877 } 878 return result; 879 } 880 return abs( f ); 881 } 882 883 884 static void tryDivide( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, CanonicalForm & result, bool & divides, bool & fail ) 885 { // M "univariate" monic polynomial 886 // f, g polynomials with coeffs modulo M. 887 // if f is divisible by g, 'divides' is set to 1 and 'result' == f/g mod M coefficientwise. 888 // 'fail' is set to 1, iff a zero divisor is encountered. 889 // divides==1 implies fail==0 890 // required: getReduce(M.mvar())==0 891 if(g.inBaseDomain()) 892 { 893 result = f/g; 894 divides = true; 895 return; 896 } 897 if(g.inCoeffDomain()) 898 { 899 tryInvert(g,M,result,fail); 900 if(fail) 901 return; 902 result = reduce(f*result, M); 903 divides = true; 904 return; 905 } 906 // here: g NOT inCoeffDomain 907 Variable x = g.mvar(); 908 if(f.degree(x) < g.degree(x)) 909 { 910 divides = false; 911 return; 912 } 913 // here: f.degree(x) > 0 and f.degree(x) >= g.degree(x) 914 CanonicalForm F = f; 915 CanonicalForm q, leadG = LC(g); 916 result = 0; 917 while(!F.isZero()) 918 { 919 tryDivide(F.LC(x),leadG,M,q,divides,fail); 920 if(fail || !divides) 921 return; 922 if(F.degree(x)<g.degree(x)) 923 { 924 divides = false; 925 return; 926 } 927 q *= power(x,F.degree(x)-g.degree(x)); 928 result += q; 929 F = reduce(F-q*g, M); 930 } 931 result = reduce(result, M); 932 divides = true; 933 } 934 483 935 484 936
Note: See TracChangeset
for help on using the changeset viewer.