X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fnumeric.cpp;h=a3872b96650b9843505126cce338757ade54169a;hp=ffcdfbfa7def03fc3d3a3ea7b3eab9f27f10ff05;hb=725021581cc862520c1f04b253ecb86f28032f69;hpb=ed21ddd5e2bc0af018c10934342f526d0ae4b7a7 diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index ffcdfbfa..a3872b96 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -7,7 +7,7 @@ * of special functions or implement the interface to the bignum package. */ /* - * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,20 +29,13 @@ #include #include #include - -#if defined(HAVE_SSTREAM) #include -#elif defined(HAVE_STRSTREAM) -#include -#else -#error Need either sstream or strstream -#endif #include "numeric.h" #include "ex.h" #include "print.h" #include "archive.h" -#include "debugmsg.h" +#include "tostring.h" #include "utils.h" // CLN should pollute the global namespace as little as possible. Hence, we @@ -69,14 +62,12 @@ namespace GiNaC { GINAC_IMPLEMENT_REGISTERED_CLASS(numeric, basic) ////////// -// default ctor, dtor, copy ctor assignment -// operator and helpers +// default ctor, dtor, copy ctor, assignment operator and helpers ////////// /** default ctor. Numerically it initializes to an integer zero. */ numeric::numeric() : basic(TINFO_numeric) { - debugmsg("numeric default ctor", LOGLEVEL_CONSTRUCT); value = cln::cl_I(0); setflag(status_flags::evaluated | status_flags::expanded); } @@ -97,13 +88,12 @@ DEFAULT_DESTROY(numeric) numeric::numeric(int i) : basic(TINFO_numeric) { - debugmsg("numeric ctor from int",LOGLEVEL_CONSTRUCT); // Not the whole int-range is available if we don't cast to long // first. This is due to the behaviour of the cl_I-ctor, which - // emphasizes efficiency. However, if the integer is small enough, - // i.e. satisfies cl_immediate_p(), we save space and dereferences by - // using an immediate type: - if (cln::cl_immediate_p(i)) + // emphasizes efficiency. However, if the integer is small enough + // we save space and dereferences by using an immediate type. + // (C.f. ) + if (i < (1U<) + if (i < (1U< 31.4e-1_ // and s on. // No exponent marker? Let's add a trivial one. - if (term.find("E") == std::string::npos) + if (term.find("E")==std::string::npos) term += "E0"; // E to lower case term = term.replace(term.find("E"),1,"e"); // append _ to term -#if defined(HAVE_SSTREAM) - std::ostringstream buf; - buf << unsigned(Digits) << std::ends; - term += "_" + buf.str(); -#else - char buf[14]; - std::ostrstream(buf,sizeof(buf)) << unsigned(Digits) << std::ends; - term += "_" + std::string(buf); -#endif + term += "_" + ToString((unsigned)Digits); // construct float using cln::cl_F(const char *) ctor. if (imaginary) ctorval = ctorval + cln::complex(cln::cl_I(0),cln::cl_F(term.c_str())); else ctorval = ctorval + cln::cl_F(term.c_str()); } else { - // not a floating point number... + // this is not a floating point number... if (imaginary) ctorval = ctorval + cln::complex(cln::cl_I(0),cln::cl_R(term.c_str())); else ctorval = ctorval + cln::cl_R(term.c_str()); } - } while(delim != std::string::npos); + } while (delim != std::string::npos); value = ctorval; setflag(status_flags::evaluated | status_flags::expanded); } @@ -250,7 +234,6 @@ numeric::numeric(const char *s) : basic(TINFO_numeric) * only. */ numeric::numeric(const cln::cl_N &z) : basic(TINFO_numeric) { - debugmsg("numeric ctor from cl_N", LOGLEVEL_CONSTRUCT); value = z; setflag(status_flags::evaluated | status_flags::expanded); } @@ -261,17 +244,12 @@ numeric::numeric(const cln::cl_N &z) : basic(TINFO_numeric) numeric::numeric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("numeric ctor from archive_node", LOGLEVEL_CONSTRUCT); cln::cl_N ctorval = 0; // Read number as string std::string str; if (n.find_string("number", str)) { -#ifdef HAVE_SSTREAM std::istringstream s(str); -#else - std::istrstream s(str.c_str(), str.size() + 1); -#endif cln::cl_idecoded_float re, im; char c; s.get(c); @@ -301,12 +279,7 @@ void numeric::archive(archive_node &n) const inherited::archive(n); // Write number as string -#ifdef HAVE_SSTREAM std::ostringstream s; -#else - char buf[1024]; - std::ostrstream s(buf, 1024); -#endif if (this->is_crational()) s << cln::the(value); else { @@ -324,19 +297,13 @@ void numeric::archive(archive_node &n) const s << im.sign << " " << im.mantissa << " " << im.exponent; } } -#ifdef HAVE_SSTREAM n.add_string("number", s.str()); -#else - s << ends; - std::string str(buf); - n.add_string("number", str); -#endif } DEFAULT_UNARCHIVE(numeric) ////////// -// functions overriding virtual functions from bases classes +// functions overriding virtual functions from base classes ////////// /** Helper function to print a real number in a nicer way than is CLN's @@ -346,18 +313,29 @@ DEFAULT_UNARCHIVE(numeric) * want to visibly distinguish from cl_LF. * * @see numeric::print() */ -static void print_real_number(std::ostream &os, const cln::cl_R &num) +static void print_real_number(const print_context & c, const cln::cl_R &x) { cln::cl_print_flags ourflags; - if (cln::instanceof(num, cln::cl_RA_ring)) { - // case 1: integer or rational, nothing special to do: - cln::print_real(os, ourflags, num); + if (cln::instanceof(x, cln::cl_RA_ring)) { + // case 1: integer or rational + if (cln::instanceof(x, cln::cl_I_ring) || + !is_a(c)) { + cln::print_real(c.s, ourflags, x); + } else { // rational output in LaTeX context + if (x < 0) + c.s << "-"; + c.s << "\\frac{"; + cln::print_real(c.s, ourflags, cln::abs(cln::numerator(cln::the(x)))); + c.s << "}{"; + cln::print_real(c.s, ourflags, cln::denominator(cln::the(x))); + c.s << '}'; + } } else { // case 2: float // make CLN believe this number has default_float_format, so it prints // 'E' as exponent marker instead of 'L': - ourflags.default_float_format = cln::float_format(cln::the(num)); - cln::print_real(os, ourflags, num); + ourflags.default_float_format = cln::float_format(cln::the(x)); + cln::print_real(c.s, ourflags, x); } } @@ -367,8 +345,6 @@ static void print_real_number(std::ostream &os, const cln::cl_R &num) * @see print_real_number() */ void numeric::print(const print_context & c, unsigned level) const { - debugmsg("numeric print", LOGLEVEL_PRINT); - if (is_a(c)) { c.s << std::string(level, ' ') << cln::the(value) @@ -380,8 +356,18 @@ void numeric::print(const print_context & c, unsigned level) const std::ios::fmtflags oldflags = c.s.flags(); c.s.setf(std::ios::scientific); - if (this->is_rational() && !this->is_integer()) { - if (compare(_num0()) > 0) { + int oldprec = c.s.precision(); + if (is_a(c)) + c.s.precision(16); + else + c.s.precision(7); + if (is_a(c) && this->is_integer()) { + c.s << "cln::cl_I(\""; + const cln::cl_R r = cln::realpart(cln::the(value)); + print_real_number(c,r); + c.s << "\")"; + } else if (this->is_rational() && !this->is_integer()) { + if (compare(_num0) > 0) { c.s << "("; if (is_a(c)) c.s << "cln::cl_F(\"" << numer().evalf() << "\")"; @@ -402,11 +388,12 @@ void numeric::print(const print_context & c, unsigned level) const c.s << ")"; } else { if (is_a(c)) - c.s << "cln::cl_F(\"" << evalf() << "\")"; + c.s << "cln::cl_F(\"" << evalf() << "_" << Digits << "\")"; else c.s << to_double(); } c.s.flags(oldflags); + c.s.precision(oldprec); } else { const std::string par_open = is_a(c) ? "{(" : "("; @@ -415,48 +402,44 @@ void numeric::print(const print_context & c, unsigned level) const const std::string mul_sym = is_a(c) ? " " : "*"; const cln::cl_R r = cln::realpart(cln::the(value)); const cln::cl_R i = cln::imagpart(cln::the(value)); + if (is_a(c)) + c.s << class_name() << "('"; if (cln::zerop(i)) { // case 1, real: x or -x if ((precedence() <= level) && (!this->is_nonneg_integer())) { c.s << par_open; - print_real_number(c.s, r); + print_real_number(c, r); c.s << par_close; } else { - print_real_number(c.s, r); + print_real_number(c, r); } } else { if (cln::zerop(r)) { // case 2, imaginary: y*I or -y*I - if ((precedence() <= level) && (i < 0)) { - if (i == -1) { - c.s << par_open+imag_sym+par_close; - } else { + if (i==1) + c.s << imag_sym; + else { + if (precedence()<=level) c.s << par_open; - print_real_number(c.s, i); - c.s << mul_sym+imag_sym+par_close; - } - } else { - if (i == 1) { - c.s << imag_sym; - } else { - if (i == -1) { - c.s << "-" << imag_sym; - } else { - print_real_number(c.s, i); - c.s << mul_sym+imag_sym; - } + if (i == -1) + c.s << "-" << imag_sym; + else { + print_real_number(c, i); + c.s << mul_sym+imag_sym; } + if (precedence()<=level) + c.s << par_close; } } else { // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I if (precedence() <= level) c.s << par_open; - print_real_number(c.s, r); + print_real_number(c, r); if (i < 0) { if (i == -1) { c.s << "-"+imag_sym; } else { - print_real_number(c.s, i); + print_real_number(c, i); c.s << mul_sym+imag_sym; } } else { @@ -464,7 +447,7 @@ void numeric::print(const print_context & c, unsigned level) const c.s << "+"+imag_sym; } else { c.s << "+"; - print_real_number(c.s, i); + print_real_number(c, i); c.s << mul_sym+imag_sym; } } @@ -472,6 +455,8 @@ void numeric::print(const print_context & c, unsigned level) const c.s << par_close; } } + if (is_a(c)) + c.s << "')"; } } @@ -520,6 +505,21 @@ bool numeric::info(unsigned inf) const return false; } +int numeric::degree(const ex & s) const +{ + return 0; +} + +int numeric::ldegree(const ex & s) const +{ + return 0; +} + +ex numeric::coeff(const ex & s, int n) const +{ + return n==0 ? *this : _ex0; +} + /** Disassemble real part and imaginary part to scan for the occurrence of a * single number. Also handles the imaginary unit. It ignores the sign on * both this and the argument, which may lead to what might appear as funny @@ -528,9 +528,9 @@ bool numeric::info(unsigned inf) const * sign as a multiplicative factor. */ bool numeric::has(const ex &other) const { - if (!is_exactly_of_type(*other.bp, numeric)) + if (!is_ex_exactly_of_type(other, numeric)) return false; - const numeric &o = static_cast(*other.bp); + const numeric &o = ex_to(other); if (this->is_equal(o) || this->is_equal(-o)) return true; if (o.imag().is_zero()) // e.g. scan for 3 in -3*I @@ -574,7 +574,7 @@ ex numeric::evalf(int level) const int numeric::compare_same_type(const basic &other) const { - GINAC_ASSERT(is_exactly_of_type(other, numeric)); + GINAC_ASSERT(is_exactly_a(other)); const numeric &o = static_cast(other); return this->compare(o); @@ -583,7 +583,7 @@ int numeric::compare_same_type(const basic &other) const bool numeric::is_equal_same_type(const basic &other) const { - GINAC_ASSERT(is_exactly_of_type(other,numeric)); + GINAC_ASSERT(is_exactly_a(other)); const numeric &o = static_cast(other); return this->is_equal(o); @@ -617,10 +617,9 @@ unsigned numeric::calchash(void) const const numeric numeric::add(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. - static const numeric * _num0p = &_num0(); - if (this==_num0p) + if (this==_num0_p) return other; - else if (&other==_num0p) + else if (&other==_num0_p) return *this; return numeric(cln::the(value)+cln::the(other.value)); @@ -640,10 +639,9 @@ const numeric numeric::sub(const numeric &other) const const numeric numeric::mul(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. - static const numeric * _num1p = &_num1(); - if (this==_num1p) + if (this==_num1_p) return other; - else if (&other==_num1p) + else if (&other==_num1_p) return *this; return numeric(cln::the(value)*cln::the(other.value)); @@ -667,8 +665,7 @@ const numeric numeric::div(const numeric &other) const const numeric numeric::power(const numeric &other) const { // Efficiency shortcut: trap the neutral exponent by pointer. - static const numeric * _num1p = &_num1(); - if (&other==_num1p) + if (&other==_num1_p) return *this; if (cln::zerop(cln::the(value))) { @@ -679,7 +676,7 @@ const numeric numeric::power(const numeric &other) const else if (cln::minusp(cln::realpart(cln::the(other.value)))) throw std::overflow_error("numeric::eval(): division by zero"); else - return _num0(); + return _num0; } return numeric(cln::expt(cln::the(value),cln::the(other.value))); } @@ -688,10 +685,9 @@ const numeric numeric::power(const numeric &other) const const numeric &numeric::add_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. - static const numeric * _num0p = &_num0(); - if (this==_num0p) + if (this==_num0_p) return other; - else if (&other==_num0p) + else if (&other==_num0_p) return *this; return static_cast((new numeric(cln::the(value)+cln::the(other.value)))-> @@ -709,10 +705,9 @@ const numeric &numeric::sub_dyn(const numeric &other) const const numeric &numeric::mul_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. - static const numeric * _num1p = &_num1(); - if (this==_num1p) + if (this==_num1_p) return other; - else if (&other==_num1p) + else if (&other==_num1_p) return *this; return static_cast((new numeric(cln::the(value)*cln::the(other.value)))-> @@ -732,8 +727,7 @@ const numeric &numeric::div_dyn(const numeric &other) const const numeric &numeric::power_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral exponent by pointer. - static const numeric * _num1p=&_num1(); - if (&other==_num1p) + if (&other==_num1_p) return *this; if (cln::zerop(cln::the(value))) { @@ -744,7 +738,7 @@ const numeric &numeric::power_dyn(const numeric &other) const else if (cln::minusp(cln::realpart(cln::the(other.value)))) throw std::overflow_error("numeric::eval(): division by zero"); else - return _num0(); + return _num0; } return static_cast((new numeric(cln::expt(cln::the(value),cln::the(other.value))))-> setflag(status_flags::dynallocated)); @@ -1111,7 +1105,7 @@ const numeric numeric::numer(void) const const numeric numeric::denom(void) const { if (this->is_integer()) - return _num1(); + return _num1; if (cln::instanceof(value, cln::cl_RA_ring)) return numeric(cln::denominator(cln::the(value))); @@ -1120,7 +1114,7 @@ const numeric numeric::denom(void) const const cln::cl_RA r = cln::the(cln::realpart(cln::the(value))); const cln::cl_RA i = cln::the(cln::imagpart(cln::the(value))); if (cln::instanceof(r, cln::cl_I_ring) && cln::instanceof(i, cln::cl_I_ring)) - return _num1(); + return _num1; if (cln::instanceof(r, cln::cl_I_ring) && cln::instanceof(i, cln::cl_RA_ring)) return numeric(cln::denominator(i)); if (cln::instanceof(r, cln::cl_RA_ring) && cln::instanceof(i, cln::cl_I_ring)) @@ -1129,7 +1123,7 @@ const numeric numeric::denom(void) const return numeric(cln::lcm(cln::denominator(r), cln::denominator(i))); } // at least one float encountered - return _num1(); + return _num1; } @@ -1233,7 +1227,7 @@ const numeric atan(const numeric &x) { if (!x.is_real() && x.real().is_zero() && - abs(x.imag()).is_equal(_num1())) + abs(x.imag()).is_equal(_num1)) throw pole_error("atan(): logarithmic pole",0); return cln::atan(x.to_cl_N()); } @@ -1384,7 +1378,7 @@ static cln::cl_N Li2_projection(const cln::cl_N &x, const numeric Li2(const numeric &x) { if (x.is_zero()) - return _num0(); + return _num0; // what is the desired float format? // first guess: default format @@ -1423,10 +1417,7 @@ const numeric zeta(const numeric &x) if (cln::zerop(x.to_cl_N()-aux)) return cln::zeta(aux); } - std::clog << "zeta(" << x - << "): Does anybody know a good way to calculate this numerically?" - << std::endl; - return numeric(0); + throw dunno(); } @@ -1434,17 +1425,11 @@ const numeric zeta(const numeric &x) * This is only a stub! */ const numeric lgamma(const numeric &x) { - std::clog << "lgamma(" << x - << "): Does anybody know a good way to calculate this numerically?" - << std::endl; - return numeric(0); + throw dunno(); } const numeric tgamma(const numeric &x) { - std::clog << "tgamma(" << x - << "): Does anybody know a good way to calculate this numerically?" - << std::endl; - return numeric(0); + throw dunno(); } @@ -1452,10 +1437,7 @@ const numeric tgamma(const numeric &x) * This is only a stub! */ const numeric psi(const numeric &x) { - std::clog << "psi(" << x - << "): Does anybody know a good way to calculate this numerically?" - << std::endl; - return numeric(0); + throw dunno(); } @@ -1463,10 +1445,7 @@ const numeric psi(const numeric &x) * This is only a stub! */ const numeric psi(const numeric &n, const numeric &x) { - std::clog << "psi(" << n << "," << x - << "): Does anybody know a good way to calculate this numerically?" - << std::endl; - return numeric(0); + throw dunno(); } @@ -1490,8 +1469,8 @@ const numeric factorial(const numeric &n) * @exception range_error (argument must be integer >= -1) */ const numeric doublefactorial(const numeric &n) { - if (n.is_equal(_num_1())) - return _num1(); + if (n.is_equal(_num_1)) + return _num1; if (!n.is_nonneg_integer()) throw std::range_error("numeric::doublefactorial(): argument must be integer >= -1"); @@ -1508,12 +1487,12 @@ const numeric binomial(const numeric &n, const numeric &k) { if (n.is_integer() && k.is_integer()) { if (n.is_nonneg_integer()) { - if (k.compare(n)!=1 && k.compare(_num0())!=-1) + if (k.compare(n)!=1 && k.compare(_num0)!=-1) return numeric(cln::binomial(n.to_int(),k.to_int())); else - return _num0(); + return _num0; } else { - return _num_1().power(k)*binomial(k-n-_num1(),k); + return _num_1.power(k)*binomial(k-n-_num1,k); } } @@ -1531,7 +1510,7 @@ const numeric bernoulli(const numeric &nn) { if (!nn.is_integer() || nn.is_negative()) throw std::range_error("numeric::bernoulli(): argument must be integer >= 0"); - + // Method: // // The Bernoulli numbers are rational numbers that may be computed using @@ -1555,46 +1534,61 @@ const numeric bernoulli(const numeric &nn) // But if somebody works with the n'th Bernoulli number she is likely to // also need all previous Bernoulli numbers. So we need a complete remember // table and above divide and conquer algorithm is not suited to build one - // up. The code below is adapted from Pari's function bernvec(). + // up. The formula below accomplishes this. It is a modification of the + // defining formula above but the computation of the binomial coefficients + // is carried along in an inline fashion. It also honors the fact that + // B_n is zero when n is odd and greater than 1. // // (There is an interesting relation with the tangent polynomials described - // in `Concrete Mathematics', which leads to a program twice as fast as our - // implementation below, but it requires storing one such polynomial in + // in `Concrete Mathematics', which leads to a program a little faster as + // our implementation below, but it requires storing one such polynomial in // addition to the remember table. This doubles the memory footprint so // we don't use it.) - + + const unsigned n = nn.to_int(); + // the special cases not covered by the algorithm below - if (nn.is_equal(_num1())) - return _num_1_2(); - if (nn.is_odd()) - return _num0(); - + if (n & 1) + return (n==1) ? _num_1_2 : _num0; + if (!n) + return _num1; + // store nonvanishing Bernoulli numbers here static std::vector< cln::cl_RA > results; - static int highest_result = 0; - // algorithm not applicable to B(0), so just store it - if (results.empty()) - results.push_back(cln::cl_RA(1)); - - int n = nn.to_long(); - for (int i=highest_result; i0; --j) { - B = cln::cl_I(n*m) * (B+results[j]) / (d1*d2); - n += 4; - m += 2; - d1 -= 1; - d2 -= 2; - } - B = (1 - ((B+1)/(2*i+3))) / (cln::cl_I(1)<<(2*i+2)); - results.push_back(B); - ++highest_result; + static unsigned next_r = 0; + + // algorithm not applicable to B(2), so just store it + if (!next_r) { + results.push_back(cln::recip(cln::cl_RA(6))); + next_r = 4; } - return results[n/2]; + if (n) + if (p < (1UL<(a.to_cl_N()), cln::the(b.to_cl_N())); else - return _num0(); + return _num0; } @@ -1692,7 +1686,7 @@ const numeric smod(const numeric &a, const numeric &b) return cln::mod(cln::the(a.to_cl_N()) + b2, cln::the(b.to_cl_N())) - b2; } else - return _num0(); + return _num0; } @@ -1701,14 +1695,17 @@ const numeric smod(const numeric &a, const numeric &b) * In general, mod(a,b) has the sign of b or is zero, and irem(a,b) has the * sign of a or is zero. * - * @return remainder of a/b if both are integer, 0 otherwise. */ + * @return remainder of a/b if both are integer, 0 otherwise. + * @exception overflow_error (division by zero) if b is zero. */ const numeric irem(const numeric &a, const numeric &b) { + if (b.is_zero()) + throw std::overflow_error("numeric::irem(): division by zero"); if (a.is_integer() && b.is_integer()) return cln::rem(cln::the(a.to_cl_N()), cln::the(b.to_cl_N())); else - return _num0(); + return _num0; } @@ -1718,17 +1715,20 @@ const numeric irem(const numeric &a, const numeric &b) * and irem(a,b) has the sign of a or is zero. * * @return remainder of a/b and quotient stored in q if both are integer, - * 0 otherwise. */ + * 0 otherwise. + * @exception overflow_error (division by zero) if b is zero. */ const numeric irem(const numeric &a, const numeric &b, numeric &q) { + if (b.is_zero()) + throw std::overflow_error("numeric::irem(): division by zero"); if (a.is_integer() && b.is_integer()) { const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the(a.to_cl_N()), cln::the(b.to_cl_N())); q = rem_quo.quotient; return rem_quo.remainder; } else { - q = _num0(); - return _num0(); + q = _num0; + return _num0; } } @@ -1736,14 +1736,17 @@ const numeric irem(const numeric &a, const numeric &b, numeric &q) /** Numeric integer quotient. * Equivalent to Maple's iquo as far as sign conventions are concerned. * - * @return truncated quotient of a/b if both are integer, 0 otherwise. */ + * @return truncated quotient of a/b if both are integer, 0 otherwise. + * @exception overflow_error (division by zero) if b is zero. */ const numeric iquo(const numeric &a, const numeric &b) { + if (b.is_zero()) + throw std::overflow_error("numeric::iquo(): division by zero"); if (a.is_integer() && b.is_integer()) return cln::truncate1(cln::the(a.to_cl_N()), cln::the(b.to_cl_N())); else - return _num0(); + return _num0; } @@ -1752,17 +1755,20 @@ const numeric iquo(const numeric &a, const numeric &b) * r == a - iquo(a,b,r)*b. * * @return truncated quotient of a/b and remainder stored in r if both are - * integer, 0 otherwise. */ + * integer, 0 otherwise. + * @exception overflow_error (division by zero) if b is zero. */ const numeric iquo(const numeric &a, const numeric &b, numeric &r) { + if (b.is_zero()) + throw std::overflow_error("numeric::iquo(): division by zero"); if (a.is_integer() && b.is_integer()) { const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the(a.to_cl_N()), cln::the(b.to_cl_N())); r = rem_quo.remainder; return rem_quo.quotient; } else { - r = _num0(); - return _num0(); + r = _num0; + return _num0; } } @@ -1777,7 +1783,7 @@ const numeric gcd(const numeric &a, const numeric &b) return cln::gcd(cln::the(a.to_cl_N()), cln::the(b.to_cl_N())); else - return _num1(); + return _num1; } @@ -1817,7 +1823,7 @@ const numeric isqrt(const numeric &x) cln::isqrt(cln::the(x.to_cl_N()), &root); return root; } else - return _num0(); + return _num0; } @@ -1876,7 +1882,6 @@ _numeric_digits::operator long() /** Append global Digits object to ostream. */ void _numeric_digits::print(std::ostream &os) const { - debugmsg("_numeric_digits print", LOGLEVEL_PRINT); os << digits; }