source: git/factory/cf_chinese.cc @ 6c5d86

spielwiese
Last change on this file since 6c5d86 was d57f19, checked in by Jens Schmidt <schmidt@…>, 26 years ago
* cf_chinese.cc (chineseRemainder( const CanonicalForm & ...)): completely rewritten * cf_chinese.cc (chineseRemainder): debug output added * cf_chinese.cc (chineseRemainder( const CFArray & ...)): slightly speeded up * cf_gcd.cc (iextgcd, igcd): functions removed. All references replaced by `bextgcd()' and `bgcd()', resp. git-svn-id: file:///usr/local/Singular/svn/trunk@1112 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 4.4 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: cf_chinese.cc,v 1.9 1998-02-02 08:57:29 schmidt Exp $ */
3
4//{{{ docu
5//
6// cf_chinese.cc - algorithms for chinese remaindering.
7//
8// Used by: cf_gcd.cc, cf_linsys.cc, sm_util.cc
9//
10// Header file: cf_algorithm.h
11//
12//}}}
13
14#include <config.h>
15
16#include "assert.h"
17#include "debug.h"
18
19#include "canonicalform.h"
20
21//{{{ void chineseRemainder ( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew )
22//{{{ docu
23//
24// chineseRemainder - integer chinese remaindering.
25//
26// Calculate xnew such that xnew=x1 (mod q1) and xnew=x2 (mod q2)
27// and qnew = q1*q2.  q1 and q2 should be positive integers,
28// pairwise prime, x1 and x2 should be polynomials with integer
29// coefficients.  If x1 and x2 are polynomials with positive
30// coefficients, the result is guaranteed to have positive
31// coefficients, too.
32//
33// Note: This algorithm is optimized for the case q1>>q2.
34//
35// This is a standard algorithm.  See, for example,
36// Geddes/Czapor/Labahn - 'Algorithms for Computer Algebra',
37// par. 5.6 and 5.8, or the article of M. Lauer - 'Computing by
38// Homomorphic Images' in B. Buchberger - 'Computer Algebra -
39// Symbolic and Algebraic Computation'.
40//
41// Note: Be sure you are calculating in Z, and not in Q!
42//
43//}}}
44void
45chineseRemainder ( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew )
46{
47    DEBINCLEVEL( cerr, "chineseRemainder" );
48
49    DEBOUTLN( cerr, "log(q1) = " << q1.ilog2() );
50    DEBOUTLN( cerr, "log(q2) = " << q2.ilog2() );
51
52    // We calculate xnew as follows:
53    //     xnew = v1 + v2 * q1
54    // where
55    //     v1 = x1 (mod q1)
56    //     v2 = (x2-v1)/q1 (mod q2)  (*)
57    //
58    // We do one extra test to check whether x2-v1 vanishes (mod
59    // q2) in (*) since it is not costly and may save us
60    // from calculating the inverse of q1 (mod q2).
61    //
62    // u: v1 (mod q2)
63    // d: x2-v1 (mod q2)
64    // s: 1/q1 (mod q2)
65    //
66    CanonicalForm v2, v1;
67    CanonicalForm u, d, s, dummy;
68
69    v1 = mod( x1, q1 );
70    u = mod( v1, q2 );
71    d = mod( x2-u, q2 );
72    if ( d.isZero() ) {
73        xnew = v1;
74        qnew = q1 * q2;
75        return;
76    }
77    (void)bextgcd( q1, q2, s, dummy );
78    v2 = mod( d*s, q2 );
79    xnew = v1 + v2*q1;
80
81    // After all, calculate new modulus.  It is important that
82    // this is done at the very end of the algorithm, since q1
83    // and qnew may refer to the same object (same is true for x1
84    // and xnew).
85    qnew = q1 * q2;
86
87    DEBDECLEVEL( cerr, "chineseRemainder" );
88}
89//}}}
90
91//{{{ void chineseRemainder ( const CFArray & x, const CFArray & q, CanonicalForm & xnew, CanonicalForm & qnew )
92//{{{ docu
93//
94// chineseRemainder - integer chinese remaindering.
95//
96// Calculate xnew such that xnew=x[i] (mod q[i]) and qnew is the
97// product of all q[i].  q[i] should be positive integers,
98// pairwise prime.  x[i] should be polynomials with integer
99// coefficients.  If all coefficients of all x[i] are positive
100// integers, the result is guaranteed to have positive
101// coefficients, too.
102//
103// This is a standard algorithm, too, except for the fact that we
104// use a divide-and-conquer method instead of a linear approach
105// to calculate the remainder.
106//
107// Note: Be sure you are calculating in Z, and not in Q!
108//
109//}}}
110void
111chineseRemainder ( const CFArray & x, const CFArray & q, CanonicalForm & xnew, CanonicalForm & qnew )
112{
113    DEBINCLEVEL( cerr, "chineseRemainder( ... CFArray ... )" );
114
115    ASSERT( x.min() == q.min() && x.size() == q.size(), "incompatible arrays" );
116    CFArray X(x), Q(q);
117    int i, j, n = x.size(), start = x.min();
118
119    DEBOUTLN( cerr, "array size = " << n );
120
121    while ( n != 1 ) {
122        i = j = start;
123        while ( i < start + n - 1 ) {
124            // This is a little bit dangerous: X[i] and X[j] (and
125            // Q[i] and Q[j]) may refer to the same object.  But
126            // xnew and qnew in the above function are modified
127            // at the very end of the function, so we do not
128            // modify x1 and q1, resp., by accident.
129            chineseRemainder( X[i], Q[i], X[i+1], Q[i+1], X[j], Q[j] );
130            i += 2;
131            j++;
132        }
133
134        if ( n & 1 ) {
135            X[j] = X[i];
136            Q[j] = Q[i];
137        }
138        // Maybe we would get some memory back at this point if
139        // we would set X[j+1, ..., n] and Q[j+1, ..., n] to zero
140        // at this point?
141
142        n = ( n + 1) / 2;
143    }
144    xnew = X[start];
145    qnew = Q[q.min()];
146
147    DEBDECLEVEL( cerr, "chineseRemainder( ... CFArray ... )" );
148}
149//}}}
Note: See TracBrowser for help on using the repository browser.