- Timestamp:
- Jul 6, 2011, 4:41:07 PM (12 years ago)
- Branches:
- (u'spielwiese', '91e5db82acc17434e4062bcfa44e6efa7d41fd30')
- Children:
- 6c19d854882ab99fd19b9b972a32606106c2f2ee
- Parents:
- 2d3091c7bb239cd4787574560ab475ac88621da7
- git-author:
- Frank Seelisch <seelisch@mathematik.uni-kl.de>2011-07-06 16:41:07+02:00
- git-committer:
- Mohamed Barakat <mohamed.barakat@rwth-aachen.de>2011-11-09 12:39:12+01:00
- Location:
- libpolys
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
libpolys/polys/ext_fields/transext.cc
r2d3091c r06df101 7 7 * transcendental variables t_1, ..., t_s, where s >= 1. 8 8 * Denoting the implemented coeffs object by cf, then these numbers 9 * are represented as quotients of polynomials in the polynomial 10 * ring K[t_1, .., t_s] represented by cf->extring. 9 * are represented as quotients of polynomials living in the 10 * polynomial ring K[t_1, .., t_s] represented by cf->extring. 11 * 12 * An element of K(t_1, .., t_s) may have numerous representations, 13 * due to the possibility of common polynomial factors in the 14 * numerator and denominator. This problem is handled by a 15 * cancellation heuristic: Each number "knows" its complexity 16 * which is 0 if and only if common factors have definitely been 17 * cancelled, and some positive integer otherwise. 18 * Each arithmetic operation of two numbers with complexities c1 19 * and c2 will result in a number of complexity c1 + c2 + some 20 * penalty (specific for each arithmetic operation; see constants 21 * in the *.h file). Whenever the resulting complexity exceeds a 22 * certain threshold (see constant in the *.h file), then the 23 * cancellation heuristic will call 'factory' to compute the gcd 24 * and cancel it out in the given number. (This definite cancel- 25 * lation will also be performed at the beginning of ntWrite, 26 * ensuring that any output is free of common factors. 27 * For the special case of K = Q (i.e., when computing over the 28 * rationals), this definite cancellation procedure will also take 29 * care of nested fractions: If there are fractional coefficients 30 * in the numerator or denominator of a number, then this number 31 * is being replaced by a quotient of two polynomials over Z, or 32 * - if the denominator is a constant - by a polynomial over Q. 11 33 */ 12 34 … … 71 93 void heuristicGcdCancellation(number a, const coeffs cf); 72 94 void definiteGcdCancellation(number a, const coeffs cf, 73 BOOLEAN skipSimpleTests); 95 BOOLEAN simpleTestsHaveAlreadyBeenPerformed); 96 void handleNestedFractionsOverQ(fraction f, const coeffs cf); 74 97 75 98 #ifdef LDEBUG … … 529 552 } 530 553 554 /* assumes that cf represents the rationals, i.e. Q, and will only 555 be called in that case; 556 assumes furthermore that f != NULL and that the denominator of f != 1; 557 generally speaking, this method removes denominators in the rational 558 coefficients of the numerator and denominator of 'a'; 559 more concretely, the following normalizations will be performed, 560 where t^alpha denotes a monomial in the transcendental variables t_k 561 (1) if 'a' is of the form 562 (sum_alpha a_alpha/b_alpha * t^alpha) 563 ------------------------------------- 564 (sum_beta c_beta/d_beta * t^beta) 565 with integers a_alpha, b_alpha, c_beta, d_beta, then both the 566 numerator and the denominator will be multiplied by the LCM of 567 the b_alpha's and the d_beta's (if this LCM is != 1), 568 (2) if 'a' is - e.g. after having performed step (1) - of the form 569 (sum_alpha a_alpha * t^alpha) 570 ----------------------------- 571 (sum_beta c_beta * t^beta) 572 with integers a_alpha, c_beta, and with a non-constant denominator, 573 then both the numerator and the denominator will be divided by the 574 GCD of the a_alpha's and the c_beta's (if this GCD is != 1), 575 (3) if 'a' is - e.g. after having performed steps (1) and (2) - of the 576 form 577 (sum_alpha a_alpha * t^alpha) 578 ----------------------------- 579 c 580 with integers a_alpha, and c != 1, then 'a' will be replaced by 581 (sum_alpha a_alpha/c * t^alpha); 582 this procedure does not alter COM(f) (this has to be done by the 583 calling procedure); 584 modifies f */ 585 void handleNestedFractionsOverQ(fraction f, const coeffs cf) 586 { 587 assume(nCoeff_is_Q(ntCoeffs)); 588 assume(!IS0(f)); 589 assume(!DENIS1(f)); 590 591 if (!p_IsConstant(DEN(f), ntRing)) 592 { /* step (1); see documentation of this procedure above */ 593 number lcmOfDenominators = n_Init(1, ntCoeffs); 594 number c; number tmp; 595 poly p = NUM(f); 596 /* careful when using n_Lcm!!! It computes the lcm of the numerator 597 of the 1st argument and the denominator of the 2nd!!! */ 598 while (p != NULL) 599 { 600 c = p_GetCoeff(p, ntRing); 601 tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs); 602 n_Delete(&lcmOfDenominators, ntCoeffs); 603 lcmOfDenominators = tmp; 604 pIter(p); 605 } 606 p = DEN(f); 607 while (p != NULL) 608 { 609 c = p_GetCoeff(p, ntRing); 610 tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs); 611 n_Delete(&lcmOfDenominators, ntCoeffs); 612 lcmOfDenominators = tmp; 613 pIter(p); 614 } 615 if (!n_IsOne(lcmOfDenominators, ntCoeffs)) 616 { /* multiply NUM(f) and DEN(f) with lcmOfDenominators */ 617 NUM(f) = p_Mult_nn(NUM(f), lcmOfDenominators, ntRing); 618 DEN(f) = p_Mult_nn(DEN(f), lcmOfDenominators, ntRing); 619 } 620 n_Delete(&lcmOfDenominators, ntCoeffs); 621 if (!p_IsConstant(DEN(f), ntRing)) 622 { /* step (2); see documentation of this procedure above */ 623 p = NUM(f); 624 number gcdOfCoefficients = n_Copy(p_GetCoeff(p, ntRing), ntCoeffs); 625 pIter(p); 626 while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs))) 627 { 628 c = p_GetCoeff(p, ntRing); 629 tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs); 630 n_Delete(&gcdOfCoefficients, ntCoeffs); 631 gcdOfCoefficients = tmp; 632 pIter(p); 633 } 634 p = DEN(f); 635 while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs))) 636 { 637 c = p_GetCoeff(p, ntRing); 638 tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs); 639 n_Delete(&gcdOfCoefficients, ntCoeffs); 640 gcdOfCoefficients = tmp; 641 pIter(p); 642 } 643 if (!n_IsOne(gcdOfCoefficients, ntCoeffs)) 644 { /* divide NUM(f) and DEN(f) by gcdOfCoefficients */ 645 number inverseOfGcdOfCoefficients = n_Invers(gcdOfCoefficients, 646 ntCoeffs); 647 NUM(f) = p_Mult_nn(NUM(f), inverseOfGcdOfCoefficients, ntRing); 648 DEN(f) = p_Mult_nn(DEN(f), inverseOfGcdOfCoefficients, ntRing); 649 n_Delete(&inverseOfGcdOfCoefficients, ntCoeffs); 650 } 651 n_Delete(&gcdOfCoefficients, ntCoeffs); 652 } 653 } 654 if (p_IsConstant(DEN(f), ntRing) && 655 (!n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))) 656 { /* step (3); see documentation of this procedure above */ 657 number inverseOfDen = n_Invers(p_GetCoeff(DEN(f), ntRing), ntCoeffs); 658 NUM(f) = p_Mult_nn(NUM(f), inverseOfDen, ntRing); 659 n_Delete(&inverseOfDen, ntCoeffs); 660 p_Delete(&DEN(f), ntRing); 661 DEN(f) = NULL; 662 } 663 664 /* Now, due to the above computations, DEN(f) may have become the 665 1-polynomial which needs to be represented by NULL: */ 666 if ((DEN(f) != NULL) && 667 p_IsConstant(DEN(f), ntRing) && 668 n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs)) 669 { 670 p_Delete(&DEN(f), ntRing); DEN(f) = NULL; 671 } 672 } 673 531 674 /* modifies a */ 532 675 void heuristicGcdCancellation(number a, const coeffs cf) … … 553 696 /* modifies a */ 554 697 void definiteGcdCancellation(number a, const coeffs cf, 555 BOOLEAN s kipSimpleTests)698 BOOLEAN simpleTestsHaveAlreadyBeenPerformed) 556 699 { 557 700 ntTest(a); … … 559 702 fraction f = (fraction)a; 560 703 561 if (!s kipSimpleTests)704 if (!simpleTestsHaveAlreadyBeenPerformed) 562 705 { 563 706 if (IS0(a)) return; … … 574 717 } 575 718 576 #ifdef HAVE_FACTORY 577 /* singclap_gcd destroys its arguments . We hence need copies: */719 #ifdef HAVE_FACTORY 720 /* singclap_gcd destroys its arguments; we hence need copies: */ 578 721 poly pNum = p_Copy(NUM(f), ntRing); 579 722 poly pDen = p_Copy(DEN(f), ntRing); 723 724 /* Note that, over Q, singclap_gcd will remove the denominators in all 725 rational coefficients of pNum and pDen, before starting to compute 726 the gcd. Thus, we do not need to ensure that the coefficients of 727 pNum and pDen live in Z; they may well be elements of Q\Z. */ 580 728 poly pGcd = singclap_gcd(pNum, pDen, cf->extRing); 581 729 if (p_IsConstant(pGcd, ntRing) && 582 730 n_IsOne(p_GetCoeff(pGcd, ntRing), ntCoeffs)) 583 { 584 /* gcd = 1; nothing to cancel */ 731 { /* gcd = 1; nothing to cancel; 732 Suppose the given rational function field is over Q. Although the 733 gcd is 1, we may have produced fractional coefficients in NUM(f), 734 DEN(f), or both, due to previous arithmetics. The next call will 735 remove those nested fractions, in case there are any. */ 736 if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf); 585 737 } 586 738 else 587 { 588 poly newNum = singclap_pdivide(NUM(f), pGcd, ntRing); 589 p_Delete(&NUM(f), ntRing); 590 NUM(f) = newNum; 591 poly newDen = singclap_pdivide(DEN(f), pGcd, ntRing); 739 { /* We divide both NUM(f) and DEN(f) by the gcd which is known 740 to be != 1. */ 741 poly newNum = singclap_pdivide(NUM(f), pGcd, ntRing); 742 p_Delete(&NUM(f), ntRing); 743 NUM(f) = newNum; 744 poly newDen = singclap_pdivide(DEN(f), pGcd, ntRing); 745 p_Delete(&DEN(f), ntRing); 746 DEN(f) = newDen; 747 if (p_IsConstant(DEN(f), ntRing) && 748 n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs)) 749 { 750 /* DEN(f) = 1 needs to be represented by NULL! */ 592 751 p_Delete(&DEN(f), ntRing); 593 if (p_IsConstant(newDen, ntRing) && 594 n_IsOne(p_GetCoeff(newDen, ntRing), ntCoeffs)) 595 { 596 /* newDen = 1 needs to be represented by NULL */ 597 p_Delete(&newDen, ntRing); 598 newDen = NULL; 599 } 600 DEN(f) = newDen; 752 newDen = NULL; 753 } 754 else 755 { /* Note that over Q, by cancelling the gcd, we may have produced 756 fractional coefficients in NUM(f), DEN(f), or both. The next 757 call will remove those nested fractions, in case there are 758 any. */ 759 if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf); 760 } 601 761 } 602 762 COM(f) = 0; -
libpolys/polys/ext_fields/transext.h
r2d3091c r06df101 9 9 * transcendental variables t_1, ..., t_s, where s >= 1. 10 10 * Denoting the implemented coeffs object by cf, then these numbers 11 * are represented as quotients of polynomials in the polynomial 12 * ring K[t_1, .., t_s] represented by cf->extring. 11 * are represented as quotients of polynomials living in the 12 * polynomial ring K[t_1, .., t_s] represented by cf->extring. 13 * 14 * An element of K(t_1, .., t_s) may have numerous representations, 15 * due to the possibility of common polynomial factors in the 16 * numerator and denominator. This problem is handled by a 17 * cancellation heuristic: Each number "knows" its complexity 18 * which is 0 if and only if common factors have definitely been 19 * cancelled, and some positive integer otherwise. 20 * Each arithmetic operation of two numbers with complexities c1 21 * and c2 will result in a number of complexity c1 + c2 + some 22 * penalty (specific for each arithmetic operation; see constants 23 * in the *.h file). Whenever the resulting complexity exceeds a 24 * certain threshold (see constant in the *.h file), then the 25 * cancellation heuristic will call 'factory' to compute the gcd 26 * and cancel it out in the given number. (This definite cancel- 27 * lation will also be performed at the beginning of ntWrite, 28 * ensuring that any output is free of common factors. 29 * For the special case of K = Q (i.e., when computing over the 30 * rationals), this definite cancellation procedure will also take 31 * care of nested fractions: If there are fractional coefficients 32 * in the numerator or denominator of a number, then this number 33 * is being replaced by a quotient of two polynomials over Z, or 34 * - if the denominator is a constant - by a polynomial over Q. 13 35 */ 14 36 -
libpolys/tests/coeffs_test.h
r2d3091c r06df101 481 481 setGMPFloatDigits( 10, 5 ); // Init global variables in mpr_complex.cc for gmp_float's... // Note that this seems also to be required for Z_2^m (and Zn?)!???? 482 482 simple(n_long_C); 483 } 484 485 486 // polynomial rings needed for extentions: n_algExt, n_transExt ! 487 483 } 484 485 void test_Q_special() 486 { 487 const coeffs cf = nInitChar(n_Q, NULLp); 488 489 if (cf == NULLp) 490 clog << ( "Test: could not get this coeff. domain" ); 491 492 TS_ASSERT_DIFFERS(cf->cfCoeffWrite, NULLp); 493 494 if (cf->cfCoeffWrite != NULL ) 495 { 496 clog << "Coeff-domain: " << endl; 497 n_CoeffWrite(cf); PrintLn(); 498 } 499 500 number q1 = n_Init(21, cf); 501 number q2 = n_Init(2, cf); 502 number q3 = n_Div(q1, q2, cf); 503 number q4 = n_Init(30, cf); 504 number q5 = n_Mult(q3, q4, cf); 505 TS_ASSERT(n_Test(q5, cf)); 506 Print("21/2 * 30 = %d\n", n_Int(q5, cf)); 507 TS_ASSERT(n_Test(q5, cf)); 508 n_Delete(&q1, cf); 509 n_Delete(&q2, cf); 510 n_Delete(&q3, cf); 511 n_Delete(&q4, cf); 512 n_Delete(&q5, cf); 513 } 488 514 }; 489 515 -
libpolys/tests/polys_test.h
r2d3091c r06df101 220 220 { 221 221 poly t = p_ISet(c, r); 222 if (exp > 0) { p_SetExp(t, i, exp, r); p_Setm(t, r); } 223 p = p_Add_q(p, t, r); 224 } 225 /* assumes that r is over Q; 226 replaces p by p + c1 / c2 * var(i)^exp (in-place); 227 expects exp >= 0, and c2 != 0 */ 228 void plusTermOverQ(poly &p, int c1, int c2, int i, int exp, const ring r) 229 { 230 number c1AsN = n_Init(c1, r->cf); 231 number c2AsN = n_Init(c2, r->cf); 232 number c = n_Div(c1AsN, c2AsN, r->cf); 233 poly t = p_ISet(1, r); p_SetCoeff(t, c, r); 222 234 if (exp > 0) { p_SetExp(t, i, exp, r); p_Setm(t, r); } 223 235 p = p_Add_q(p, t, r); … … 2493 2505 poly theProduct = p_Mult_q(entry, factor, s); 2494 2506 p_Write(theProduct, s); 2495 clog << " ending multiplication..." << endl;2507 clog << "...ending multiplication" << endl; 2496 2508 n_Delete(&qfactorAsN, cf); p_Delete(&theProduct, s); 2497 2509 … … 2508 2520 /* The following multiplication + output of the product is very slow 2509 2521 in the svn/trunk SINGULAR version; see trac ticket #308. 2510 Here, in the Spielwiese, the result is instantaneous !*/2522 Here, in the Spielwiese, the result is instantaneous. */ 2511 2523 theProduct = p_Mult_q(entry, factor, s); 2512 2524 p_Write(theProduct, s); 2513 clog << " ending very special multiplication..." << endl;2525 clog << "...ending very special multiplication" << endl; 2514 2526 n_Delete(&qfactorAsN, cf); p_Delete(&theProduct, s); 2527 2528 rDelete(s); // kills 'cf' and 'r' as well 2529 } 2530 void test_Q_Ext_s_t_NestedFractions() 2531 { 2532 clog << "Start by creating Q[s, t]..." << endl; 2533 2534 char* n[] = {"s", "t"}; 2535 ring r = rDefault( 0, 2, n); // Q[s, t] 2536 TS_ASSERT_DIFFERS( r, NULLp ); 2537 2538 PrintRing(r); 2539 2540 TS_ASSERT( rField_is_Domain(r) ); 2541 TS_ASSERT( rField_is_Q(r) ); 2542 2543 TS_ASSERT( !rField_is_Zp(r) ); 2544 TS_ASSERT( !rField_is_Zp(r, 17) ); 2545 2546 TS_ASSERT_EQUALS( rVar(r), 2); 2547 2548 n_coeffType type = nRegister(n_transExt, ntInitChar); 2549 TS_ASSERT(type == n_transExt); 2550 2551 TransExtInfo extParam; 2552 extParam.r = r; 2553 2554 clog << "Next create the rational function field Q(s, t)..." << endl; 2555 2556 const coeffs cf = nInitChar(type, &extParam); // Q(s, t) 2557 2558 if( cf == NULL ) 2559 TS_FAIL("Could not get needed coeff. domain"); 2560 2561 TS_ASSERT_DIFFERS( cf->cfCoeffWrite, NULLp ); 2562 2563 if( cf->cfCoeffWrite != NULL ) 2564 { 2565 clog << "Coeff-domain: " << endl; 2566 n_CoeffWrite(cf); PrintLn(); 2567 } 2568 2569 TS_ASSERT( !nCoeff_is_algExt(cf) ); 2570 TS_ASSERT( nCoeff_is_transExt(cf) ); 2571 2572 clog << "Finally create the polynomial ring Q(s, t)[x, y, z]..." 2573 << endl; 2574 2575 char* m[] = {"x", "y", "z"}; 2576 ring s = rDefault(cf, 3, m); // Q(s, t)[x, y, z] 2577 TS_ASSERT_DIFFERS(s, NULLp); 2578 2579 PrintRing(s); 2580 2581 TS_ASSERT( rField_is_Domain(s) ); 2582 TS_ASSERT( !rField_is_Q(s) ); 2583 TS_ASSERT( !rField_is_Zp(s) ); 2584 TS_ASSERT( !rField_is_Zp(s, 11) ); 2585 TS_ASSERT( !rField_is_Zp(s, 17) ); 2586 TS_ASSERT( !rField_is_GF(s) ); 2587 TS_ASSERT( rField_is_Extension(s) ); 2588 TS_ASSERT( !rField_is_GF(s, 25) ); 2589 TS_ASSERT_EQUALS(rVar(s), 3); 2590 2591 /* test 1 for nested fractions, i.e. fractional coefficients: */ 2592 poly v1 = NULL; 2593 plusTermOverQ(v1, 21, 2, 1, 1, cf->extRing); // 21/2*s 2594 plusTermOverQ(v1, 14, 3, 1, 0, cf->extRing); // 21/2*s + 14/3 2595 number v1_n = toFractionNumber(v1, cf); 2596 PrintSized(v1_n, cf); 2597 poly v2 = NULL; 2598 plusTermOverQ(v2, 7, 5, 1, 1, cf->extRing); // 7/5*s 2599 plusTermOverQ(v2, -49, 6, 2, 1, cf->extRing); // 7/5*s - 49/6*t 2600 number v2_n = toFractionNumber(v2, cf); 2601 PrintSized(v2_n, cf); 2602 number v3_n = n_Div(v1_n, v2_n, cf); // (45*s + 20) / (6s - 35*t) 2603 PrintSized(v3_n, cf); 2604 n_Delete(&v1_n, cf); n_Delete(&v2_n, cf); n_Delete(&v3_n, cf); 2605 2606 /* test 2 for nested fractions, i.e. fractional coefficients: */ 2607 v1 = NULL; 2608 plusTermOverQ(v1, 1, 2, 1, 1, cf->extRing); // 1/2*s 2609 plusTermOverQ(v1, 1, 1, 1, 0, cf->extRing); // 1/2*s + 1 2610 v2 = NULL; 2611 plusTermOverQ(v2, 1, 1, 1, 1, cf->extRing); // s 2612 plusTermOverQ(v2, 2, 3, 2, 1, cf->extRing); // s + 2/3*t 2613 poly v3 = p_Mult_q(v1, v2, cf->extRing); // (1/2*s + 1) * (s + 2/3*t) 2614 number v_n = toFractionNumber(v3, cf); 2615 PrintSized(v_n, cf); 2616 poly w1 = NULL; 2617 plusTermOverQ(w1, 1, 2, 1, 1, cf->extRing); // 1/2*s 2618 plusTermOverQ(w1, 1, 1, 1, 0, cf->extRing); // 1/2*s + 1 2619 poly w2 = NULL; 2620 plusTermOverQ(w2, -7, 5, 1, 0, cf->extRing); // -7/5 2621 poly w3 = p_Mult_q(w1, w2, cf->extRing); // (1/2*s + 1) * (-7/5) 2622 number w_n = toFractionNumber(w3, cf); 2623 PrintSized(w_n, cf); 2624 number z_n = n_Div(v_n, w_n, cf); // -5/7*s - 10/21*t 2625 PrintSized(z_n, cf); 2626 n_Delete(&v_n, cf); n_Delete(&w_n, cf); n_Delete(&z_n, cf); 2515 2627 2516 2628 rDelete(s); // kills 'cf' and 'r' as well
Note: See TracChangeset
for help on using the changeset viewer.