diff options
author | Kevin Ryde <user42@zip.com.au> | 2001-11-27 00:07:39 +0100 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2001-11-27 00:07:39 +0100 |
commit | c88cc29e8968422c2903d5b59076f0a5e835a1fd (patch) | |
tree | e32a6d1f45636e7cdbb9dcc62363cd376b52d9a8 /gmpxx.h | |
parent | 46ab2ebea42a7cdc261fee350b05999bc1b34113 (diff) | |
download | gmp-c88cc29e8968422c2903d5b59076f0a5e835a1fd.tar.gz |
2001-10-09 Gerardo Ballabio <ballabio@sissa.it>
* gmpxx.h, mpfrxx.h: Various updates and improvements.
Diffstat (limited to 'gmpxx.h')
-rw-r--r-- | gmpxx.h | 3876 |
1 files changed, 2113 insertions, 1763 deletions
@@ -1,4 +1,4 @@ -/* gmpxx.h -- C++ class wrapper for GMP types. +/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*- Copyright 2001 Free Software Foundation, Inc. @@ -19,20 +19,35 @@ along with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* the C++ compiler must implement the following features: + - member templates + - partial specialization of templates + - namespace support + for g++, this means version 2.91 or higher + for other compilers, I don't know */ #ifdef __GNUC__ -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) -#error gmp++.h requires g++ version 2.8 or higher +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91) +#error gmp++.h requires g++ version 2.91 (egcs 1.1.2) or higher #endif #endif #ifndef __GMP_PLUSPLUS__ #define __GMP_PLUSPLUS__ -#include <cctype> -#include <iosfwd> +#include <iostream> #include <string> +// #include <strstream> #include <gmp.h> + +/**************** Function objects ****************/ +/* Any evaluation of a __gmp_expr ends up calling one of these functions + all intermediate functions being inline, the evaluation should optimize + to a direct call to the relevant function, thus yielding no overhead + over the C interface. + Functions with mpfr_t arguments are wrapped by an #ifdef test because + mpfr isn't installed by default */ + struct __gmp_unary_plus { static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); } @@ -150,6 +165,17 @@ struct __gmp_binary_plus mpq_clear(temp); } + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { + mpq_set(q, r); + mpz_addmul(mpq_numref(q), mpq_denref(q), z); + } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { + mpq_set(q, r); + mpz_addmul(mpq_numref(q), mpq_denref(q), z); + } + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) { mpf_add(f, g, h); } @@ -319,6 +345,17 @@ struct __gmp_binary_minus mpq_clear(temp); } + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { + mpq_set(q, r); + mpz_submul(mpq_numref(q), mpq_denref(q), z); + } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { + mpq_neg(q, r); + mpz_addmul(mpq_numref(q), mpq_denref(q), z); + } + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) { mpf_sub(f, g, h); } @@ -813,7 +850,7 @@ struct __gmp_binary_modulus static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) { if (mpz_fits_slong_p(w)) - mpz_set_si(z, l / mpz_get_si(w)); + mpz_set_si(z, l % mpz_get_si(w)); else mpz_set_si(z, l); } @@ -1993,13 +2030,20 @@ struct __gmp_rand_function { mpf_urandomb(f, s, prec); } }; + +/**************** Auxiliary classes ****************/ + +/* this is the same as gmp_allocated_string in gmp-impl.h + since gmp-impl.h is not publicly available, I redefine it here + I use a different name to avoid possible clashes */ struct __gmp_alloc_cstring { char *str; - __gmp_alloc_cstring(char *s = 0) { str = s; } + __gmp_alloc_cstring(char *s) { str = s; } ~__gmp_alloc_cstring() { __gmp_free_func(str, strlen(str)+1); } }; + template <class T, class U> class __gmp_expr; @@ -2034,494 +2078,117 @@ private: __gmp_binary_expr(); }; + +class __gmpz_value { }; +class __gmpzref_value { }; +class __gmpq_value { }; +class __gmpf_value { }; + + template <class T, class U> -struct __gmp_resolve_expr; +void __gmp_set_expr(mpz_ptr, const __gmp_expr<T, U> &); +template <class T, class U> +void __gmp_set_expr(mpq_ptr, const __gmp_expr<T, U> &); +template <class T, class U> +void __gmp_set_expr(mpf_ptr, const __gmp_expr<T, U> &); -// function definition macros -#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \ - \ -template <class T, class U> \ -inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \ -} +/**************** Macros for in-class declarations ****************/ +/* This is just repetitive code that is easier to maintain if it's written + only once */ -#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ - \ -template <class T, class U, class V, class W> \ -inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ -__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2) \ -{ \ - return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ - __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ - (expr1, expr2); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, bool b) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, b); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ -fun(bool b, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <unsigned long int, __gmp_expr<T, U>, eval_fun> >(b, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, signed char c) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, c); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ -fun(signed char c, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <signed long int, __gmp_expr<T, U>, eval_fun> >(c, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, unsigned char c) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, c); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ -fun(unsigned char c, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <unsigned long int, __gmp_expr<T, U>, eval_fun> >(c, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, signed int i) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, i); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ -fun(signed int i, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <signed long int, __gmp_expr<T, U>, eval_fun> >(i, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, unsigned int i) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, i); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ -fun(unsigned int i, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <unsigned long int, __gmp_expr<T, U>, eval_fun> >(i, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, signed short int s) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, s); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ -fun(signed short int s, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <signed long int, __gmp_expr<T, U>, eval_fun> >(s, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, unsigned short int s) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, s); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ -fun(unsigned short int s, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <unsigned long int, __gmp_expr<T, U>, eval_fun> >(s, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, signed long int l) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, l); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ -fun(signed long int l, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <signed long int, __gmp_expr<T, U>, eval_fun> >(l, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, l); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ -fun(unsigned long int l, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <unsigned long int, __gmp_expr<T, U>, eval_fun> >(l, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, float f) \ -{ \ - return __gmp_expr \ - <T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> >(expr, f); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr<T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> > \ -fun(float f, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr \ - <T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> >(f, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, double d) \ -{ \ - return __gmp_expr \ - <T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> >(expr, d); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr<T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> > \ -fun(double d, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr \ - <T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> >(d, expr); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, long double, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, long double ld) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, long double, eval_fun> >(expr, ld); \ -} \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<long double, __gmp_expr<T, U>, eval_fun> > \ -fun(long double ld, const __gmp_expr<T, U> &expr) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <long double, __gmp_expr<T, U>, eval_fun> >(ld, expr); \ -} +#define __GMPZZ_DECLARE_COMPOUND_OPERATOR(fun) \ + template <class T, class U> \ + __gmp_expr<__gmpz_value, __gmpz_value> & fun(const __gmp_expr<T, U> &); -#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \ - \ -template <class T, class U> \ -inline __gmp_expr \ -<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ -fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ -{ \ - return __gmp_expr<T, __gmp_binary_expr \ - <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, l); \ -} +#define __GMPZN_DECLARE_COMPOUND_OPERATOR(fun) \ + __gmp_expr & fun(bool); \ + __gmp_expr & fun(signed char); \ + __gmp_expr & fun(unsigned char); \ + __gmp_expr & fun(signed int); \ + __gmp_expr & fun(unsigned int); \ + __gmp_expr & fun(signed short int); \ + __gmp_expr & fun(unsigned short int); \ + __gmp_expr & fun(signed long int); \ + __gmp_expr & fun(unsigned long int); \ + __gmp_expr & fun(float); \ + __gmp_expr & fun(double); \ + __gmp_expr & fun(long double); -#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp()); \ -} +#define __GMPZ_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPZZ_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPZN_DECLARE_COMPOUND_OPERATOR(fun) -#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ - \ -template <class T, class U, class V, class W> \ -inline type fun(const __gmp_expr<T, U> &expr1, \ - const __gmp_expr<V, W> &expr2) \ -{ \ - typename __gmp_resolve_expr<T, V>::temp_type temp1(expr1), temp2(expr2); \ - return eval_fun::eval(temp1.get_mp(), temp2.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr1, \ - const __gmp_expr<T, U> &expr2) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp1(expr1), temp2(expr2); \ - return eval_fun::eval(temp1.get_mp(), temp2.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, bool b) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (unsigned long int) b); \ -} \ - \ -template <class T, class U> \ -inline type fun(bool b, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((unsigned long int) b, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, signed char c) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (signed long int) c); \ -} \ - \ -template <class T, class U> \ -inline type fun(signed char c, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((signed long int) c, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, unsigned char c) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (unsigned long int) c); \ -} \ - \ -template <class T, class U> \ -inline type fun(unsigned char c, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((unsigned long int) c, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, signed int i) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (signed long int) i); \ -} \ - \ -template <class T, class U> \ -inline type fun(signed int i, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((signed long int) i, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, unsigned int i) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (unsigned long int) i); \ -} \ - \ -template <class T, class U> \ -inline type fun(unsigned int i, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((unsigned long int) i, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, signed short int s) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (signed long int) s); \ -} \ - \ -template <class T, class U> \ -inline type fun(signed short int s, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((signed long int) s, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, unsigned short int s) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (unsigned long int) s); \ -} \ - \ -template <class T, class U> \ -inline type fun(unsigned short int s, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((unsigned long int) s, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, signed long int l) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), l); \ -} \ - \ -template <class T, class U> \ -inline type fun(signed long int l, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(l, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), l); \ -} \ - \ -template <class T, class U> \ -inline type fun(unsigned long int l, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(l, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, float f) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), (double) f); \ -} \ - \ -template <class T, class U> \ -inline type fun(float f, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval((double) f, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, double d) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), d); \ -} \ - \ -template <class T, class U> \ -inline type fun(double d, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(d, temp.get_mp()); \ -} \ - \ -template <class T, class U> \ -inline type fun(const __gmp_expr<T, U> &expr, long double ld) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(temp.get_mp(), ld); \ -} \ - \ -template <class T, class U> \ -inline type fun(long double ld, const __gmp_expr<T, U> &expr) \ -{ \ - typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ - return eval_fun::eval(ld, temp.get_mp()); \ -} +#define __GMPZ_DECLARE_COMPOUND_OPERATOR_UI(fun) \ + __gmp_expr & fun(unsigned long int); -// define operators and functions +#define __GMPZ_DECLARE_INCREMENT_OPERATOR(fun) \ + inline __gmp_expr & fun(); \ + inline __gmp_expr fun(int); -__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus) -__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus) +#define __GMPZRR_DECLARE_COMPOUND_OPERATOR(fun) \ + template <class T, class U> \ + __gmp_expr<__gmpz_value, __gmpzref_value> & fun(const __gmp_expr<T, U> &); -__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus) -__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus) -__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies) -__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides) +#define __GMPZRN_DECLARE_COMPOUND_OPERATOR(fun) \ + __gmp_expr & fun(bool); \ + __gmp_expr & fun(signed char); \ + __gmp_expr & fun(unsigned char); \ + __gmp_expr & fun(signed int); \ + __gmp_expr & fun(unsigned int); \ + __gmp_expr & fun(signed short int); \ + __gmp_expr & fun(unsigned short int); \ + __gmp_expr & fun(signed long int); \ + __gmp_expr & fun(unsigned long int); \ + __gmp_expr & fun(float); \ + __gmp_expr & fun(double); \ + __gmp_expr & fun(long double); -__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift) -__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift) +#define __GMPZR_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPZRR_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPZRN_DECLARE_COMPOUND_OPERATOR(fun) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, __gmp_binary_not_equal) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, __gmp_binary_less_equal) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, \ - __gmp_binary_greater_equal) +#define __GMPZR_DECLARE_COMPOUND_OPERATOR_UI(fun) \ + __gmp_expr & fun(unsigned long int); -__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function) -__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function) -__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function) -__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function) -__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function) -__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function) +#define __GMPZR_DECLARE_INCREMENT_OPERATOR(fun) \ + inline __gmp_expr & fun(); \ + inline mpz_class fun(int); -__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, compare, __gmp_cmp_function) +#define __GMPQQ_DECLARE_COMPOUND_OPERATOR(fun) \ + template <class T, class U> \ + __gmp_expr<__gmpq_value, __gmpq_value> & fun(const __gmp_expr<T, U> &); -template <class T, class U> -void __gmp_set_expr(mpz_ptr, const __gmp_expr<T, U> &); +#define __GMPQN_DECLARE_COMPOUND_OPERATOR(fun) \ + __gmp_expr & fun(bool); \ + __gmp_expr & fun(signed char); \ + __gmp_expr & fun(unsigned char); \ + __gmp_expr & fun(signed int); \ + __gmp_expr & fun(unsigned int); \ + __gmp_expr & fun(signed short int); \ + __gmp_expr & fun(unsigned short int); \ + __gmp_expr & fun(signed long int); \ + __gmp_expr & fun(unsigned long int); \ + __gmp_expr & fun(float); \ + __gmp_expr & fun(double); \ + __gmp_expr & fun(long double); -class __gmpz_value { }; -class __gmpzref_value { }; +#define __GMPQ_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPQQ_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPQN_DECLARE_COMPOUND_OPERATOR(fun) -// class wrapper for mpz_t +#define __GMPQ_DECLARE_COMPOUND_OPERATOR_UI(fun) \ + __gmp_expr & fun(unsigned long int); -#define __GMPZZ_DECLARE_COMPOUND_OPERATOR(fun) \ +#define __GMPQ_DECLARE_INCREMENT_OPERATOR(fun) \ + inline __gmp_expr & fun(); \ + inline __gmp_expr fun(int); + +#define __GMPFF_DECLARE_COMPOUND_OPERATOR(fun) \ template <class T, class U> \ - __gmp_expr<__gmpz_value, __gmpz_value> & fun(const __gmp_expr<T, U> &); + __gmp_expr<__gmpf_value, __gmpf_value> & fun(const __gmp_expr<T, U> &); -#define __GMPZN_DECLARE_COMPOUND_OPERATOR(fun) \ +#define __GMPFN_DECLARE_COMPOUND_OPERATOR(fun) \ __gmp_expr & fun(bool); \ __gmp_expr & fun(signed char); \ __gmp_expr & fun(unsigned char); \ @@ -2535,24 +2202,27 @@ class __gmpzref_value { }; __gmp_expr & fun(double); \ __gmp_expr & fun(long double); -#define __GMPZ_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPZZ_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPZN_DECLARE_COMPOUND_OPERATOR(fun) +#define __GMPF_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPFF_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPFN_DECLARE_COMPOUND_OPERATOR(fun) -#define __GMPZ_DECLARE_COMPOUND_OPERATOR_UI(fun) \ +#define __GMPF_DECLARE_COMPOUND_OPERATOR_UI(fun) \ __gmp_expr & fun(unsigned long int); -#define __GMPZ_DECLARE_INCREMENT_OPERATOR(fun) \ +#define __GMPF_DECLARE_INCREMENT_OPERATOR(fun) \ inline __gmp_expr & fun(); \ inline __gmp_expr fun(int); + +/**************** mpz_class -- wrapper for mpz_t ****************/ + template <> class __gmp_expr<__gmpz_value, __gmpz_value> { private: mpz_t mp; public: - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } // constructors and destructor __gmp_expr() { mpz_init(mp); } @@ -2580,10 +2250,14 @@ public: __gmp_expr(double d) { mpz_init_set_d(mp, d); } // __gmp_expr(long double ld) { mpz_init_set_d(mp, ld); } - explicit __gmp_expr(const char *s) { mpz_init_set_str(mp, s, 0); } - __gmp_expr(const char *s, int base) { mpz_init_set_str(mp, s, base); } - explicit __gmp_expr(const string &s) { mpz_init_set_str(mp, s.c_str(), 0); } - __gmp_expr(const string &s, int base) + explicit __gmp_expr(const char *s) + + { mpz_init_set_str(mp, s, 0); } + __gmp_expr(const char *s, int base) + { mpz_init_set_str(mp, s, base); } + explicit __gmp_expr(const std::string &s) + { mpz_init_set_str(mp, s.c_str(), 0); } + __gmp_expr(const std::string &s, int base) { mpz_init_set_str(mp, s.c_str(), base); } explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); } @@ -2624,16 +2298,16 @@ public: __gmp_expr & operator=(const char *s) { mpz_set_str(mp, s, 0); return *this; } - __gmp_expr & operator=(const string &s) + __gmp_expr & operator=(const std::string &s) { mpz_set_str(mp, s.c_str(), 0); return *this; } // string input/output functions - void set_str_base(const string &s, int base) - { mpz_set_str(mp, s.c_str(), base); } - string get_str_base(int base) const + int set_str(const std::string &s, int base) + { return mpz_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const { __gmp_alloc_cstring temp(mpz_get_str(0, base, mp)); - return string(temp.str); + return std::string(temp.str); } // conversion functions @@ -2676,393 +2350,27 @@ public: typedef __gmp_expr<__gmpz_value, __gmpz_value> mpz_class; -// unary expressions - -template <class Op> -class __gmp_expr<__gmpz_value, __gmp_unary_expr<mpz_class, Op> > -{ -private: - __gmp_unary_expr<mpz_class, Op> expr; -public: - __gmp_expr(const mpz_class &val) : expr(val) { } - void eval(mpz_ptr z) const { Op::eval(z, expr.val.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class Op> -class __gmp_expr<__gmpz_value, __gmp_unary_expr<__gmp_expr<T, U>, Op> > -{ -private: - __gmp_unary_expr<__gmp_expr<T, U>, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val) : expr(val) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val); - Op::eval(z, temp.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -// binary expressions - -template <class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_class, mpz_class, Op> > -{ -private: - __gmp_binary_expr<mpz_class, mpz_class, Op> expr; -public: - __gmp_expr(const mpz_class &val1, const mpz_class &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_class, T, Op> > -{ -private: - __gmp_binary_expr<mpz_class, T, Op> expr; -public: - __gmp_expr(const mpz_class &val1, T val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, mpz_class, Op> > -{ -private: - __gmp_binary_expr<T, mpz_class, Op> expr; -public: - __gmp_expr(T val1, const mpz_class &val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1, expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<mpz_class, __gmp_expr<T, U>, Op> > -{ -private: - __gmp_binary_expr<mpz_class, __gmp_expr<T, U>, Op> expr; -public: - __gmp_expr(const mpz_class &val1, const __gmp_expr<T, U> &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val2); - Op::eval(z, expr.val1.get_mpz_t(), temp.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, mpz_class, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, mpz_class, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, const mpz_class &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val1); - Op::eval(z, temp.get_mpz_t(), expr.val2.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class V, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, V, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, V val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val1); - Op::eval(z, temp.get_mpz_t(), expr.val2); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; -template <class T, class U, class V, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, __gmp_expr<U, V>, Op> > -{ -private: - __gmp_binary_expr<T, __gmp_expr<U, V>, Op> expr; -public: - __gmp_expr(T val1, const __gmp_expr<U, V> &val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val2); - Op::eval(z, expr.val1, temp.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class V, class W, class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > -{ -private: - __gmp_binary_expr - <__gmp_expr<T, U>, __gmp_expr<V, W>, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, const __gmp_expr<V, W> &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp1(expr.val1), temp2(expr.val2); - Op::eval(z, temp1.get_mpz_t(), temp2.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -// type conversions - -class __gmpz_temp -{ -private: - mpz_srcptr mp; - bool is_temp; - mpz_t temp; - - __gmpz_temp(); - __gmpz_temp(const __gmpz_temp &); - void operator=(const __gmpz_temp &); -public: - __gmpz_temp(const mpz_class &z) : mp(z.get_mpz_t()), is_temp(false) { } - __gmpz_temp(const __gmp_expr<__gmpz_value, __gmpzref_value> &); - template <class T, class U> - __gmpz_temp(const __gmp_expr<T, U> &expr) - { - mpz_init(temp); - __gmp_set_expr(temp, expr); - mp = temp; - is_temp = true; - } - ~__gmpz_temp() { if (is_temp) mpz_clear(temp); } - - mpz_srcptr get_mp() const { return mp; } -}; - -template <> -struct __gmp_resolve_expr<__gmpz_value, __gmpz_value> -{ - typedef __gmpz_value value_type; - typedef __gmpz_temp temp_type; -}; - -template <> -inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w) -{ - mpz_set(z, w.get_mpz_t()); -} - -template <class T> -inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<__gmpz_value, T> &expr) -{ - expr.eval(z); -} - -// functions - -inline ostream & operator<<(ostream &o, const mpz_class &z) +inline std::ostream & operator<<(std::ostream &o, const mpz_class &z) { return o << z.get_mpz_t(); } template <class T> -inline ostream & operator<< -(ostream &o, const __gmp_expr<__gmpz_value, T> &expr) +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<__gmpz_value, T> &expr) { mpz_class temp(expr); return o << temp.get_mpz_t(); } -inline istream & operator>>(istream &i, mpz_class &z) +inline std::istream & operator>>(std::istream &i, mpz_class &z) { return i >> z.get_mpz_t(); } -#define __GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ - \ -template <class T, class U> \ -inline mpz_class & mpz_class::fun(const __gmp_expr<T, U> &expr) \ -{ \ - __gmpz_temp temp(expr); \ - eval_fun::eval(mp, mp, temp.get_mp()); \ - return *this; \ -} - -#define __GMPZN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ - \ -inline mpz_class & mpz_class::fun(bool b) \ -{ \ - eval_fun::eval(mp, mp, (unsigned long int) b); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(signed char c) \ -{ \ - eval_fun::eval(mp, mp, (signed long int) c); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(unsigned char c) \ -{ \ - eval_fun::eval(mp, mp, (unsigned long int) c); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(signed int i) \ -{ \ - eval_fun::eval(mp, mp, (signed long int) i); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(unsigned int i) \ -{ \ - eval_fun::eval(mp, mp, (unsigned long int) i); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(signed short int s) \ -{ \ - eval_fun::eval(mp, mp, (signed long int) s); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(unsigned short int s) \ -{ \ - eval_fun::eval(mp, mp, (unsigned long int) s); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(signed long int l) \ -{ \ - eval_fun::eval(mp, mp, l); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(unsigned long int l) \ -{ \ - eval_fun::eval(mp, mp, l); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(float f) \ -{ \ - eval_fun::eval(mp, mp, (double) f); \ - return *this; \ -} \ - \ -inline mpz_class & mpz_class::fun(double d) \ -{ \ - eval_fun::eval(mp, mp, d); \ - return *this; \ -} \ - \ -/* \ -inline mpz_class & mpz_class::fun(long double ld) \ -{ \ - eval_fun::eval(mp, mp, ld); \ - return *this; \ -} */ - -#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ -__GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ -__GMPZN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) - -#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ - \ -inline mpz_class & mpz_class::fun(unsigned long int l) \ -{ \ - eval_fun::eval(mp, mp, l); \ - return *this; \ -} - -#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ - \ -inline mpz_class & mpz_class::fun() \ -{ \ - eval_fun::eval(mp, mp); \ - return *this; \ -} \ - \ -inline mpz_class mpz_class::fun(int) \ -{ \ - mpz_class temp(*this); \ - eval_fun::eval(mp, mp); \ - return temp; \ -} - -// define operators and functions -__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com) -__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus) -__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and) -__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior) -__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor) - -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) - -__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) -__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) -__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) - -__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - -template <class T, class U> -void __gmp_set_expr(mpq_ptr, const __gmp_expr<T, U> &); - -class __gmpq_value { }; - -// reference class for numerator/denominator of mpq_t - -#define __GMPZRR_DECLARE_COMPOUND_OPERATOR(fun) \ - template <class T, class U> \ - __gmp_expr<__gmpz_value, __gmpzref_value> & fun(const __gmp_expr<T, U> &); - -#define __GMPZRN_DECLARE_COMPOUND_OPERATOR(fun) \ - __gmp_expr & fun(bool); \ - __gmp_expr & fun(signed char); \ - __gmp_expr & fun(unsigned char); \ - __gmp_expr & fun(signed int); \ - __gmp_expr & fun(unsigned int); \ - __gmp_expr & fun(signed short int); \ - __gmp_expr & fun(unsigned short int); \ - __gmp_expr & fun(signed long int); \ - __gmp_expr & fun(unsigned long int); \ - __gmp_expr & fun(float); \ - __gmp_expr & fun(double); \ - __gmp_expr & fun(long double); - -#define __GMPZR_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPZRR_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPZRN_DECLARE_COMPOUND_OPERATOR(fun) - -#define __GMPZR_DECLARE_COMPOUND_OPERATOR_UI(fun) \ - __gmp_expr & fun(unsigned long int); - -#define __GMPZR_DECLARE_INCREMENT_OPERATOR(fun) \ - inline __gmp_expr & fun(); \ - inline mpz_class fun(int); +/**************** mpz_classref -- num/den of mpq_t ****************/ template <> class __gmp_expr<__gmpz_value, __gmpzref_value> @@ -3076,7 +2384,7 @@ private: __gmp_expr(mpz_ptr z) : ref(z) { } __gmp_expr(mpz_srcptr z) : ref((mpz_ptr) z) { } public: - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } // assignment operators __gmp_expr & operator=(const __gmp_expr &z) @@ -3116,16 +2424,16 @@ public: __gmp_expr & operator=(const char *s) { mpz_set_str(ref, s, 0); return *this; } - __gmp_expr & operator=(const string &s) + __gmp_expr & operator=(const std::string &s) { mpz_set_str(ref, s.c_str(), 0); return *this; } // string input/output functions - void set_str_base(const string &s, int base) - { mpz_set_str(ref, s.c_str(), base); } - string get_str_base(int base) const + int set_str(const std::string &s, int base) + { return mpz_set_str(ref, s.c_str(), base); } + std::string get_str(int base = 10) const { __gmp_alloc_cstring temp(mpz_get_str(0, base, ref)); - return string(temp.str); + return std::string(temp.str); } // conversion functions @@ -3169,174 +2477,18 @@ public: typedef __gmp_expr<__gmpz_value, __gmpzref_value> mpz_classref; -// unary expressions - -template <class Op> -class __gmp_expr<__gmpz_value, __gmp_unary_expr<mpz_classref, Op> > -{ -private: - __gmp_unary_expr<mpz_classref, Op> expr; -public: - __gmp_expr(const mpz_classref &val) : expr(val) { } - void eval(mpz_ptr z) const { Op::eval(z, expr.val.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -// binary expressions - -template <class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<mpz_classref, mpz_classref, Op> > -{ -private: - __gmp_binary_expr<mpz_classref, mpz_classref, Op> expr; -public: - __gmp_expr(const mpz_classref &val1, const mpz_classref &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<mpz_class, mpz_classref, Op> > -{ -private: - __gmp_binary_expr<mpz_class, mpz_classref, Op> expr; -public: - __gmp_expr(const mpz_class &val1, const mpz_classref &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<mpz_classref, mpz_class, Op> > -{ -private: - __gmp_binary_expr<mpz_classref, mpz_class, Op> expr; -public: - __gmp_expr(const mpz_classref &val1, const mpz_class &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_classref, T, Op> > -{ -private: - __gmp_binary_expr<mpz_classref, T, Op> expr; -public: - __gmp_expr(const mpz_classref &val1, T val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1.get_mpz_t(), expr.val2); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class Op> -class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, mpz_classref, Op> > -{ -private: - __gmp_binary_expr<T, mpz_classref, Op> expr; -public: - __gmp_expr(T val1, const mpz_classref &val2) : expr(val1, val2) { } - void eval(mpz_ptr z) const - { Op::eval(z, expr.val1, expr.val2.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<mpz_classref, __gmp_expr<T, U>, Op> > -{ -private: - __gmp_binary_expr<mpz_classref, __gmp_expr<T, U>, Op> expr; -public: - __gmp_expr(const mpz_classref &val1, const __gmp_expr<T, U> &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val2); - Op::eval(z, expr.val1.get_mpz_t(), temp.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, mpz_classref, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, mpz_classref, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, const mpz_classref &val2) - : expr(val1, val2) { } - void eval(mpz_ptr z) const - { - mpz_class temp(expr.val1); - Op::eval(z, temp.get_mpz_t(), expr.val2.get_mpz_t()); - } - unsigned long int precision() const { return mpf_get_default_prec(); } -}; - -// type conversions - -inline __gmpz_temp::__gmpz_temp(const mpz_classref &z) - : mp(z.get_mpz_t()), is_temp(false) { } - -template <> -inline void __gmp_set_expr(mpz_ptr z, const mpz_classref &w) -{ - mpz_set(z, w.get_mpz_t()); -} - -// functions -inline ostream & operator<<(ostream &o, const mpz_classref &z) +inline std::ostream & operator<<(std::ostream &o, const mpz_classref &z) { return o << z.get_mpz_t(); } -inline istream & operator>>(istream &i, mpz_classref &z) +inline std::istream & operator>>(std::istream &i, mpz_classref &z) { return i >> z.get_mpz_t(); } -// class wrapper for mpq_t - -#define __GMPQQ_DECLARE_COMPOUND_OPERATOR(fun) \ - template <class T, class U> \ - __gmp_expr<__gmpq_value, __gmpq_value> & fun(const __gmp_expr<T, U> &); - -#define __GMPQN_DECLARE_COMPOUND_OPERATOR(fun) \ - __gmp_expr & fun(bool); \ - __gmp_expr & fun(signed char); \ - __gmp_expr & fun(unsigned char); \ - __gmp_expr & fun(signed int); \ - __gmp_expr & fun(unsigned int); \ - __gmp_expr & fun(signed short int); \ - __gmp_expr & fun(unsigned short int); \ - __gmp_expr & fun(signed long int); \ - __gmp_expr & fun(unsigned long int); \ - __gmp_expr & fun(float); \ - __gmp_expr & fun(double); \ - __gmp_expr & fun(long double); - -#define __GMPQ_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPQQ_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPQN_DECLARE_COMPOUND_OPERATOR(fun) - -#define __GMPQ_DECLARE_COMPOUND_OPERATOR_UI(fun) \ - __gmp_expr & fun(unsigned long int); - -#define __GMPQ_DECLARE_INCREMENT_OPERATOR(fun) \ - inline __gmp_expr & fun(); \ - inline __gmp_expr fun(int); +/**************** mpq_class -- wrapper for mpq_t ****************/ template <> class __gmp_expr<__gmpq_value, __gmpq_value> @@ -3344,7 +2496,7 @@ class __gmp_expr<__gmpq_value, __gmpq_value> private: mpq_t mp; public: - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } void canonicalize() { mpq_canonicalize(mp); } // constructors and destructor @@ -3373,17 +2525,24 @@ public: __gmp_expr(double d) { mpq_init(mp); mpq_set_d(mp, d); } // __gmp_expr(long double ld) { mpq_init(mp); mpq_set_ld(mp, ld); } - explicit __gmp_expr(const char *s) { mpq_init(mp); mpq_set_str(mp, s, 0); } + explicit __gmp_expr(const char *s) + { mpq_init(mp); mpq_set_str(mp, s, 0); } __gmp_expr(const char *s, unsigned long int base) { mpq_init(mp); mpq_set_str(mp, s, base); } - explicit __gmp_expr(const string &s) + explicit __gmp_expr(const std::string &s) { mpq_init(mp); mpq_set_str(mp, s.c_str(), 0); } - __gmp_expr(const string &s, unsigned long int base) + __gmp_expr(const std::string &s, unsigned long int base) { mpq_init(mp); mpq_set_str(mp, s.c_str(), base); } explicit __gmp_expr(mpq_srcptr q) { mpq_init(mp); mpq_set(mp, q); } - __gmp_expr(const mpz_class &, const mpz_class &); + __gmp_expr(const mpz_class &num, const mpz_class &den) + { + mpq_init(mp); + mpz_set(mpq_numref(mp), num.get_mpz_t()); + mpz_set(mpq_denref(mp), den.get_mpz_t()); + } + // this is defined later (after __gmpz_temp) template <class T, class U> __gmp_expr(const __gmp_expr<__gmpz_value, T> &, const __gmp_expr<__gmpz_value, U> &); @@ -3427,16 +2586,16 @@ public: __gmp_expr & operator=(const char *s) { mpq_set_str(mp, s, 0); return *this; } - __gmp_expr & operator=(const string &s) + __gmp_expr & operator=(const std::string &s) { mpq_set_str(mp, s.c_str(), 0); return *this; } // string input/output functions - void set_str_base(const string &s, int base) - { mpq_set_str(mp, s.c_str(), base); } - string get_str_base(int base) const + int set_str(const std::string &s, int base) + { return mpq_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const { __gmp_alloc_cstring temp(mpq_get_str(0, base, mp)); - return string(temp.str); + return std::string(temp.str); } // conversion functions @@ -3470,7 +2629,581 @@ public: typedef __gmp_expr<__gmpq_value, __gmpq_value> mpq_class; -// unary expressions + +inline std::ostream & operator<<(std::ostream &o, const mpq_class &q) +{ + return o << q.get_mpq_t(); +} + +template <class T> +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<__gmpq_value, T> &expr) +{ + mpq_class temp(expr); + return o << temp.get_mpq_t(); +} + +inline std::istream & operator>>(std::istream &i, mpq_class &q) +{ + i >> q.get_mpq_t(); + // q.canonicalize(); + return i; +} + + +/**************** mpf_class -- wrapper for mpf_t ****************/ + +template <> +class __gmp_expr<__gmpf_value, __gmpf_value> +{ +private: + mpf_t mp; +public: + // size information + unsigned long int get_prec() const { return mpf_get_prec(mp); } + + void set_prec(unsigned long int prec) { mpf_set_prec(mp, prec); } + void set_prec_raw(unsigned long int prec) { mpf_set_prec_raw(mp, prec); } + + // constructors and destructor + __gmp_expr() { mpf_init(mp); } + + __gmp_expr(const __gmp_expr &f) + { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); } + __gmp_expr(const __gmp_expr &f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set(mp, f.mp); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr) + { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr, unsigned long int prec) + { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); } + + __gmp_expr(bool b) { mpf_init_set_ui(mp, b); } + __gmp_expr(bool b, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, b); } + + __gmp_expr(signed char c) { mpf_init_set_si(mp, c); } + __gmp_expr(signed char c, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, c); } + __gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); } + __gmp_expr(unsigned char c, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, c); } + + __gmp_expr(signed int i) { mpf_init_set_si(mp, i); } + __gmp_expr(signed int i, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, i); } + __gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); } + __gmp_expr(unsigned int i, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, i); } + + __gmp_expr(signed short int s) { mpf_init_set_si(mp, s); } + __gmp_expr(signed short int s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, s); } + __gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); } + __gmp_expr(unsigned short int s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, s); } + + __gmp_expr(signed long int l) { mpf_init_set_si(mp, l); } + __gmp_expr(signed long int l, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_si(mp, l); } + __gmp_expr(unsigned long int l) { mpf_init_set_ui(mp, l); } + __gmp_expr(unsigned long int l, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, l); } + + __gmp_expr(float f) { mpf_init_set_d(mp, f); } + __gmp_expr(float f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_d(mp, f); } + __gmp_expr(double d) { mpf_init_set_d(mp, d); } + __gmp_expr(double d, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_d(mp, d); } + /* + __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); } + __gmp_expr(long double ld, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_d(mp, ld); } + */ + + explicit __gmp_expr(const char *s) { mpf_init_set_str(mp, s, 0); } + __gmp_expr(const char *s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_str(mp, s, 0); } + explicit __gmp_expr(const std::string &s) + { mpf_init_set_str(mp, s.c_str(), 0); } + __gmp_expr(const std::string &s, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set_str(mp, s.c_str(), 0); } + + explicit __gmp_expr(mpf_srcptr f) + { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); } + __gmp_expr(mpf_srcptr f, unsigned long int prec) + { mpf_init2(mp, prec); mpf_set(mp, f); } + + ~__gmp_expr() { mpf_clear(mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &f) + { mpf_set(mp, f.mp); return *this; } + template <class T, class U> + __gmp_expr<__gmpf_value, __gmpf_value> & operator= + (const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __gmp_expr & operator=(bool b) { mpf_set_ui(mp, b); return *this; } + + __gmp_expr & operator=(signed char c) { mpf_set_si(mp, c); return *this; } + __gmp_expr & operator=(unsigned char c) { mpf_set_ui(mp, c); return *this; } + + __gmp_expr & operator=(signed int i) { mpf_set_si(mp, i); return *this; } + __gmp_expr & operator=(unsigned int i) { mpf_set_ui(mp, i); return *this; } + + __gmp_expr & operator=(signed short int s) + { mpf_set_si(mp, s); return *this; } + __gmp_expr & operator=(unsigned short int s) + { mpf_set_ui(mp, s); return *this; } + + __gmp_expr & operator=(signed long int l) + { mpf_set_si(mp, l); return *this; } + __gmp_expr & operator=(unsigned long int l) + { mpf_set_ui(mp, l); return *this; } + + __gmp_expr & operator=(float f) { mpf_set_d(mp, f); return *this; } + __gmp_expr & operator=(double d) { mpf_set_d(mp, d); return *this; } + /* + __gmp_expr & operator=(long double ld) { mpf_set_ld(mp, ld); return *this; } + */ + + __gmp_expr & operator=(const char *s) + { mpf_set_str(mp, s, 0); return *this; } + __gmp_expr & operator=(const std::string &s) + { mpf_set_str(mp, s.c_str(), 0); return *this; } + + // string input/output functions + int set_str(const std::string &s, int base) + { return mpf_set_str(mp, s.c_str(), base); } + std::string get_str(mp_exp_t *expo, int base, size_t size) const + { + __gmp_alloc_cstring temp(mpf_get_str(0, expo, base, size, mp)); + return std::string(temp.str); + } + std::string get_str2(int base = 10) const + { + std::ostrstream o; + mp_exp_t expo; + std::string temp(mpf_get_str(0, &expo, base, 0, mp)); + + if (temp[0] == '-') + o << "-0." << temp.substr(1); + else + o << "0." << temp; + + if (base <= 10) + o << "e" << expo << '\0'; + else + o << "@" << expo << '\0'; + + return o.str(); + } + + // conversion functions + mpf_srcptr get_mpf_t() const { return mp; } + mpf_ptr get_mpf_t() { return mp; } + + signed long int get_si() const { return mpf_get_si(mp); } + unsigned long int get_ui() const { return mpf_get_ui(mp); } + double get_d() const { return mpf_get_d(mp); } // should be long double + + // bool fits_schar_p() const { return mpf_fits_schar_p(mp); } + // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); } + bool fits_sint_p() const { return mpf_fits_sint_p(mp); } + bool fits_uint_p() const { return mpf_fits_uint_p(mp); } + bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); } + bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); } + bool fits_slong_p() const { return mpf_fits_slong_p(mp); } + bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); } + // bool fits_float_p() const { return mpf_fits_float_p(mp); } + // bool fits_double_p() const { return mpf_fits_double_p(mp); } + // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); } + + // compound assignments + __GMPF_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMPF_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMPF_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMPF_DECLARE_COMPOUND_OPERATOR(operator/=) + + __GMPF_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMPF_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMPF_DECLARE_INCREMENT_OPERATOR(operator++) + __GMPF_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<__gmpf_value, __gmpf_value> mpf_class; + + +inline std::ostream & operator<<(std::ostream &o, const mpf_class &f) +{ + return o << f.get_mpf_t(); +} + +template <class T> +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<__gmpf_value, T> &expr) +{ + mpf_class temp(expr); + return o << temp.get_mpf_t(); +} + +inline std::istream & operator>>(std::istream &i, mpf_class &f) +{ + return i >> f.get_mpf_t(); +} + + +/**************** Classes for type conversion ****************/ +/* If the expression to be converted is a plain mp[zqf]_class, a direct + reference to its mp[zqf]_t internal yields optimal efficiency. + If it's a compound expression, a temporary must be used */ + +class __gmpz_temp +{ +private: + mpz_srcptr mp; + bool is_temp; + mpz_t temp; + + __gmpz_temp(); + __gmpz_temp(const __gmpz_temp &); + void operator=(const __gmpz_temp &); +public: + __gmpz_temp(const mpz_class &z) : mp(z.get_mpz_t()), is_temp(false) { } + __gmpz_temp(const mpz_classref &z) : mp(z.get_mpz_t()), is_temp(false) { } + template <class T, class U> + __gmpz_temp(const __gmp_expr<T, U> &expr) + { + mpz_init(temp); + __gmp_set_expr(temp, expr); + mp = temp; + is_temp = true; + } + ~__gmpz_temp() { if (is_temp) mpz_clear(temp); } + + mpz_srcptr get_mp() const { return mp; } +}; + +class __gmpq_temp +{ +private: + mpq_srcptr mp; + bool is_temp; + mpq_t temp; + + __gmpq_temp(); + __gmpq_temp(const __gmpq_temp &); + void operator=(const __gmpq_temp &); +public: + __gmpq_temp(const mpq_class &q) : mp(q.get_mpq_t()), is_temp(false) { } + template <class T, class U> + __gmpq_temp(const __gmp_expr<T, U> &expr) + { + mpq_init(temp); + __gmp_set_expr(temp, expr); + mp = temp; + is_temp = true; + } + ~__gmpq_temp() { if (is_temp) mpq_clear(temp); } + + mpq_srcptr get_mp() const { return mp; } +}; + +class __gmpf_temp +{ +private: + mpf_srcptr mp; + bool is_temp; + mpf_t temp; + + __gmpf_temp(); + __gmpf_temp(const __gmpf_temp &); + void operator=(const __gmpf_temp &); +public: + __gmpf_temp(const mpf_class &f) : mp(f.get_mpf_t()), is_temp(false) { } + __gmpf_temp(const mpf_class &f, unsigned long int) + : mp(f.get_mpf_t()), is_temp(false) { } + template <class T, class U> + __gmpf_temp(const __gmp_expr<T, U> &expr) + { + mpf_init2(temp, expr.get_prec()); + __gmp_set_expr(temp, expr); + mp = temp; + is_temp = true; + } + template <class T, class U> + __gmpf_temp(const __gmp_expr<T, U> &expr, unsigned long int prec) + { + mpf_init2(temp, prec); + __gmp_set_expr(temp, expr); + mp = temp; + is_temp = true; + } + ~__gmpf_temp() { if (is_temp) mpf_clear(temp); } + + mpf_srcptr get_mp() const { return mp; } +}; + + +// this function must be defined after __gmpz_temp +template <class T, class U> +inline mpq_class::__gmp_expr(const __gmp_expr<__gmpz_value, T> &num, + const __gmp_expr<__gmpz_value, U> &den) +{ + __gmpz_temp temp1(num), temp2(den); + mpq_init(mp); + mpz_set(mpq_numref(mp), temp1.get_mp()); + mpz_set(mpq_denref(mp), temp2.get_mp()); +} + + +// type of mixed-type expressions +template <class T, class U> +struct __gmp_resolve_expr; + +template <> +struct __gmp_resolve_expr<__gmpz_value, __gmpz_value> +{ + typedef __gmpz_value value_type; + typedef __gmpz_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpq_value, __gmpq_value> +{ + typedef __gmpq_value value_type; + typedef __gmpq_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpz_value, __gmpq_value> +{ + typedef __gmpq_value value_type; + typedef __gmpq_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpq_value, __gmpz_value> +{ + typedef __gmpq_value value_type; + typedef __gmpq_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpf_value, __gmpf_value> +{ + typedef __gmpf_value value_type; + typedef __gmpf_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpz_value, __gmpf_value> +{ + typedef __gmpf_value value_type; + typedef __gmpf_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpf_value, __gmpz_value> +{ + typedef __gmpf_value value_type; + typedef __gmpf_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpq_value, __gmpf_value> +{ + typedef __gmpf_value value_type; + typedef __gmpf_temp temp_type; +}; + +template <> +struct __gmp_resolve_expr<__gmpf_value, __gmpq_value> +{ + typedef __gmpf_value value_type; + typedef __gmpf_temp temp_type; +}; + + +// perform type conversions + +template <> +inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w) +{ + mpz_set(z, w.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<__gmpz_value, T> &expr) +{ + expr.eval(z); +} + +template <> +inline void __gmp_set_expr(mpz_ptr z, const mpz_classref &w) +{ + mpz_set(z, w.get_mpz_t()); +} + +template <> +inline void __gmp_set_expr(mpz_ptr z, const mpq_class &q) +{ + mpz_set_q(z, q.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<__gmpq_value, T> &expr) +{ + mpq_class temp(expr); + mpz_set_q(z, temp.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const mpf_class &f) +{ + mpz_set_f(z, f.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<__gmpf_value, T> &expr) +{ + mpf_class temp(expr); + mpz_set_f(z, temp.get_mpf_t()); +} + +template <> +inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z) +{ + mpq_set_z(q, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpz_value, T> &expr) +{ + mpz_class temp(expr); + mpq_set_z(q, temp.get_mpz_t()); +} + +template <> +inline void __gmp_set_expr(mpq_ptr q, const mpz_classref &z) +{ + mpq_set_z(q, z.get_mpz_t()); +} + +template <> +inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r) +{ + mpq_set(q, r.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpq_value, T> &expr) +{ + expr.eval(q); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const mpf_class &f) +{ + mpq_set_f(q, f.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpf_value, T> &expr) +{ + mpf_class temp(expr); + mpq_set_f(q, temp.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const mpz_class &z) +{ + mpf_set_z(f, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpz_value, T> &expr) +{ + mpz_class temp(expr); + mpf_set_z(f, temp.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const mpz_classref &z) +{ + mpf_set_z(f, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const mpq_class &q) +{ + mpf_set_q(f, q.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpq_value, T> &expr) +{ + mpq_class temp(expr); + mpf_set_q(f, temp.get_mpq_t()); +} + +template <> +inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g) +{ + mpf_set(f, g.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpf_value, T> &expr) +{ + expr.eval(f, mpf_get_prec(f)); +} + + +/**************** Specializations of __gmp_expr ****************/ +/* The eval() method of __gmp_expr<T, U> evaluates the corresponding + expression assigning the result to its argument, which is either an + mpz_t, mpq_t, or mpf_t -- this depends on the T argument, which is + either __gmpz_value, __gmpq_value, or __gmpf_value, respectively. + Compound expressions are evaluated recursively (temporaries are created + to hold intermediate values), while for simple expressions the eval() + method of the appropriate function object (available as the Op argument + of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is + called. */ + +/**************** Unary expressions ****************/ +/* cases: + - simple: argument is mp[zqf]_class, or mpz_classref + - compound: argument is __gmp_expr<...> */ + + +// simple expressions + +template <class Op> +class __gmp_expr<__gmpz_value, __gmp_unary_expr<mpz_class, Op> > +{ +private: + __gmp_unary_expr<mpz_class, Op> expr; +public: + __gmp_expr(const mpz_class &val) : expr(val) { } + void eval(mpz_ptr z) const { Op::eval(z, expr.val.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr<__gmpz_value, __gmp_unary_expr<mpz_classref, Op> > +{ +private: + __gmp_unary_expr<mpz_classref, Op> expr; +public: + __gmp_expr(const mpz_classref &val) : expr(val) { } + void eval(mpz_ptr z) const { Op::eval(z, expr.val.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; template <class Op> class __gmp_expr<__gmpq_value, __gmp_unary_expr<mpq_class, Op> > @@ -3480,7 +3213,38 @@ private: public: __gmp_expr(const mpq_class &val) : expr(val) { } void eval(mpq_ptr q) const { Op::eval(q, expr.val.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr<__gmpf_value, __gmp_unary_expr<mpf_class, Op> > +{ +private: + __gmp_unary_expr<mpf_class, Op> expr; +public: + __gmp_expr(const mpf_class &val) : expr(val) { } + void eval(mpf_ptr f, unsigned long int) const + { Op::eval(f, expr.val.get_mpf_t()); } + unsigned long int get_prec() const + { return mpf_get_prec(expr.val.get_mpf_t()); } +}; + + +// compound expressions + +template <class T, class U, class Op> +class __gmp_expr<__gmpz_value, __gmp_unary_expr<__gmp_expr<T, U>, Op> > +{ +private: + __gmp_unary_expr<__gmp_expr<T, U>, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val) : expr(val) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val); + Op::eval(z, temp.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class Op> @@ -3495,10 +3259,91 @@ public: mpq_class temp(expr.val); Op::eval(q, temp.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr<__gmpf_value, __gmp_unary_expr<__gmp_expr<T, U>, Op> > +{ +private: + __gmp_unary_expr<__gmp_expr<T, U>, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val) : expr(val) { } + void eval(mpf_ptr f, unsigned long int prec) const + { + mpf_class temp(expr.val, prec); + Op::eval(f, temp.get_mpf_t()); + } + unsigned long int get_prec() const { return expr.val.get_prec(); } }; -// binary expressions + +/**************** Binary expressions ****************/ +/* simple: + - arguments are both mp[zqf]_class, or mpz_classref + - one argument is mp[zqf]_class(ref), one is a built-in type + compound: + - one is mp[zqf]_class(ref), one is __gmp_expr<...> + - one is __gmp_expr<...>, one is built-in + - both arguments are __gmp_expr<...> */ + + +// simple expressions + +template <class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_class, mpz_class, Op> > +{ +private: + __gmp_binary_expr<mpz_class, mpz_class, Op> expr; +public: + __gmp_expr(const mpz_class &val1, const mpz_class &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<mpz_class, mpz_classref, Op> > +{ +private: + __gmp_binary_expr<mpz_class, mpz_classref, Op> expr; +public: + __gmp_expr(const mpz_class &val1, const mpz_classref &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<mpz_classref, mpz_class, Op> > +{ +private: + __gmp_binary_expr<mpz_classref, mpz_class, Op> expr; +public: + __gmp_expr(const mpz_classref &val1, const mpz_class &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<mpz_classref, mpz_classref, Op> > +{ +private: + __gmp_binary_expr<mpz_classref, mpz_classref, Op> expr; +public: + __gmp_expr(const mpz_classref &val1, const mpz_classref &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; template <class Op> class __gmp_expr<__gmpq_value, __gmp_binary_expr<mpq_class, mpq_class, Op> > @@ -3510,7 +3355,76 @@ public: : expr(val1, val2) { } void eval(mpq_ptr q) const { Op::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class Op> +class __gmp_expr<__gmpf_value, __gmp_binary_expr<mpf_class, mpf_class, Op> > +{ +private: + __gmp_binary_expr<mpf_class, mpf_class, Op> expr; +public: + __gmp_expr(const mpf_class &val1, const mpf_class &val2) + : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int) const + { Op::eval(f, expr.val1.get_mpf_t(), expr.val2.get_mpf_t()); } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// simple expressions, T is a built-in numerical type + +template <class T, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_class, T, Op> > +{ +private: + __gmp_binary_expr<mpz_class, T, Op> expr; +public: + __gmp_expr(const mpz_class &val1, T val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, mpz_class, Op> > +{ +private: + __gmp_binary_expr<T, mpz_class, Op> expr; +public: + __gmp_expr(T val1, const mpz_class &val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1, expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<mpz_classref, T, Op> > +{ +private: + __gmp_binary_expr<mpz_classref, T, Op> expr; +public: + __gmp_expr(const mpz_classref &val1, T val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1.get_mpz_t(), expr.val2); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, mpz_classref, Op> > +{ +private: + __gmp_binary_expr<T, mpz_classref, Op> expr; +public: + __gmp_expr(T val1, const mpz_classref &val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { Op::eval(z, expr.val1, expr.val2.get_mpz_t()); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class Op> @@ -3522,7 +3436,7 @@ public: __gmp_expr(const mpq_class &val1, T val2) : expr(val1, val2) { } void eval(mpq_ptr q) const { Op::eval(q, expr.val1.get_mpq_t(), expr.val2); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class Op> @@ -3534,7 +3448,112 @@ public: __gmp_expr(T val1, const mpq_class &val2) : expr(val1, val2) { } void eval(mpq_ptr q) const { Op::eval(q, expr.val1, expr.val2.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class Op> +class __gmp_expr<__gmpf_value, __gmp_binary_expr<mpf_class, T, Op> > +{ +private: + __gmp_binary_expr<mpf_class, T, Op> expr; +public: + __gmp_expr(const mpf_class &val1, T val2) : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int) const + { Op::eval(f, expr.val1.get_mpf_t(), expr.val2); } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = mpf_get_default_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class Op> +class __gmp_expr<__gmpf_value, __gmp_binary_expr<T, mpf_class, Op> > +{ +private: + __gmp_binary_expr<T, mpf_class, Op> expr; +public: + __gmp_expr(T val1, const mpf_class &val2) : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int) const + { Op::eval(f, expr.val1, expr.val2.get_mpf_t()); } + unsigned long int get_prec() const + { + unsigned long int prec1 = mpf_get_default_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// compound expressions, one argument is a subexpression + +template <class T, class U, class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<mpz_class, __gmp_expr<T, U>, Op> > +{ +private: + __gmp_binary_expr<mpz_class, __gmp_expr<T, U>, Op> expr; +public: + __gmp_expr(const mpz_class &val1, const __gmp_expr<T, U> &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val2); + Op::eval(z, expr.val1.get_mpz_t(), temp.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, mpz_class, Op> > +{ +private: + __gmp_binary_expr<__gmp_expr<T, U>, mpz_class, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, const mpz_class &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val1); + Op::eval(z, temp.get_mpz_t(), expr.val2.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<mpz_classref, __gmp_expr<T, U>, Op> > +{ +private: + __gmp_binary_expr<mpz_classref, __gmp_expr<T, U>, Op> expr; +public: + __gmp_expr(const mpz_classref &val1, const __gmp_expr<T, U> &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val2); + Op::eval(z, expr.val1.get_mpz_t(), temp.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, mpz_classref, Op> > +{ +private: + __gmp_binary_expr<__gmp_expr<T, U>, mpz_classref, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, const mpz_classref &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val1); + Op::eval(z, temp.get_mpz_t(), expr.val2.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class Op> @@ -3551,7 +3570,7 @@ public: mpq_class temp(expr.val2); Op::eval(q, expr.val1.get_mpq_t(), temp.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class Op> @@ -3568,7 +3587,84 @@ public: mpq_class temp(expr.val1); Op::eval(q, temp.get_mpq_t(), expr.val2.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr +<__gmpf_value, __gmp_binary_expr<mpf_class, __gmp_expr<T, U>, Op> > +{ +private: + __gmp_binary_expr<mpf_class, __gmp_expr<T, U>, Op> expr; +public: + __gmp_expr(const mpf_class &val1, const __gmp_expr<T, U> &val2) + : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int prec) const + { + mpf_class temp(expr.val2, prec); + Op::eval(f, expr.val1.get_mpf_t(), temp.get_mpf_t()); + } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class Op> +class __gmp_expr +<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, mpf_class, Op> > +{ +private: + __gmp_binary_expr<__gmp_expr<T, U>, mpf_class, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, const mpf_class &val2) + : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int prec) const + { + mpf_class temp(expr.val1, prec); + Op::eval(f, temp.get_mpf_t(), expr.val2.get_mpf_t()); + } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// one argument is a subexpression, one is a built-in + +template <class T, class U, class V, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > +{ +private: + __gmp_binary_expr<__gmp_expr<T, U>, V, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, V val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val1); + Op::eval(z, temp.get_mpz_t(), expr.val2); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr<__gmpz_value, __gmp_binary_expr<T, __gmp_expr<U, V>, Op> > +{ +private: + __gmp_binary_expr<T, __gmp_expr<U, V>, Op> expr; +public: + __gmp_expr(T val1, const __gmp_expr<U, V> &val2) : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp(expr.val2); + Op::eval(z, expr.val1, temp.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class V, class Op> @@ -3583,7 +3679,7 @@ public: mpq_class temp(expr.val1); Op::eval(q, temp.get_mpq_t(), expr.val2); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class V, class Op> @@ -3598,7 +3694,68 @@ public: mpq_class temp(expr.val2); Op::eval(q, expr.val1, temp.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > +{ +private: + __gmp_binary_expr<__gmp_expr<T, U>, V, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, V val2) : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int prec) const + { + mpf_class temp(expr.val1, prec); + Op::eval(f, temp.get_mpf_t(), expr.val2); + } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = mpf_get_default_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr<__gmpf_value, __gmp_binary_expr<T, __gmp_expr<U, V>, Op> > +{ +private: + __gmp_binary_expr<T, __gmp_expr<U, V>, Op> expr; +public: + __gmp_expr(T val1, const __gmp_expr<U, V> &val2) : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int prec) const + { + mpf_class temp(expr.val2, prec); + Op::eval(f, expr.val1, temp.get_mpf_t()); + } + unsigned long int get_prec() const + { + unsigned long int prec1 = mpf_get_default_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// both arguments are subexpressions + +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<__gmpz_value, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > +{ +private: + __gmp_binary_expr + <__gmp_expr<T, U>, __gmp_expr<V, W>, Op> expr; +public: + __gmp_expr(const __gmp_expr<T, U> &val1, const __gmp_expr<V, W> &val2) + : expr(val1, val2) { } + void eval(mpz_ptr z) const + { + mpz_class temp1(expr.val1), temp2(expr.val2); + Op::eval(z, temp1.get_mpz_t(), temp2.get_mpz_t()); + } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <class T, class U, class V, class W, class Op> @@ -3615,147 +3772,755 @@ public: mpq_class temp1(expr.val1), temp2(expr.val2); Op::eval(q, temp1.get_mpq_t(), temp2.get_mpq_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; -// type conversions - -class __gmpq_temp +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > { private: - mpq_srcptr mp; - bool is_temp; - mpq_t temp; - - __gmpq_temp(); - __gmpq_temp(const __gmpq_temp &); - void operator=(const __gmpq_temp &); + __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> expr; public: - __gmpq_temp(const mpq_class &q) : mp(q.get_mpq_t()), is_temp(false) { } - template <class T, class U> - __gmpq_temp(const __gmp_expr<T, U> &expr) + __gmp_expr(const __gmp_expr<T, U> &val1, const __gmp_expr<V, W> &val2) + : expr(val1, val2) { } + void eval(mpf_ptr f, unsigned long int prec) const { - mpq_init(temp); - __gmp_set_expr(temp, expr); - mp = temp; - is_temp = true; + mpf_class temp1(expr.val1, prec), temp2(expr.val2, prec); + Op::eval(f, temp1.get_mpf_t(), temp2.get_mpf_t()); + } + unsigned long int get_prec() const + { + unsigned long int prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; } - ~__gmpq_temp() { if (is_temp) mpq_clear(temp); } - - mpq_srcptr get_mp() const { return mp; } -}; - -template <> -struct __gmp_resolve_expr<__gmpq_value, __gmpq_value> -{ - typedef __gmpq_value value_type; - typedef __gmpq_temp temp_type; }; -template <> -inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r) -{ - mpq_set(q, r.get_mpq_t()); -} -template <class T> -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpq_value, T> &expr) -{ - expr.eval(q); -} +/**************** Special cases ****************/ +/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments + can be done directly without first converting the mpz to mpq. + Appropriate specializations are required. */ -// functions -inline ostream & operator<<(ostream &o, const mpq_class &q) -{ - return o << q.get_mpq_t(); -} +#define __GMPZQ_DEFINE_EXPR(eval_fun) \ + \ +template <> \ +class __gmp_expr \ +<__gmpq_value, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<mpz_class, mpq_class, eval_fun> expr; \ +public: \ + __gmp_expr(const mpz_class &val1, const mpq_class &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <> \ +class __gmp_expr \ +<__gmpq_value, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<mpq_class, mpz_class, eval_fun> expr; \ +public: \ + __gmp_expr(const mpq_class &val1, const mpz_class &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr<__gmpq_value, \ + __gmp_binary_expr<mpz_class, __gmp_expr<__gmpq_value, T>, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<mpz_class, __gmp_expr<__gmpq_value, T>, eval_fun> expr; \ +public: \ + __gmp_expr(const mpz_class &val1, const __gmp_expr<__gmpq_value, T> &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr<__gmpq_value, \ + __gmp_binary_expr<mpq_class, __gmp_expr<__gmpz_value, T>, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<mpq_class, __gmp_expr<__gmpz_value, T>, eval_fun> expr; \ +public: \ + __gmp_expr(const mpq_class &val1, const __gmp_expr<__gmpz_value, T> &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr<__gmpq_value, \ + __gmp_binary_expr<__gmp_expr<__gmpz_value, T>, mpq_class, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<__gmp_expr<__gmpz_value, T>, mpq_class, eval_fun> expr; \ +public: \ + __gmp_expr(const __gmp_expr<__gmpz_value, T> &val1, const mpq_class &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr<__gmpq_value, \ + __gmp_binary_expr<__gmp_expr<__gmpq_value, T>, mpz_class, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr<__gmp_expr<__gmpq_value, T>, mpz_class, eval_fun> expr; \ +public: \ + __gmp_expr(const __gmp_expr<__gmpq_value, T> &val1, const mpz_class &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<__gmpq_value, __gmp_binary_expr \ +<__gmp_expr<__gmpz_value, T>, __gmp_expr<__gmpq_value, U>, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr \ + <__gmp_expr<__gmpz_value, T>, __gmp_expr<__gmpq_value, U>, eval_fun> expr; \ +public: \ + __gmp_expr(const __gmp_expr<__gmpz_value, T> &val1, \ + const __gmp_expr<__gmpq_value, U> &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp1(expr.val1); \ + mpq_class temp2(expr.val2); \ + eval_fun::eval(q, temp1.get_mpz_t(), temp2.get_mpq_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<__gmpq_value, __gmp_binary_expr \ +<__gmp_expr<__gmpq_value, T>, __gmp_expr<__gmpz_value, U>, eval_fun> > \ +{ \ +private: \ + __gmp_binary_expr \ + <__gmp_expr<__gmpq_value, T>, __gmp_expr<__gmpz_value, U>, eval_fun> expr; \ +public: \ + __gmp_expr(const __gmp_expr<__gmpq_value, T> &val1, \ + const __gmp_expr<__gmpz_value, U> &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp1(expr.val1); \ + mpz_class temp2(expr.val2); \ + eval_fun::eval(q, temp1.get_mpq_t(), temp2.get_mpz_t()); \ + } \ + unsigned long int get_prec() const { return mpf_get_default_prec(); } \ +}; -template <class T> -inline ostream & operator<< -(ostream &o, const __gmp_expr<__gmpq_value, T> &expr) -{ - mpq_class temp(expr); - return o << temp.get_mpq_t(); -} -inline istream & operator>>(istream &i, mpq_class &q) -{ - i >> q.get_mpq_t(); - q.canonicalize(); - return i; -} +__GMPZQ_DEFINE_EXPR(__gmp_binary_plus) +__GMPZQ_DEFINE_EXPR(__gmp_binary_minus) -// mixed-arguments functions -// type conversions +/**************** Macros for defining functions ****************/ +/* Results of operators and functions are __gmp_expr<T, U> objects. + T determines the numerical type of the expression: it can be either + __gmpz_value, __gmpq_value, or __gmpf_value. + U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>, + where V and W are the arguments' types -- they can in turn be + expressions, thus allowing to build compound expressions to any + degree of complexity. Op is a function object that must have an + eval() method accepting appropriate arguments. + When the arguments of a binary expression have different numerical + types, __gmp_resolve_expr is used to determine the "larger" type. + Actual evaluation of a __gmp_expr<T, U> object is done when it gets + assigned to an mp[zqf]_class: this is done by calling its eval() + method. */ -template <> -struct __gmp_resolve_expr<__gmpz_value, __gmpq_value> -{ - typedef __gmpq_value value_type; - typedef __gmpq_temp temp_type; -}; +// non-member operators and functions -template <> -struct __gmp_resolve_expr<__gmpq_value, __gmpz_value> -{ - typedef __gmpq_value value_type; - typedef __gmpq_temp temp_type; -}; +#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \ +} -template <> -inline void __gmp_set_expr(mpz_ptr z, const mpq_class &q) -{ - mpz_set_q(z, q.get_mpq_t()); +#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ +__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2) \ +{ \ + return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ + __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ + (expr1, expr2); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, bool b) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, b); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ +fun(bool b, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <unsigned long int, __gmp_expr<T, U>, eval_fun> >(b, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, signed char c) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, c); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ +fun(signed char c, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <signed long int, __gmp_expr<T, U>, eval_fun> >(c, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned char c) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, c); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ +fun(unsigned char c, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <unsigned long int, __gmp_expr<T, U>, eval_fun> >(c, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, signed int i) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, i); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ +fun(signed int i, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <signed long int, __gmp_expr<T, U>, eval_fun> >(i, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned int i) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, i); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ +fun(unsigned int i, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <unsigned long int, __gmp_expr<T, U>, eval_fun> >(i, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, signed short int s) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, s); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ +fun(signed short int s, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <signed long int, __gmp_expr<T, U>, eval_fun> >(s, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned short int s) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, s); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ +fun(unsigned short int s, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <unsigned long int, __gmp_expr<T, U>, eval_fun> >(s, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, signed long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, signed long int l) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, signed long int, eval_fun> >(expr, l); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<signed long int, __gmp_expr<T, U>, eval_fun> > \ +fun(signed long int l, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <signed long int, __gmp_expr<T, U>, eval_fun> >(l, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, l); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<unsigned long int, __gmp_expr<T, U>, eval_fun> > \ +fun(unsigned long int l, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <unsigned long int, __gmp_expr<T, U>, eval_fun> >(l, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, float f) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> >(expr, f); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> > \ +fun(float f, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> >(f, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, double d) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<__gmp_expr<T, U>, double, eval_fun> >(expr, d); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> > \ +fun(double d, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<double, __gmp_expr<T, U>, eval_fun> >(d, expr); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, long double, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, long double ld) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, long double, eval_fun> >(expr, ld); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<long double, __gmp_expr<T, U>, eval_fun> > \ +fun(long double ld, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <long double, __gmp_expr<T, U>, eval_fun> >(ld, expr); \ } -template <class T> -inline void __gmp_set_expr -(mpz_ptr z, const __gmp_expr<__gmpq_value, T> &expr) -{ - mpq_class temp(expr); - mpz_set_q(z, temp.get_mpq_t()); +#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, unsigned long int, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, unsigned long int, eval_fun> >(expr, l); \ } -template <> -inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z) -{ - mpq_set_z(q, z.get_mpz_t()); +#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp()); \ } -template <> -inline void __gmp_set_expr(mpq_ptr q, const mpz_classref &z) -{ - mpq_set_z(q, z.get_mpz_t()); +#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline type fun(const __gmp_expr<T, U> &expr1, \ + const __gmp_expr<V, W> &expr2) \ +{ \ + typename __gmp_resolve_expr<T, V>::temp_type temp1(expr1), temp2(expr2); \ + return eval_fun::eval(temp1.get_mp(), temp2.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr1, \ + const __gmp_expr<T, U> &expr2) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp1(expr1), temp2(expr2); \ + return eval_fun::eval(temp1.get_mp(), temp2.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, bool b) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (unsigned long int) b); \ +} \ + \ +template <class T, class U> \ +inline type fun(bool b, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((unsigned long int) b, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, signed char c) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (signed long int) c); \ +} \ + \ +template <class T, class U> \ +inline type fun(signed char c, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((signed long int) c, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, unsigned char c) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (unsigned long int) c); \ +} \ + \ +template <class T, class U> \ +inline type fun(unsigned char c, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((unsigned long int) c, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, signed int i) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (signed long int) i); \ +} \ + \ +template <class T, class U> \ +inline type fun(signed int i, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((signed long int) i, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, unsigned int i) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (unsigned long int) i); \ +} \ + \ +template <class T, class U> \ +inline type fun(unsigned int i, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((unsigned long int) i, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, signed short int s) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (signed long int) s); \ +} \ + \ +template <class T, class U> \ +inline type fun(signed short int s, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((signed long int) s, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, unsigned short int s) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (unsigned long int) s); \ +} \ + \ +template <class T, class U> \ +inline type fun(unsigned short int s, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((unsigned long int) s, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, signed long int l) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), l); \ +} \ + \ +template <class T, class U> \ +inline type fun(signed long int l, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(l, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, unsigned long int l) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), l); \ +} \ + \ +template <class T, class U> \ +inline type fun(unsigned long int l, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(l, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, float f) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), (double) f); \ +} \ + \ +template <class T, class U> \ +inline type fun(float f, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval((double) f, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, double d) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), d); \ +} \ + \ +template <class T, class U> \ +inline type fun(double d, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(d, temp.get_mp()); \ +} \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, long double ld) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(temp.get_mp(), ld); \ +} \ + \ +template <class T, class U> \ +inline type fun(long double ld, const __gmp_expr<T, U> &expr) \ +{ \ + typename __gmp_resolve_expr<T, T>::temp_type temp(expr); \ + return eval_fun::eval(ld, temp.get_mp()); \ } -template <class T> -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpz_value, T> &expr) -{ - mpz_class temp(expr); - mpq_set_z(q, temp.get_mpz_t()); + +// member operators for mpz_class + +#define __GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ + \ +template <class T, class U> \ +inline mpz_class & mpz_class::fun(const __gmp_expr<T, U> &expr) \ +{ \ + __gmpz_temp temp(expr); \ + eval_fun::eval(mp, mp, temp.get_mp()); \ + return *this; \ } -// functions +#define __GMPZN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ + \ +inline mpz_class & mpz_class::fun(bool b) \ +{ \ + eval_fun::eval(mp, mp, (unsigned long int) b); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(signed char c) \ +{ \ + eval_fun::eval(mp, mp, (signed long int) c); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(unsigned char c) \ +{ \ + eval_fun::eval(mp, mp, (unsigned long int) c); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(signed int i) \ +{ \ + eval_fun::eval(mp, mp, (signed long int) i); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(unsigned int i) \ +{ \ + eval_fun::eval(mp, mp, (unsigned long int) i); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(signed short int s) \ +{ \ + eval_fun::eval(mp, mp, (signed long int) s); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(unsigned short int s) \ +{ \ + eval_fun::eval(mp, mp, (unsigned long int) s); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(signed long int l) \ +{ \ + eval_fun::eval(mp, mp, l); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(unsigned long int l) \ +{ \ + eval_fun::eval(mp, mp, l); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(float f) \ +{ \ + eval_fun::eval(mp, mp, (double) f); \ + return *this; \ +} \ + \ +inline mpz_class & mpz_class::fun(double d) \ +{ \ + eval_fun::eval(mp, mp, d); \ + return *this; \ +} \ + \ +/* \ +inline mpz_class & mpz_class::fun(long double ld) \ +{ \ + eval_fun::eval(mp, mp, ld); \ + return *this; \ +} */ -inline mpq_class::__gmp_expr(const mpz_class &num, const mpz_class &den) -{ - mpq_init(mp); - mpz_set(mpq_numref(mp), num.get_mpz_t()); - mpz_set(mpq_denref(mp), den.get_mpz_t()); +#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMPZZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMPZN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) + +#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ + \ +inline mpz_class & mpz_class::fun(unsigned long int l) \ +{ \ + eval_fun::eval(mp, mp, l); \ + return *this; \ } -template <class T, class U> -inline mpq_class::__gmp_expr(const __gmp_expr<__gmpz_value, T> &num, - const __gmp_expr<__gmpz_value, U> &den) -{ - __gmpz_temp temp1(num), temp2(den); - mpq_init(mp); - mpz_set(mpq_numref(mp), temp1.get_mp()); - mpz_set(mpq_denref(mp), temp2.get_mp()); +#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ + \ +inline mpz_class & mpz_class::fun() \ +{ \ + eval_fun::eval(mp, mp); \ + return *this; \ +} \ + \ +inline mpz_class mpz_class::fun(int) \ +{ \ + mpz_class temp(*this); \ + eval_fun::eval(mp, mp); \ + return temp; \ } + +// member operators for mpz_classref + #define __GMPZRR_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ \ template <class T, class U> \ @@ -3845,6 +4610,32 @@ inline mpz_classref & mpz_classref::fun(long double ld) \ __GMPZRR_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ __GMPZRN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) +#define __GMPZR_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ + \ +inline mpz_classref & mpz_classref::fun(unsigned long int l) \ +{ \ + eval_fun::eval(ref, ref, l); \ + return *this; \ +} + +#define __GMPZR_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ + \ +inline mpz_classref & mpz_classref::fun() \ +{ \ + eval_fun::eval(ref, ref); \ + return *this; \ +} \ + \ +inline mpz_class mpz_classref::fun(int) \ +{ \ + mpz_class temp(*this); \ + eval_fun::eval(ref, ref); \ + return temp; \ +} + + +// member operators for mpq_class + #define __GMPQQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ \ template <class T, class U> \ @@ -3934,14 +4725,6 @@ inline mpq_class & mpq_class::fun(long double ld) \ __GMPQQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ __GMPQN_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) -#define __GMPZR_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ - \ -inline mpz_classref & mpz_classref::fun(unsigned long int l) \ -{ \ - eval_fun::eval(ref, ref, l); \ - return *this; \ -} - #define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ \ inline mpq_class & mpq_class::fun(unsigned long int l) \ @@ -3950,21 +4733,6 @@ inline mpq_class & mpq_class::fun(unsigned long int l) \ return *this; \ } -#define __GMPZR_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ - \ -inline mpz_classref & mpz_classref::fun() \ -{ \ - eval_fun::eval(ref, ref); \ - return *this; \ -} \ - \ -inline mpz_class mpz_classref::fun(int) \ -{ \ - mpz_class temp(*this); \ - eval_fun::eval(ref, ref); \ - return temp; \ -} - #define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ \ inline mpq_class & mpq_class::fun() \ @@ -3980,502 +4748,15 @@ inline mpq_class mpq_class::fun(int) \ return temp; \ } -// define operators and functions - -__GMPZR_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPZR_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPZR_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPZR_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) -__GMPZR_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) - -__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) -__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) -__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) - -__GMPZR_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPZR_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPZR_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPZR_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) - -__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - -template <class T, class U> -void __gmp_set_expr(mpf_ptr, const __gmp_expr<T, U> &); - -class __gmpf_value { }; - -// class wrapper for mpf_t - -#define __GMPFF_DECLARE_COMPOUND_OPERATOR(fun) \ - template <class T, class U> \ - __gmp_expr<__gmpf_value, __gmpf_value> & fun(const __gmp_expr<T, U> &); - -#define __GMPFN_DECLARE_COMPOUND_OPERATOR(fun) \ - __gmp_expr & fun(bool); \ - __gmp_expr & fun(signed char); \ - __gmp_expr & fun(unsigned char); \ - __gmp_expr & fun(signed int); \ - __gmp_expr & fun(unsigned int); \ - __gmp_expr & fun(signed short int); \ - __gmp_expr & fun(unsigned short int); \ - __gmp_expr & fun(signed long int); \ - __gmp_expr & fun(unsigned long int); \ - __gmp_expr & fun(float); \ - __gmp_expr & fun(double); \ - __gmp_expr & fun(long double); - -#define __GMPF_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPFF_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPFN_DECLARE_COMPOUND_OPERATOR(fun) - -#define __GMPF_DECLARE_COMPOUND_OPERATOR_UI(fun) \ - __gmp_expr & fun(unsigned long int); -#define __GMPF_DECLARE_INCREMENT_OPERATOR(fun) \ - inline __gmp_expr & fun(); \ - inline __gmp_expr fun(int); - -template <> -class __gmp_expr<__gmpf_value, __gmpf_value> -{ -private: - mpf_t mp; -public: - // size information - unsigned long int precision() const { return mpf_get_prec(mp); } - - // constructors and destructor - __gmp_expr() { mpf_init(mp); } - - __gmp_expr(const __gmp_expr &f) - { mpf_init2(mp, f.precision()); mpf_set(mp, f.mp); } - __gmp_expr(const __gmp_expr &f, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set(mp, f.mp); } - template <class T, class U> - __gmp_expr(const __gmp_expr<T, U> &expr) - { mpf_init2(mp, expr.precision()); __gmp_set_expr(mp, expr); } - template <class T, class U> - __gmp_expr(const __gmp_expr<T, U> &expr, unsigned long int precision) - { mpf_init2(mp, precision); __gmp_set_expr(mp, expr); } - - __gmp_expr(bool b) { mpf_init_set_ui(mp, b); } - __gmp_expr(bool b, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_ui(mp, b); } - - __gmp_expr(signed char c) { mpf_init_set_si(mp, c); } - __gmp_expr(signed char c, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_si(mp, c); } - __gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); } - __gmp_expr(unsigned char c, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_ui(mp, c); } - - __gmp_expr(signed int i) { mpf_init_set_si(mp, i); } - __gmp_expr(signed int i, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_si(mp, i); } - __gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); } - __gmp_expr(unsigned int i, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_ui(mp, i); } - - __gmp_expr(signed short int s) { mpf_init_set_si(mp, s); } - __gmp_expr(signed short int s, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_si(mp, s); } - __gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); } - __gmp_expr(unsigned short int s, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_ui(mp, s); } - - __gmp_expr(signed long int l) { mpf_init_set_si(mp, l); } - __gmp_expr(signed long int l, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_si(mp, l); } - __gmp_expr(unsigned long int l) { mpf_init_set_ui(mp, l); } - __gmp_expr(unsigned long int l, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_ui(mp, l); } - - __gmp_expr(float f) { mpf_init_set_d(mp, f); } - __gmp_expr(float f, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_d(mp, f); } - __gmp_expr(double d) { mpf_init_set_d(mp, d); } - __gmp_expr(double d, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_d(mp, d); } - /* - __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); } - __gmp_expr(long double ld, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_d(mp, ld); } - */ - - explicit __gmp_expr(const char *s) { mpf_init_set_str(mp, s, 0); } - __gmp_expr(const char *s, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_str(mp, s, 0); } - explicit __gmp_expr(const string &s) { mpf_init_set_str(mp, s.c_str(), 0); } - __gmp_expr(const string &s, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set_str(mp, s.c_str(), 0); } - - explicit __gmp_expr(mpf_srcptr f) - { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); } - __gmp_expr(mpf_srcptr f, unsigned long int precision) - { mpf_init2(mp, precision); mpf_set(mp, f); } - - ~__gmp_expr() { mpf_clear(mp); } - - // assignment operators - __gmp_expr & operator=(const __gmp_expr &f) - { mpf_set(mp, f.mp); return *this; } - template <class T, class U> - __gmp_expr<__gmpf_value, __gmpf_value> & operator= - (const __gmp_expr<T, U> &expr) - { __gmp_set_expr(mp, expr); return *this; } - - __gmp_expr & operator=(bool b) { mpf_set_ui(mp, b); return *this; } - - __gmp_expr & operator=(signed char c) { mpf_set_si(mp, c); return *this; } - __gmp_expr & operator=(unsigned char c) { mpf_set_ui(mp, c); return *this; } - - __gmp_expr & operator=(signed int i) { mpf_set_si(mp, i); return *this; } - __gmp_expr & operator=(unsigned int i) { mpf_set_ui(mp, i); return *this; } - - __gmp_expr & operator=(signed short int s) - { mpf_set_si(mp, s); return *this; } - __gmp_expr & operator=(unsigned short int s) - { mpf_set_ui(mp, s); return *this; } - - __gmp_expr & operator=(signed long int l) - { mpf_set_si(mp, l); return *this; } - __gmp_expr & operator=(unsigned long int l) - { mpf_set_ui(mp, l); return *this; } - - __gmp_expr & operator=(float f) { mpf_set_d(mp, f); return *this; } - __gmp_expr & operator=(double d) { mpf_set_d(mp, d); return *this; } - /* - __gmp_expr & operator=(long double ld) { mpf_set_ld(mp, ld); return *this; } - */ - - __gmp_expr & operator=(const char *s) - { mpf_set_str(mp, s, 0); return *this; } - __gmp_expr & operator=(const string &s) - { mpf_set_str(mp, s.c_str(), 0); return *this; } - - // string input/output functions - void set_str_base(const string &s, int base) - { mpf_set_str(mp, s.c_str(), base); } - string get_str_base(int base) const - { - mp_exp_t expo; - __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, 0, mp)); - - // cancel terminating zeros - for (size_t i=strlen(temp.str)-1; temp.str[i]=='0' && i>0; --i) - temp.str[i] = '\0'; - - if (*temp.str == '-') - return "-0." + string(temp.str+1) + "e"; // the exponent? - else - return "0." + string(temp.str) + "e"; // the exponent? - } - - // conversion functions - mpf_srcptr get_mpf_t() const { return mp; } - mpf_ptr get_mpf_t() { return mp; } - - // signed long int get_si() const { return mpf_get_si(mp); } - // unsigned long int get_ui() const { return mpf_get_ui(mp); } - double get_d() const { return mpf_get_d(mp); } // should be long double - - // compound assignments - __GMPF_DECLARE_COMPOUND_OPERATOR(operator+=) - __GMPF_DECLARE_COMPOUND_OPERATOR(operator-=) - __GMPF_DECLARE_COMPOUND_OPERATOR(operator*=) - __GMPF_DECLARE_COMPOUND_OPERATOR(operator/=) - - __GMPF_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) - __GMPF_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) - - __GMPF_DECLARE_INCREMENT_OPERATOR(operator++) - __GMPF_DECLARE_INCREMENT_OPERATOR(operator--) -}; - -typedef __gmp_expr<__gmpf_value, __gmpf_value> mpf_class; - -// unary expressions - -template <class Op> -class __gmp_expr<__gmpf_value, __gmp_unary_expr<mpf_class, Op> > -{ -private: - __gmp_unary_expr<mpf_class, Op> expr; -public: - __gmp_expr(const mpf_class &val) : expr(val) { } - void eval(mpf_ptr f, unsigned long int) const - { Op::eval(f, expr.val.get_mpf_t()); } - unsigned long int precision() const - { return mpf_get_prec(expr.val.get_mpf_t()); } -}; - -template <class T, class U, class Op> -class __gmp_expr<__gmpf_value, __gmp_unary_expr<__gmp_expr<T, U>, Op> > -{ -private: - __gmp_unary_expr<__gmp_expr<T, U>, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val) : expr(val) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp(expr.val, precision); - Op::eval(f, temp.get_mpf_t()); - } - unsigned long int precision() const { return expr.val.precision(); } -}; - -// binary expressions - -template <class Op> -class __gmp_expr<__gmpf_value, __gmp_binary_expr<mpf_class, mpf_class, Op> > -{ -private: - __gmp_binary_expr<mpf_class, mpf_class, Op> expr; -public: - __gmp_expr(const mpf_class &val1, const mpf_class &val2) - : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int) const - { Op::eval(f, expr.val1.get_mpf_t(), expr.val2.get_mpf_t()); } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class Op> -class __gmp_expr<__gmpf_value, __gmp_binary_expr<mpf_class, T, Op> > -{ -private: - __gmp_binary_expr<mpf_class, T, Op> expr; -public: - __gmp_expr(const mpf_class &val1, T val2) : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int) const - { Op::eval(f, expr.val1.get_mpf_t(), expr.val2); } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = mpf_get_default_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class Op> -class __gmp_expr<__gmpf_value, __gmp_binary_expr<T, mpf_class, Op> > -{ -private: - __gmp_binary_expr<T, mpf_class, Op> expr; -public: - __gmp_expr(T val1, const mpf_class &val2) : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int) const - { Op::eval(f, expr.val1, expr.val2.get_mpf_t()); } - unsigned long int precision() const - { - unsigned long int prec1 = mpf_get_default_prec(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpf_value, __gmp_binary_expr<mpf_class, __gmp_expr<T, U>, Op> > -{ -private: - __gmp_binary_expr<mpf_class, __gmp_expr<T, U>, Op> expr; -public: - __gmp_expr(const mpf_class &val1, const __gmp_expr<T, U> &val2) - : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp(expr.val2, precision); - Op::eval(f, expr.val1.get_mpf_t(), temp.get_mpf_t()); - } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class U, class Op> -class __gmp_expr -<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, mpf_class, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, mpf_class, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, const mpf_class &val2) - : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp(expr.val1, precision); - Op::eval(f, temp.get_mpf_t(), expr.val2.get_mpf_t()); - } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class U, class V, class Op> -class __gmp_expr<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, V, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, V val2) : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp(expr.val1, precision); - Op::eval(f, temp.get_mpf_t(), expr.val2); - } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = mpf_get_default_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class U, class V, class Op> -class __gmp_expr<__gmpf_value, __gmp_binary_expr<T, __gmp_expr<U, V>, Op> > -{ -private: - __gmp_binary_expr<T, __gmp_expr<U, V>, Op> expr; -public: - __gmp_expr(T val1, const __gmp_expr<U, V> &val2) : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp(expr.val2, precision); - Op::eval(f, expr.val1, temp.get_mpf_t()); - } - unsigned long int precision() const - { - unsigned long int prec1 = mpf_get_default_prec(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template <class T, class U, class V, class W, class Op> -class __gmp_expr -<__gmpf_value, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > -{ -private: - __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> expr; -public: - __gmp_expr(const __gmp_expr<T, U> &val1, const __gmp_expr<V, W> &val2) - : expr(val1, val2) { } - void eval(mpf_ptr f, unsigned long int precision) const - { - mpf_class temp1(expr.val1, precision), temp2(expr.val2, precision); - Op::eval(f, temp1.get_mpf_t(), temp2.get_mpf_t()); - } - unsigned long int precision() const - { - unsigned long int prec1 = expr.val1.precision(), - prec2 = expr.val2.precision(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -// type conversions - -class __gmpf_temp -{ -private: - mpf_srcptr mp; - bool is_temp; - mpf_t temp; - - __gmpf_temp(); - __gmpf_temp(const __gmpf_temp &); - void operator=(const __gmpf_temp &); -public: - __gmpf_temp(const mpf_class &f) : mp(f.get_mpf_t()), is_temp(false) { } - __gmpf_temp(const mpf_class &f, unsigned long int) - : mp(f.get_mpf_t()), is_temp(false) { } - template <class T, class U> - __gmpf_temp(const __gmp_expr<T, U> &expr) - { - mpf_init2(temp, expr.precision()); - __gmp_set_expr(temp, expr); - mp = temp; - is_temp = true; - } - template <class T, class U> - __gmpf_temp(const __gmp_expr<T, U> &expr, unsigned long int precision) - { - mpf_init2(temp, precision); - __gmp_set_expr(temp, expr); - mp = temp; - is_temp = true; - } - ~__gmpf_temp() { if (is_temp) mpf_clear(temp); } - - mpf_srcptr get_mp() const { return mp; } -}; - -template <> -struct __gmp_resolve_expr<__gmpf_value, __gmpf_value> -{ - typedef __gmpf_value value_type; - typedef __gmpf_temp temp_type; -}; - -template <> -inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g) -{ - mpf_set(f, g.get_mpf_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpf_value, T> &expr) -{ - expr.eval(f, mpf_get_prec(f)); -} - -// functions - -inline ostream & operator<<(ostream &o, const mpf_class &f) -{ - return o << f.get_mpf_t(); -} - -template <class T> -inline ostream & operator<< -(ostream &o, const __gmp_expr<__gmpf_value, T> &expr) -{ - mpf_class temp(expr); - return o << temp.get_mpf_t(); -} - -inline istream & operator>>(istream &i, mpf_class &f) -{ - return i >> f.get_mpf_t(); -} +// member operators for mpf_class #define __GMPFF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ \ template <class T, class U> \ inline mpf_class & mpf_class::fun(const __gmp_expr<T, U> &expr) \ { \ - __gmpf_temp temp(expr, precision()); \ + __gmpf_temp temp(expr, get_prec()); \ eval_fun::eval(mp, mp, temp.get_mp()); \ return *this; \ } @@ -4582,7 +4863,95 @@ inline mpf_class mpf_class::fun(int) \ return temp; \ } -// define operators and functions + +/**************** Arithmetic operators and functions ****************/ + +// non-member operators and functions + +__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus) +__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus) +__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com) + +__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus) +__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus) +__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies) +__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides) +__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus) +__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and) +__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior) +__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor) + +__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift) +__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift) + +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, __gmp_binary_not_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, __gmp_binary_less_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, \ + __gmp_binary_greater_equal) + +__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function) +__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function) +__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function) +__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function) +__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function) +__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function) + +__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, compare, __gmp_cmp_function) + +// member operators for mpz_class + +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) + +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) +__GMPZZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) + +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpz_classref + +__GMPZR_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPZR_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPZR_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPZR_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) +__GMPZR_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) + +__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) +__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) +__GMPZRR_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) + +__GMPZR_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPZR_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPZR_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPZR_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpq_class + +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) + +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpf_class __GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) __GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) @@ -4595,6 +4964,9 @@ __GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) __GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) __GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +/**************** Class wrapper for gmp_randstate_t ****************/ + class __gmp_urandomb_value { }; class __gmp_urandomm_value { }; @@ -4607,7 +4979,7 @@ private: public: __gmp_expr(gmp_randstate_t s, unsigned long int l) : state(s), bits(l) { } void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <> @@ -4620,7 +4992,7 @@ public: __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { } void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, range.get_mpz_t()); } - unsigned long int precision() const { return mpf_get_default_prec(); } + unsigned long int get_prec() const { return mpf_get_default_prec(); } }; template <> @@ -4632,8 +5004,8 @@ private: public: __gmp_expr(gmp_randstate_t s, unsigned long int l) : state(s), bits(l) { } void eval(mpf_ptr f, unsigned long int prec) const - { __gmp_rand_function::eval(f, state, (bits>0) ? precision() : prec); } - unsigned long int precision() const + { __gmp_rand_function::eval(f, state, (bits>0) ? get_prec() : prec); } + unsigned long int get_prec() const { if (bits == 0) return mpf_get_default_prec(); @@ -4642,8 +5014,6 @@ public: } }; -// class wrapper for gmp_randstate_t - class gmp_randclass { private: @@ -4652,10 +5022,18 @@ public: // constructors and destructor gmp_randclass(gmp_randalg_t alg, unsigned long int size) { - if (alg != GMP_RAND_ALG_LC) - ; // complain - gmp_randinit(state, alg, size); + switch (alg) + { + case GMP_RAND_ALG_LC: // no other cases for now + default: + gmp_randinit(state, alg, size); + break; + } } + gmp_randclass(void (*f)(gmp_randstate_t, mpz_srcptr, + unsigned long int, unsigned long int), + mpz_class z, unsigned long int l1, unsigned long int l2) + { f(state, z.get_mpz_t(), l1, l2); } ~gmp_randclass() { gmp_randclear(state); } @@ -4676,96 +5054,68 @@ public: get_z_range(const mpz_class &z) { return __gmp_expr<__gmpz_value, __gmp_urandomm_value>(state, z); } __gmp_expr<__gmpf_value, __gmp_urandomb_value> - get_f(unsigned long int precision = 0) - { return __gmp_expr<__gmpf_value, __gmp_urandomb_value>(state, precision); } -}; - -// type conversions - -template <> -struct __gmp_resolve_expr<__gmpz_value, __gmpf_value> -{ - typedef __gmpf_value value_type; - typedef __gmpf_temp temp_type; -}; - -template <> -struct __gmp_resolve_expr<__gmpf_value, __gmpz_value> -{ - typedef __gmpf_value value_type; - typedef __gmpf_temp temp_type; + get_f(unsigned long int prec = 0) + { return __gmp_expr<__gmpf_value, __gmp_urandomb_value>(state, prec); } }; -template <> -struct __gmp_resolve_expr<__gmpq_value, __gmpf_value> -{ - typedef __gmpf_value value_type; - typedef __gmpf_temp temp_type; -}; -template <> -struct __gmp_resolve_expr<__gmpf_value, __gmpq_value> -{ - typedef __gmpf_value value_type; - typedef __gmpf_temp temp_type; -}; - -template <class T> -inline void __gmp_set_expr(mpz_ptr z, const mpf_class &f) -{ - mpz_set_f(z, f.get_mpf_t()); -} +/**************** #undef all private macros ****************/ + +#undef __GMPZQ_DEFINE_EXPR + +#undef __GMP_DEFINE_UNARY_FUNCTION +#undef __GMP_DEFINE_BINARY_FUNCTION +#undef __GMP_DEFINE_BINARY_FUNCTION_UI +#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION +#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION + +#undef __GMPZZ_DECLARE_COMPOUND_OPERATOR +#undef __GMPZN_DECLARE_COMPOUND_OPERATOR +#undef __GMPZ_DECLARE_COMPOUND_OPERATOR +#undef __GMPZ_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMPZ_DECLARE_INCREMENT_OPERATOR + +#undef __GMPZZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPZN_DEFINE_COMPOUND_OPERATOR +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPZ_DEFINE_INCREMENT_OPERATOR + +#undef __GMPZRR_DECLARE_COMPOUND_OPERATOR +#undef __GMPZRN_DECLARE_COMPOUND_OPERATOR +#undef __GMPZR_DECLARE_COMPOUND_OPERATOR +#undef __GMPZR_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMPZR_DECLARE_INCREMENT_OPERATOR + +#undef __GMPZRR_DEFINE_COMPOUND_OPERATOR +#undef __GMPZRN_DEFINE_COMPOUND_OPERATOR +#undef __GMPZR_DEFINE_COMPOUND_OPERATOR +#undef __GMPZR_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPZR_DEFINE_INCREMENT_OPERATOR + +#undef __GMPQQ_DECLARE_COMPOUND_OPERATOR +#undef __GMPQN_DECLARE_COMPOUND_OPERATOR +#undef __GMPQ_DECLARE_COMPOUND_OPERATOR +#undef __GMPQ_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMPQ_DECLARE_INCREMENT_OPERATOR + +#undef __GMPQQ_DEFINE_COMPOUND_OPERATOR +#undef __GMPQN_DEFINE_COMPOUND_OPERATOR +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPQ_DEFINE_INCREMENT_OPERATOR + +#undef __GMPFF_DECLARE_COMPOUND_OPERATOR +#undef __GMPFN_DECLARE_COMPOUND_OPERATOR +#undef __GMPF_DECLARE_COMPOUND_OPERATOR +#undef __GMPF_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMPF_DECLARE_INCREMENT_OPERATOR + +#undef __GMPFF_DEFINE_COMPOUND_OPERATOR +#undef __GMPFN_DEFINE_COMPOUND_OPERATOR +#undef __GMPF_DEFINE_COMPOUND_OPERATOR +#undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPF_DEFINE_INCREMENT_OPERATOR -template <class T> -inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<__gmpf_value, T> &expr) -{ - mpf_class temp(expr); - mpz_set_f(z, temp.get_mpf_t()); -} - -template <class T> -inline void __gmp_set_expr(mpq_ptr q, const mpf_class &f) -{ - mpq_set_f(q, f.get_mpf_t()); -} - -template <class T> -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<__gmpf_value, T> &expr) -{ - mpf_class temp(expr); - mpq_set_f(q, temp.get_mpf_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const mpz_class &z) -{ - mpf_set_z(f, z.get_mpz_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const mpz_classref &z) -{ - mpf_set_z(f, z.get_mpz_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpz_value, T> &expr) -{ - mpz_class temp(expr); - mpf_set_z(f, temp.get_mpz_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const mpq_class &q) -{ - mpf_set_q(f, q.get_mpq_t()); -} - -template <class T> -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<__gmpq_value, T> &expr) -{ - mpq_class temp(expr); - mpf_set_q(f, temp.get_mpq_t()); -} #endif /* __GMP_PLUSPLUS__ */ |