diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,13 @@ PURPOSE "Required for building KCalc." ) +find_package(MPFR) +set_package_properties(MPFR PROPERTIES + DESCRIPTION "The GNU Multiple Precision Floating-Point Reliable Library" + URL "https://www.mpfr.org/" + TYPE RECOMMENDED +) + include(CheckTypeSize) include(CheckIncludeFiles) @@ -118,9 +125,13 @@ KF5::XmlGui KF5::Crash ${GMP_LIBRARIES} - ${MPFR_LIBRARIES} ) +if(MPFR_FOUND) + add_definitions(-DKNUMBER_USE_MPFR) + target_link_libraries(kdeinit_kcalc ${MPFR_LIBRARIES}) +endif(MPFR_FOUND) + install(TARGETS kdeinit_kcalc ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) target_link_libraries( kcalc kdeinit_kcalc ) diff --git a/config-kcalc.h.cmake b/config-kcalc.h.cmake --- a/config-kcalc.h.cmake +++ b/config-kcalc.h.cmake @@ -24,3 +24,5 @@ /* The size of a `unsigned long', as computed by sizeof. */ #define SIZEOF_UNSIGNED_LONG ${SIZEOF_UNSIGNED_LONG} + +#define HAVE_LONG_DOUBLE 1 diff --git a/knumber/knumber.cpp b/knumber/knumber.cpp --- a/knumber/knumber.cpp +++ b/knumber/knumber.cpp @@ -210,7 +210,11 @@ void KNumber::setDefaultFloatPrecision(int precision) { // Need to transform decimal digits into binary digits const unsigned long int bin_prec = static_cast(double(precision) * M_LN10 / M_LN2 + 1); +#ifdef KNUMBER_USE_MPFR + mpfr_set_default_prec(static_cast(bin_prec)); +#else mpf_set_default_prec(bin_prec); +#endif } //------------------------------------------------------------------------------ diff --git a/knumber/knumber_float.h b/knumber/knumber_float.h --- a/knumber/knumber_float.h +++ b/knumber/knumber_float.h @@ -19,6 +19,7 @@ #ifndef KNUMBER_FLOAT_H_ #define KNUMBER_FLOAT_H_ +#include #include "knumber_base.h" class KNumber; @@ -44,7 +45,12 @@ explicit knumber_float(long double value); #endif +#ifdef KNUMBER_USE_MPFR + explicit knumber_float(mpfr_t mpfr); +#else explicit knumber_float(mpf_t mpf); +#endif + ~knumber_float() override; private: @@ -120,14 +126,33 @@ knumber_base *clone() override; private: +#ifdef KNUMBER_USE_MPFR + knumber_base *ensureIsValid(mpfr_ptr mpfr); + + template + knumber_base *execute_mpfr_func(); + + template + knumber_base *execute_mpfr_func(); + + template + knumber_base *execute_mpfr_func(mpfr_srcptr op); + + mpfr_ptr initialized_mpfr(); +#else template knumber_base *execute_libc_func(double x); template knumber_base *execute_libc_func(double x, double y); +#endif private: +#ifdef KNUMBER_USE_MPFR + mpfr_t mpfr_; +#else mpf_t mpf_; +#endif }; } diff --git a/knumber/knumber_float.cpp b/knumber/knumber_float.cpp --- a/knumber/knumber_float.cpp +++ b/knumber/knumber_float.cpp @@ -16,7 +16,6 @@ along with this program. If not, see . */ -#include #include "knumber_integer.h" #include "knumber_float.h" #include "knumber_fraction.h" @@ -47,6 +46,39 @@ const mpfr_prec_t knumber_float::precision = 1024; #endif +#ifdef KNUMBER_USE_MPFR +knumber_base *knumber_float::ensureIsValid(mpfr_ptr mpfr) { + if (mpfr_nan_p(mpfr)) { + knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); + delete this; + return e; + } else if (mpfr_inf_p(mpfr)) { + knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); + delete this; + return e; + } else { + return this; + } +} + +template +knumber_base *knumber_float::execute_mpfr_func() { + F(mpfr_, mpfr_); + return ensureIsValid(mpfr_); +} + +template +knumber_base *knumber_float::execute_mpfr_func() { + F(mpfr_, mpfr_, rounding_mode); + return ensureIsValid(mpfr_); +} + +template +knumber_base *knumber_float::execute_mpfr_func(mpfr_srcptr op) { + F(mpfr_, mpfr_, op, rounding_mode); + return ensureIsValid(mpfr_); +} +#else template knumber_base *knumber_float::execute_libc_func(double x) { const double r = F(x); @@ -80,14 +112,19 @@ return this; } } +#endif //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::knumber_float(const QString &s) { +#ifdef KNUMBER_USE_MPFR + mpfr_set_str(initialized_mpfr(), s.toLatin1().constData(), 10, rounding_mode); +#else mpf_init(mpf_); - mpf_set_str(mpf_, s.toLatin1().constData(), 10); + mpf_set_str(mpf_, s.toLatin1().constData(), 10); +#endif } //------------------------------------------------------------------------------ @@ -98,7 +135,11 @@ Q_ASSERT(!isinf(value)); Q_ASSERT(!isnan(value)); +#ifdef KNUMBER_USE_MPFR + mpfr_set_d(initialized_mpfr(), value, rounding_mode); +#else mpf_init_set_d(mpf_, value); +#endif } #ifdef HAVE_LONG_DOUBLE @@ -110,43 +151,69 @@ Q_ASSERT(!isinf(value)); Q_ASSERT(!isnan(value)); +#ifdef KNUMBER_USE_MPFR + mpfr_set_ld(initialized_mpfr(), value, rounding_mode); +#else mpf_init_set_d(mpf_, value); +#endif } #endif +#ifdef KNUMBER_USE_MPFR +//------------------------------------------------------------------------------ +// Name: +//------------------------------------------------------------------------------ +knumber_float::knumber_float(mpfr_t mpfr) { + + mpfr_set(initialized_mpfr(), mpfr, rounding_mode); +} +#else //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::knumber_float(mpf_t mpf) { mpf_init(mpf_); mpf_set(mpf_, mpf); } +#endif //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::knumber_float(const knumber_float *value) { +#ifdef KNUMBER_USE_MPFR + mpfr_set(initialized_mpfr(), value->mpfr_, rounding_mode); +#else mpf_init_set(mpf_, value->mpf_); +#endif } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::knumber_float(const knumber_integer *value) { +#ifdef KNUMBER_USE_MPFR + mpfr_set_z(initialized_mpfr(), value->mpz_, rounding_mode); +#else mpf_init(mpf_); mpf_set_z(mpf_, value->mpz_); +#endif } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::knumber_float(const knumber_fraction *value) { +#ifdef KNUMBER_USE_MPFR + mpfr_set_q(initialized_mpfr(), value->mpq_, rounding_mode); +#else mpf_init(mpf_); mpf_set_q(mpf_, value->mpq_); +#endif } //------------------------------------------------------------------------------ @@ -157,12 +224,23 @@ return new knumber_float(this); } +#ifdef KNUMBER_USE_MPFR +mpfr_ptr knumber_float::initialized_mpfr() { + mpfr_init2(mpfr_, mpfr_get_default_prec()); + return mpfr_; +} +#endif + //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_float::~knumber_float() { +#ifdef KNUMBER_USE_MPFR + mpfr_clear(mpfr_); +#else mpf_clear(mpf_); +#endif } //------------------------------------------------------------------------------ @@ -174,7 +252,11 @@ knumber_float f(p); return add(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + mpfr_add(mpfr_, mpfr_, p->mpfr_, rounding_mode); +#else mpf_add(mpf_, mpf_, p->mpf_); +#endif return this; } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); @@ -198,7 +280,11 @@ knumber_float f(p); return sub(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + mpfr_sub(mpfr_, mpfr_, p->mpfr_, rounding_mode); +#else mpf_sub(mpf_, mpf_, p->mpf_); +#endif return this; } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); @@ -222,7 +308,11 @@ knumber_float f(p); return mul(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + mpfr_mul(mpfr_, mpfr_, p->mpfr_, rounding_mode); +#else mpf_mul(mpf_, mpf_, p->mpf_); +#endif return this; } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); @@ -266,7 +356,11 @@ knumber_float f(p); return div(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + mpfr_div(mpfr_, mpfr_, p->mpfr_, rounding_mode); +#else mpf_div(mpf_, mpf_, p->mpf_); +#endif return this; } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); @@ -347,7 +441,12 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::neg() { +#ifdef KNUMBER_USE_MPFR + mpfr_neg(mpfr_, mpfr_, rounding_mode); +#else mpf_neg(mpf_, mpf_); +#endif + return this; } @@ -365,7 +464,12 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::abs() { +#ifdef KNUMBER_USE_MPFR + mpfr_abs(mpfr_, mpfr_, rounding_mode); +#else mpf_abs(mpf_, mpf_); +#endif + return this; } @@ -380,11 +484,7 @@ } #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_sqrt(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); + mpfr_sqrt(mpfr_, mpfr_, rounding_mode); #else mpf_sqrt(mpf_, mpf_); #endif @@ -397,11 +497,7 @@ knumber_base *knumber_float::cbrt() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_cbrt(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); + return execute_mpfr_func< ::mpfr_cbrt>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -414,8 +510,8 @@ return execute_libc_func< ::cbrt>(x); #endif } -#endif return this; +#endif } //------------------------------------------------------------------------------ @@ -439,12 +535,7 @@ knumber_base *knumber_float::sin() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_sin(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_sin>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -462,12 +553,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::floor() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_floor(mpfr, mpfr); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_floor>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -484,12 +570,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::ceil() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_ceil(mpfr, mpfr); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_ceil>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -506,12 +587,7 @@ knumber_base *knumber_float::cos() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_cos(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_cos>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -529,12 +605,7 @@ knumber_base *knumber_float::tan() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_tan(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_tan>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -550,18 +621,17 @@ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_float::asin() { +#ifdef KNUMBER_USE_MPFR + if (mpfr_cmp_d(mpfr_, 1.0) > 0 || mpfr_cmp_d(mpfr_, -1.0) < 0) { +#else if(mpf_cmp_d(mpf_, 1.0) > 0 || mpf_cmp_d(mpf_, -1.0) < 0) { +#endif delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_asin(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_asin>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -577,18 +647,17 @@ // Name: //------------------------------------------------------------------------------s knumber_base *knumber_float::acos() { +#ifdef KNUMBER_USE_MPFR + if (mpfr_cmp_d(mpfr_, 1.0) > 0 || mpfr_cmp_d(mpfr_, -1.0) < 0) { +#else if(mpf_cmp_d(mpf_, 1.0) > 0 || mpf_cmp_d(mpf_, -1.0) < 0) { +#endif delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_acos(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_acos>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -606,12 +675,7 @@ knumber_base *knumber_float::atan() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_atan(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_atan>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -628,12 +692,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::sinh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_sinh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_sinh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::sinh>(x); @@ -646,12 +705,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::cosh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_cosh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_cosh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::cosh>(x); @@ -663,12 +717,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::tanh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_tanh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_tanh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::tanh>(x); @@ -681,12 +730,7 @@ knumber_base *knumber_float::tgamma() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_gamma(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_gamma>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -705,12 +749,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::asinh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_asinh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_asinh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::asinh>(x); @@ -722,12 +761,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::acosh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_acosh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_acosh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::acosh>(x); @@ -739,12 +773,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::atanh() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_atanh(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_atanh>(); #else const double x = mpf_get_d(mpf_); return execute_libc_func< ::atanh>(x); @@ -757,18 +786,30 @@ knumber_base *knumber_float::pow(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + mpfr_pow_ui(mpfr_, mpfr_, mpz_get_ui(p->mpz_), rounding_mode); +#else mpf_pow_ui(mpf_, mpf_, mpz_get_ui(p->mpz_)); +#endif if(p->sign() < 0) { return reciprocal(); } else { return this; } } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + return execute_mpfr_func< ::mpfr_pow>(p->mpfr_); +#else return execute_libc_func< ::pow>(mpf_get_d(mpf_), mpf_get_d(p->mpf_)); +#endif } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); +#ifdef KNUMBER_USE_MPFR + return execute_mpfr_func< ::mpfr_pow>(f.mpfr_); +#else return execute_libc_func< ::pow>(mpf_get_d(mpf_), mpf_get_d(f.mpf_)); +#endif } else if(knumber_error *const p = dynamic_cast(rhs)) { if(p->sign() > 0) { knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); @@ -798,7 +839,11 @@ knumber_float f(p); return compare(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { +#ifdef KNUMBER_USE_MPFR + return mpfr_cmp(mpfr_, p->mpfr_); +#else return mpf_cmp(mpf_, p->mpf_); +#endif } else if(knumber_fraction *const p = dynamic_cast(rhs)) { knumber_float f(p); return compare(&f); @@ -818,19 +863,36 @@ QString knumber_float::toString(int precision) const { size_t size; + +#ifdef KNUMBER_USE_MPFR + if (precision > 0) { + size = static_cast(mpfr_snprintf(nullptr, 0, "%.*Rg", precision, mpfr_) + 1); + } else { + size = static_cast(mpfr_snprintf(nullptr, 0, "%.Rg", mpfr_) + 1); + } +#else if (precision > 0) { size = gmp_snprintf(nullptr, 0, "%.*Fg", precision, mpf_) + 1; } else { size = gmp_snprintf(nullptr, 0, "%.Fg", mpf_) + 1; } +#endif QScopedArrayPointer buf(new char[size]); +#ifdef KNUMBER_USE_MPFR + if (precision > 0) { + mpfr_snprintf(&buf[0], size, "%.*Rg", precision, mpfr_); + } else { + mpfr_snprintf(&buf[0], size, "%.Rg", mpfr_); + } +#else if (precision > 0) { gmp_snprintf(&buf[0], size, "%.*Fg", precision, mpf_); } else { gmp_snprintf(&buf[0], size, "%.Fg", mpf_); } +#endif return QLatin1String(&buf[0]); } @@ -840,47 +902,62 @@ //------------------------------------------------------------------------------ bool knumber_float::is_integer() const { +#ifdef KNUMBER_USE_MPFR + return mpfr_integer_p(mpfr_) != 0; +#else return mpf_integer_p(mpf_) != 0; +#endif } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ bool knumber_float::is_zero() const { +#ifdef KNUMBER_USE_MPFR + return mpfr_zero_p(mpfr_); +#else return mpf_sgn(mpf_) == 0; +#endif } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ int knumber_float::sign() const { +#ifdef KNUMBER_USE_MPFR + return mpfr_sgn(mpfr_); +#else return mpf_sgn(mpf_); +#endif } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_float::reciprocal() { +#ifdef KNUMBER_USE_MPFR + mpfr_t mpfr; + mpfr_init_set_d(mpfr, 1.0, rounding_mode); + mpfr_div(mpfr_, mpfr, mpfr_, rounding_mode); + mpfr_clear(mpfr); +#else mpf_t mpf; mpf_init_set_d(mpf, 1.0); mpf_div(mpf_, mpf, mpf_); +#endif + return this; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_float::log2() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_log2(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_log2>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -897,12 +974,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::log10() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_log10(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_log10>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -919,12 +991,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::ln() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_log(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_log>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -941,12 +1008,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::exp2() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_exp2(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_exp2>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -963,12 +1025,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::exp10() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_exp10(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_exp10>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { @@ -985,12 +1042,7 @@ //------------------------------------------------------------------------------ knumber_base *knumber_float::exp() { #ifdef KNUMBER_USE_MPFR - mpfr_t mpfr; - mpfr_init_set_f(mpfr, mpf_, rounding_mode); - mpfr_exp(mpfr, mpfr, rounding_mode); - mpfr_get_f(mpf_, mpfr, rounding_mode); - mpfr_clear(mpfr); - return this; + return execute_mpfr_func< ::mpfr_exp>(); #else const double x = mpf_get_d(mpf_); if(isinf(x)) { diff --git a/knumber/knumber_integer.cpp b/knumber/knumber_integer.cpp --- a/knumber/knumber_integer.cpp +++ b/knumber/knumber_integer.cpp @@ -99,7 +99,18 @@ //------------------------------------------------------------------------------ knumber_integer::knumber_integer(const knumber_float *value) { mpz_init(mpz_); + +#ifdef KNUMBER_USE_MPFR + mpf_t mpf; + mpf_init(mpf); + + mpfr_get_f(mpf, value->mpfr_, knumber_float::rounding_mode); + mpz_set_f(mpz_, mpf); + + mpf_clear(mpf); +#else mpz_set_f(mpz_, value->mpf_); +#endif } //------------------------------------------------------------------------------ diff --git a/knumber/tests/CMakeLists.txt b/knumber/tests/CMakeLists.txt --- a/knumber/tests/CMakeLists.txt +++ b/knumber/tests/CMakeLists.txt @@ -2,8 +2,13 @@ include(ECMAddTests) +list(APPEND knumbertest_LIBS Qt5::Core ${GMP_LIBRARIES}) + +if(MPFR_FOUND) + list(APPEND knumbertest_LIBS ${MPFR_LIBRARIES}) +endif(MPFR_FOUND) + ecm_add_test(knumbertest.cpp ${libknumber_la_SRCS} - LINK_LIBRARIES Qt5::Core ${GMP_LIBRARIES} + LINK_LIBRARIES ${knumbertest_LIBS} TEST_NAME knumbertest ) -