polynomial.H

Go to the documentation of this file.
00001 // polynomial arithmetic
00002 // last change: 2004-09-13
00003 
00004 #ifndef POLYNOMIAL_HEADER_
00005 #define POLYNOMIAL_HEADER_
00006 
00012 #include <gmp.h>
00013 
00015 namespace polynomial
00016 {
00017 
00018 //#define DEBUG    /* for explicit DEBUGGING-sessions */
00019 //#define VERBOSE  /* be more verbose */
00020 
00021 // this define should be triggered by Makefile
00022 // #define USE_DFT /* enable use of discrete fourier transform */
00023 #if !defined(USE_DFT) && (CONTINUATION_METHOD==2)
00024  #define USE_DFT /* enable use of discrete fourier transform */
00025 #endif
00026 
00027 typedef mpz_t* TPolynom;
00028 typedef const mpz_t* TconstPolynom;
00029 /* A polynomial is defined by an array of mpz_t-coefficients:
00030    P(x)=a0*x^0+a1*x^1+...+a[k-1]*x^[k-1],
00031    stored as (a0,a1,a2,...,a[k-1]).
00032 */
00033 
00034 /* Hints for function calls:
00035 
00036  TPolynom denotes a pointer to an array of coefficients
00037  (which thereby defines a polynomial).
00038 
00039  As usual in C++, take respect to the following calling conventions:
00040 
00041  Parameter              Restrictions/Properties
00042  -------------------------------------------------------------
00043  mpz_t* p                mutable pointer, mutable data
00044  const mpz_t* p          mutable pointer, constant data
00045  mpz_t* const p          constant pointer, mutable data
00046  const mpz_t* const p    constant pointer, constant data
00047 
00048  "const TPolynom P" and "TPolynom const P" are (unfortunately) equivalent.
00049  Both define a constant pointer to a mutable polynomial!
00050 
00051  For this reason, I have defined an auxiliary datatype
00052  for constant polynomials: TconstPolynom
00053  So keep this in mind:
00054 
00055  Parameter              Restrictions/Properties
00056  ----------------------------------------------------------------
00057  TPolynom P              P mutable,     coefficients mutable
00058  const TPolynom P        P constant,    coefficients mutable
00059  TPolynom const P        P constant,    coefficients mutable
00060  TconstPolynom P         P mutable,     coefficients constant
00061  const TconstPolynom P   P constant,    coefficients constant
00062  TconstPolynom const P   P constant,    coefficients constant
00063 
00064 */
00065 
00066 
00075 class TTempPolynom : private ForbidAssignment
00076 {
00077 private:
00078   mpz_t* const data;
00079   const int _capacity;
00080 public:
00081   explicit TTempPolynom(const int n) : data(new mpz_t[n]), _capacity(n)
00082    {
00083      //cout << "allocate polynomial of size " << n << endl;
00084      for (int i=0; i<n; ++i) mpz_init(data[i]);
00085    }
00086   TTempPolynom(const int n, const int estimated_operand_size) : data(new mpz_t[n]), _capacity(n)
00087    {
00088      //cout << "allocate polynomial of size " << n << endl;
00089      for (int i=0; i<n; ++i) mpz_init2(data[i],estimated_operand_size);
00090    }
00091   ~TTempPolynom()
00092    {
00093      //cout << "dispose polynomial of size " << _capacity << endl;
00094      for (int i=_capacity-1; i>=0; --i) mpz_clear(data[i]);
00095      delete [] data;
00096    }
00097   int capacity() const { return _capacity; }
00098 
00099   //const mpz_t& operator[] (const unsigned int i) const { return data[i]; }
00100   //mpz_t& operator[] (const unsigned int i) { return data[i]; }
00101 
00102   // dangerous, but helpful:
00103   // remember: TPolynom will not live longer than TempPolynom!
00104   operator TPolynom() const { return data; }
00105 };
00106 
00107 
00114 void print (const TconstPolynom P, int k);
00115 
00116 
00128 void eval(mpz_t res, const TconstPolynom P, const int k, const mpz_t x, const mpz_t m);
00129 // berechnet mit dem Hornerschema res = P(x) mod m
00130 
00131 
00132 #ifdef USE_DFT
00133  // fast discrete fourier transformation
00134  // (will allocate internal temporary memory, which you may want to release)
00135 
00142 void clear_dft_tempmemory() ;
00143 
00144 #endif
00145 
00146 
00161 int classic_mul(const TPolynom Pr, const int kr,
00162                 const TconstPolynom P1, const int k1,
00163                 const TconstPolynom P2, const int k2);
00164 // Pres = P1*P2, &Pres must be different from &P1,&P2
00165 // returns degree of the resulting polynomial
00166 // complexity: O(k1*k2)
00167 // (classical method, implemented alternatively to Karatsuba for small polynomials)
00168 
00169 
00185 int classic_mul(const TPolynom Pr, const int kr,
00186                 const TconstPolynom P1, const int k1,
00187                 const TconstPolynom P2, const int k2, const mpz_t m);
00188 // Pres = P1*P2, &Pres must be different from &P1,&P2
00189 // returns degree of the resulting polynomial
00190 // complexity: O(k1*k2)
00191 // (classical method, implemented alternatively to Karatsuba for small polynomials)
00192 
00193 
00194 
00207 int square(const TPolynom R, const int kR, const TconstPolynom P, const int k, const mpz_t m);
00208 // R = P^2, &R must be different from &P
00209 // returns degree of resulting polynomial
00210 // complexity: O(k^1.59) -> Karatsuba
00211 
00212 
00224 int square(const TPolynom R, const int kR, const TconstPolynom P, const int k);
00225 // R = P^2, &R must be different from &P
00226 // returns degree of resulting polynomial
00227 // complexity: O(k^1.59) -> Karatsuba
00228 
00229 
00246 int mul(const TPolynom R, const int kR,
00247         TconstPolynom P1, int k1,
00248         TconstPolynom P2, int k2, const mpz_t m);
00249 // Pres = P1*P2, &R must be different from &P1,&P2
00250 // returns degree of the resulting polynomial
00251 // complexity: O(max(k1,k2)^1.59) -> Karatsuba
00252 // resp. complexity: O((k1+k2)*ld(k1+k2)) -> using (optimal) dft
00253 
00254 
00269 int mul(const TPolynom R, const int kR,
00270         TconstPolynom P1, int k1,
00271         TconstPolynom P2, int k2);
00272 // Pres = P1*P2, &R must be different from &P1,&P2
00273 // returns degree of resulting polynomial
00274 // complexity: O(max(k1,k2)^1.59) -> Karatsuba
00275 
00276 
00288 void reciprocal(TPolynom R, int &kR, const TconstPolynom P, const int k, const mpz_t m, const unsigned int scale=0);
00289 // computes the reciprocal polynomial of P,
00290 // R must provide enough memory!
00291 // the given polynomial will be scaled using x^scale as multiplier,
00292 // thereby shifting the coefficients by scale places
00293 
00294 
00312 void classic_div(TPolynom Q, int &kQ, TPolynom R, int &kR,
00313          const TconstPolynom P1, int k1,
00314          const TconstPolynom P2, int k2, const mpz_t m) __attribute__ ((deprecated));
00315 
00316 
00331 void classic_mod(TPolynom R, int &kR,
00332             const TconstPolynom P1, int k1,
00333             const TconstPolynom P2, int k2, const mpz_t m);
00334 // Remainder of polynomial division, O(n^2)
00335 // returns P1 mod P2 in R
00336 
00337 
00351 void div(TPolynom Q, int &kQ,
00352          const TconstPolynom P1, const int k1,
00353          const TconstPolynom P2, const int k2, const mpz_t m);
00354 // (fast) polynomial division by multiplying with the reciprocal polynomial
00355 
00356 
00371 void mod(TPolynom R, int &kR,
00372          const TconstPolynom P1, int k1,
00373          const TconstPolynom P2, int k2, const mpz_t m);
00374 // polynomial remainder, fast(er) method
00375 // returns P1 modulo P2 in R
00376 /* asymptotically faster than the "naive modulo", because we can make use of
00377    fast multiplication algorithms. */
00378 
00379 
00391 void multipoint_eval(mpz_t* res,
00392                      const TconstPolynom P, const int k, 
00393                      const mpz_t* const array_of_arguments, const int size,
00394                      const mpz_t m);
00395 
00396 
00407 int construct_polynomial_from_roots
00408       (TPolynom &res,
00409        const mpz_t* const roots_array, const int size,
00410        const mpz_t m);
00411   // task:
00412   // Creates a new polynomial using the zeros given in "roots_array";
00413   // this polynomial will be placed in "res" and its size will be returned.
00414   // To avoid memory leaks (due to erroneous calls), we expect that
00415   // "res" is initially an NULL-pointer.
00416   // additional remark:
00417   // Sure, it would be possible to return this pointer instead of using a reference
00418   // parameter, but what if you forget to delete it later? -- Using this technique,
00419   // the programmer is at least urged to provide a valid container for our data!
00420 
00421 } // namespace polynomial
00422 
00423 #endif /* POLYNOMIAL_HEADER_ */

Generated on Wed Nov 7 23:29:26 2007 for Qsieve by  doxygen 1.5.4