diff options
Diffstat (limited to 'kcalc/knumber/knumber_priv.cpp')
-rw-r--r-- | kcalc/knumber/knumber_priv.cpp | 1083 |
1 files changed, 1083 insertions, 0 deletions
diff --git a/kcalc/knumber/knumber_priv.cpp b/kcalc/knumber/knumber_priv.cpp new file mode 100644 index 0000000..1326d44 --- /dev/null +++ b/kcalc/knumber/knumber_priv.cpp @@ -0,0 +1,1083 @@ +/* This file is part of the KDE libraries + Copyright (c) 2005 Klaus Niederkrueger <kniederk@math.uni-koeln.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <math.h> +#include <config.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <qregexp.h> +#include <qstring.h> + +#include "knumber_priv.h" + +_knumerror::_knumerror(_knumber const & num) +{ + switch(num.type()) { + case SpecialType: + _error = dynamic_cast<_knumerror const &>(num)._error; + break; + case IntegerType: + case FractionType: + case FloatType: + // What should I do here? + break; + } +} + + + +_knuminteger::_knuminteger(unsigned long long int num) +{ + mpz_init(_mpz); +#if SIZEOF_UNSIGNED_LONG == 8 + mpz_init_set_ui(_mpz, static_cast<unsigned long int>(num)); +#elif SIZEOF_UNSIGNED_LONG == 4 + mpz_set_ui(_mpz, static_cast<unsigned long int>(num >> 32)); + mpz_mul_2exp(_mpz, _mpz, 32); + mpz_add_ui(_mpz, _mpz, static_cast<unsigned long int>(num)); +#else +#error "SIZEOF_UNSIGNED_LONG is a unhandled case" +#endif +} + + +_knuminteger::_knuminteger(_knumber const & num) +{ + mpz_init(_mpz); + + switch(num.type()) { + case IntegerType: + mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfraction::_knumfraction(_knumber const & num) +{ + mpq_init(_mpq); + + switch(num.type()) { + case IntegerType: + mpq_set_z(_mpq, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfloat::_knumfloat(_knumber const & num) +{ + mpf_init(_mpf); + + switch(num.type()) { + case IntegerType: + mpf_set_z(_mpf, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpf_set_q(_mpf, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); + break; + case SpecialType: + // What should I do here? + break; + } +} + + + +_knumerror::_knumerror(QString const & num) +{ + if (num == "nan") + _error = UndefinedNumber; + else if (num == "inf") + _error = Infinity; + else if (num == "-inf") + _error = MinusInfinity; +} + +_knuminteger::_knuminteger(QString const & num) +{ + mpz_init(_mpz); + mpz_set_str(_mpz, num.ascii(), 10); +} + +_knumfraction::_knumfraction(QString const & num) +{ + mpq_init(_mpq); + if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) { + // my hand-made conversion is terrible + // first me convert the mantissa + unsigned long int digits_after_dot = ((num.section( '.', 1, 1)).section('e', 0, 0)).length(); + QString tmp_num = num.section('e', 0, 0).remove('.'); + mpq_set_str(_mpq, tmp_num.ascii(), 10); + mpz_t tmp_int; + mpz_init(tmp_int); + mpz_ui_pow_ui (tmp_int, 10, digits_after_dot); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + // now we take care of the exponent + if (! (tmp_num = num.section('e', 1, 1)).isEmpty()) { + long int tmp_exp = tmp_num.toLong(); + if (tmp_exp > 0) { + mpz_ui_pow_ui (tmp_int, 10, + static_cast<unsigned long int>(tmp_exp)); + mpz_mul(mpq_numref(_mpq), mpq_numref(_mpq), tmp_int); + } else { + mpz_ui_pow_ui (tmp_int, 10, + static_cast<unsigned long int>(-tmp_exp)); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + } + } + mpz_clear(tmp_int); + } else + mpq_set_str(_mpq, num.ascii(), 10); + mpq_canonicalize(_mpq); +} + +_knumfloat::_knumfloat(QString const & num) +{ + mpf_init(_mpf); + mpf_set_str(_mpf, num.ascii(), 10); +} + +_knuminteger const & _knuminteger::operator = (_knuminteger const & num) +{ + if (this == &num) + return *this; + + mpz_set(_mpz, num._mpz); + return *this; +} + +QString const _knumerror::ascii(int prec) const +{ + static_cast<void>(prec); + + switch(_error) { + case UndefinedNumber: + return QString("nan"); + case Infinity: + return QString("inf"); + case MinusInfinity: + return QString("-inf"); + default: + return QString::null; + } +} + +QString const _knuminteger::ascii(int prec) const +{ + static_cast<void>(prec); + char *tmp_ptr; + + gmp_asprintf(&tmp_ptr, "%Zd", _mpz); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + return ret_str; +} + +QString const _knumfraction::ascii(int prec) const +{ + static_cast<void>(prec); + char *tmp_ptr = mpq_get_str(0, 10, _mpq); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + +QString const _knumfloat::ascii(int prec) const +{ + QString ret_str; + char *tmp_ptr; + if (prec > 0) + gmp_asprintf(&tmp_ptr, ("%." + QString().setNum(prec) + "Fg").ascii(), _mpf); + else + gmp_asprintf(&tmp_ptr, "%Fg", _mpf); + + ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + + +bool _knumfraction::isInteger(void) const +{ + if (mpz_cmp_ui(mpq_denref(_mpq), 1) == 0) + return true; + else + return false; +} + + +_knumber * _knumerror::abs(void) const +{ + _knumerror * tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::abs(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_abs(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::abs(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_abs(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::abs(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_abs(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::intPart(void) const +{ + return new _knumerror(*this); +} + +_knumber * _knuminteger::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + mpz_set(tmp_num->_mpz, _mpz); + return tmp_num; +} + +_knumber * _knumfraction::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_q(tmp_num->_mpz, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_f(tmp_num->_mpz, _mpf); + + return tmp_num; +} + + + + +int _knumerror::sign(void) const +{ + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 0; + } +} + +int _knuminteger::sign(void) const +{ + return mpz_sgn(_mpz); +} + +int _knumfraction::sign(void) const +{ + return mpq_sgn(_mpq); +} + +int _knumfloat::sign(void) const +{ + return mpf_sgn(_mpf); +} + + + +#warning _cbrt for now this is a stupid work around +static void _cbrt(mpf_t &num) +{ + double tmp_num = cbrt(mpf_get_d(num)); + mpf_init_set_d(num, tmp_num); +} + + +_knumber * _knumerror::cbrt(void) const +{ + // infty ^3 = infty; -infty^3 = -infty + _knumerror *tmp_num = new _knumerror(*this); + + return tmp_num; +} + +_knumber * _knuminteger::cbrt(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + if(mpz_root(tmp_num->_mpz, _mpz, 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_z(tmp_num2->_mpf, _mpz); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfraction::cbrt(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + if (mpz_root(mpq_numref(tmp_num->_mpq), mpq_numref(_mpq), 3) + && mpz_root(mpq_denref(tmp_num->_mpq), mpq_denref(_mpq), 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_q(tmp_num2->_mpf, _mpq); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfloat::cbrt(void) const +{ + _knumfloat * tmp_num = new _knumfloat(*this); + + _cbrt(tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::sqrt(void) const +{ + _knumerror *tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = UndefinedNumber; + + return tmp_num; +} + +_knumber * _knuminteger::sqrt(void) const +{ + if (mpz_sgn(_mpz) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(_mpz)) { + _knuminteger * tmp_num = new _knuminteger(); + + mpz_sqrt(tmp_num->_mpz, _mpz); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_z(tmp_num->_mpf, _mpz); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } +} + +_knumber * _knumfraction::sqrt(void) const +{ + if (mpq_sgn(_mpq) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(mpq_numref(_mpq)) + && mpz_perfect_square_p(mpq_denref(_mpq))) { + _knumfraction * tmp_num = new _knumfraction(); + mpq_set(tmp_num->_mpq, _mpq); + mpz_sqrt(mpq_numref(tmp_num->_mpq), mpq_numref(tmp_num->_mpq)); + mpz_sqrt(mpq_denref(tmp_num->_mpq), mpq_denref(tmp_num->_mpq)); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_q(tmp_num->_mpf, _mpq); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } + + _knumfraction * tmp_num = new _knumfraction(); + + return tmp_num; +} + +_knumber * _knumfloat::sqrt(void) const +{ + if (mpf_sgn(_mpf) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + _knumfloat * tmp_num = new _knumfloat(); + + mpf_sqrt(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::change_sign(void) const +{ + _knumerror * tmp_num = new _knumerror(); + + if(_error == Infinity) tmp_num->_error = MinusInfinity; + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::change_sign(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_neg(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::change_sign(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_neg(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::change_sign(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_neg(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + +_knumber * _knumerror::reciprocal(void) const +{ + switch(_error) { + case Infinity: + case MinusInfinity: + return new _knuminteger(0); + case UndefinedNumber: + default: + return new _knumerror(UndefinedNumber); + } +} + +_knumber * _knuminteger::reciprocal(void) const +{ + if(mpz_cmp_si(_mpz, 0) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(*this); + + mpq_inv(tmp_num->_mpq, tmp_num->_mpq); + + return tmp_num; +} + +_knumber * _knumfraction::reciprocal() const +{ + if(mpq_cmp_si(_mpq, 0, 1) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_inv(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::reciprocal(void) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_div(tmp_num->_mpf, _knumfloat("1.0")._mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::add(_knumber const & arg2) const +{ + if (arg2.type() != SpecialType) + return new _knumerror(_error); + + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + + if (_error == UndefinedNumber + || tmp_arg2._error == UndefinedNumber + || (_error == Infinity && tmp_arg2._error == MinusInfinity) + || (_error == MinusInfinity && tmp_arg2._error == Infinity) + ) + return new _knumerror(UndefinedNumber); + + return new _knumerror(_error); +} + +_knumber * _knuminteger::add(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.add(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_add(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::add(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.add(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.add(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_add(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::add(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.add(*this); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.add(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_add(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + +_knumber * _knumerror::multiply(_knumber const & arg2) const +{ + //improve this + switch(arg2.type()) { + case SpecialType: + { + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + if (_error == UndefinedNumber || tmp_arg2._error == UndefinedNumber) + return new _knumerror(UndefinedNumber); + if ( this->sign() * arg2.sign() > 0) + return new _knumerror(Infinity); + else + return new _knumerror(MinusInfinity); + } + case IntegerType: + case FractionType: + case FloatType: + { + int sign_arg2 = arg2.sign(); + if (_error == UndefinedNumber || sign_arg2 == 0) + return new _knumerror(UndefinedNumber); + if ( (_error == Infinity && sign_arg2 > 0) || + (_error == MinusInfinity && sign_arg2 < 0) ) + return new _knumerror(Infinity); + + return new _knumerror(MinusInfinity); + } + } + + return new _knumerror(_error); +} + + +_knumber * _knuminteger::multiply(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.multiply(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mul(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::multiply(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.multiply(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.multiply(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_mul(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::multiply(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.multiply(*this); + if (arg2.type() == IntegerType && + mpz_cmp_si(dynamic_cast<_knuminteger const &>(arg2)._mpz,0) == 0) + // if arg2 == 0 return integer 0!! + return new _knuminteger(0); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.multiply(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_mul(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + + + + +_knumber * _knumber::divide(_knumber const & arg2) const +{ + _knumber * tmp_num = arg2.reciprocal(); + _knumber * rslt_num = this->multiply(*tmp_num); + + delete tmp_num; + + return rslt_num; +} + +_knumber *_knumfloat::divide(_knumber const & arg2) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + // automatically casts arg2 to float + _knumfloat * tmp_num = new _knumfloat(arg2); + + mpf_div(tmp_num->_mpf, _mpf, tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::power(_knumber const & exponent) const +{ + static_cast<void>(exponent); + return new _knumerror(UndefinedNumber); +} + +_knumber * _knuminteger::power(_knumber const & exponent) const +{ + if (exponent.type() == IntegerType) { + + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + dynamic_cast<_knuminteger const &>(exponent)._mpz); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + _knuminteger * tmp_num = new _knuminteger(); + mpz_pow_ui(tmp_num->_mpz, _mpz, tmp_int); + return tmp_num; + } + if (exponent.type() == FractionType) { + if (mpz_sgn(_mpz) < 0) + return new _knumerror(UndefinedNumber); + // GMP only supports few root functions, so we need to convert + // into signed long int + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + mpq_denref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + // first check if result will be an integer + _knuminteger * tmp_num = new _knuminteger(); + int flag = mpz_root(tmp_num->_mpz, _mpz, tmp_int); + if (flag == 0) { // result is not exact + delete tmp_num; + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + // result is exact + + mpz_init_set(tmp_mpz, + mpq_numref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + mpz_pow_ui(tmp_num->_mpz, tmp_num->_mpz, tmp_int); + + return tmp_num; + } + if (exponent.type() == FloatType) { + // need to cast everything to float + _knumfloat tmp_num(*this); + return tmp_num.power(exponent); + } + + return new _knumerror(Infinity); +} + +_knumber * _knumfraction::power(_knumber const & exponent) const +{ + _knuminteger tmp_num = _knuminteger(); + + mpz_set(tmp_num._mpz, mpq_numref(_mpq)); + _knumber *numer = tmp_num.power(exponent); + + mpz_set(tmp_num._mpz, mpq_denref(_mpq)); + _knumber *denom = tmp_num.power(exponent); + + _knumber *result = numer->divide(*denom); + delete numer; + delete denom; + return result; +} + +_knumber * _knumfloat::power(_knumber const & exponent) const +{ + return new _knumfloat(pow(static_cast<double>(*this), + static_cast<double>(exponent))); +} + + +int _knumerror::compare(_knumber const &arg2) const +{ + if (arg2.type() != SpecialType) { + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 1; // Not really o.k., but what should I return + } + } + + switch(_error) { + case Infinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == Infinity) + // Infinity is larger than anything else, but itself + return 0; + return 1; + case MinusInfinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == MinusInfinity) + // MinusInfinity is smaller than anything else, but itself + return 0; + return -1; + default: + if (dynamic_cast<_knumerror const &>(arg2)._error == UndefinedNumber) + // Undefined only equal to itself + return 0; + return -arg2.compare(*this); + } +} + +int _knuminteger::compare(_knumber const &arg2) const +{ + if (arg2.type() != IntegerType) + return - arg2.compare(*this); + + return mpz_cmp(_mpz, dynamic_cast<_knuminteger const &>(arg2)._mpz); +} + +int _knumfraction::compare(_knumber const &arg2) const +{ + if (arg2.type() != FractionType) { + if (arg2.type() == IntegerType) { + mpq_t tmp_frac; + mpq_init(tmp_frac); + mpq_set_z(tmp_frac, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + int cmp_result = mpq_cmp(_mpq, tmp_frac); + mpq_clear(tmp_frac); + return cmp_result; + } else + return - arg2.compare(*this); + } + + return mpq_cmp(_mpq, dynamic_cast<_knumfraction const &>(arg2)._mpq); +} + +int _knumfloat::compare(_knumber const &arg2) const +{ + if (arg2.type() != FloatType) { + mpf_t tmp_float; + if (arg2.type() == IntegerType) { + mpf_init(tmp_float); + mpf_set_z(tmp_float, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + } else if (arg2.type() == FractionType) { + mpf_init(tmp_float); + mpf_set_q(tmp_float, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + } else + return - arg2.compare(*this); + + int cmp_result = mpf_cmp(_mpf, tmp_float); + mpf_clear(tmp_float); + return cmp_result; + } + + return mpf_cmp(_mpf, dynamic_cast<_knumfloat const &>(arg2)._mpf); +} + + + +_knumerror::operator signed long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + +_knumerror::operator unsigned long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + + +_knuminteger::operator signed long int (void) const +{ + return mpz_get_si(_mpz); +} + +_knumfraction::operator signed long int (void) const +{ + return static_cast<signed long int>(mpq_get_d(_mpq)); +} + +_knumfloat::operator signed long int (void) const +{ + return mpf_get_si(_mpf); +} + +_knuminteger::operator unsigned long int (void) const +{ + return mpz_get_ui(_mpz); +} + +_knumfraction::operator unsigned long int (void) const +{ + return static_cast<unsigned long int>(mpq_get_d(_mpq)); +} + +_knumfloat::operator unsigned long int (void) const +{ + return mpf_get_ui(_mpf); +} + + + +_knumerror::operator double (void) const +{ + if (_error == Infinity) + return INFINITY; + if (_error == MinusInfinity) + return -INFINITY; + else // if (_error == UndefinedNumber) + return NAN; +} + +_knuminteger::operator double (void) const +{ + return mpz_get_d(_mpz); +} + +_knumfraction::operator double (void) const +{ + return mpq_get_d(_mpq); +} + +_knumfloat::operator double (void) const +{ + return mpf_get_d(_mpf); +} + + + + +_knuminteger * _knuminteger::intAnd(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_and(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knuminteger * _knuminteger::intOr(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_ior(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::mod(_knuminteger const &arg2) const +{ + if(mpz_cmp_si(arg2._mpz, 0) == 0) return new _knumerror(UndefinedNumber); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mod(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::shift(_knuminteger const &arg2) const +{ + mpz_t tmp_mpz; + + mpz_init_set (tmp_mpz, arg2._mpz); + + if (! mpz_fits_slong_p(tmp_mpz)) { + mpz_clear(tmp_mpz); + return new _knumerror(UndefinedNumber); + } + + signed long int tmp_arg2 = mpz_get_si(tmp_mpz); + mpz_clear(tmp_mpz); + + + _knuminteger * tmp_num = new _knuminteger(); + + if (tmp_arg2 > 0) // left shift + mpz_mul_2exp(tmp_num->_mpz, _mpz, tmp_arg2); + else // right shift + mpz_tdiv_q_2exp(tmp_num->_mpz, _mpz, -tmp_arg2); + + + return tmp_num; +} + |