X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=ginac%2Fnumeric.cpp;h=795c76099172dba5d5284fd6fc08c4183428fc3d;hb=a06a27122b0a9087e9c64743940016c7e0176ce2;hp=49951470475de6ccf9de61b97b9f76e03a259d88;hpb=5e9875d5f67a68d2cb680454ff4de480bad1b6f1;p=ginac.git diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 49951470..795c7609 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-2008 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2011 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 @@ -24,13 +24,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H #include "config.h" - -#include -#include -#include -#include -#include +#endif #include "numeric.h" #include "ex.h" @@ -39,6 +35,12 @@ #include "tostring.h" #include "utils.h" +#include +#include +#include +#include +#include + // CLN should pollute the global namespace as little as possible. Hence, we // include most of it here and include only the part needed for properly // declaring cln::cl_number in numeric.h. This can only be safely done in @@ -73,7 +75,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(numeric, basic, ////////// /** default ctor. Numerically it initializes to an integer zero. */ -numeric::numeric() : basic(&numeric::tinfo_static) +numeric::numeric() { value = cln::cl_I(0); setflag(status_flags::evaluated | status_flags::expanded); @@ -85,7 +87,7 @@ numeric::numeric() : basic(&numeric::tinfo_static) // public -numeric::numeric(int i) : basic(&numeric::tinfo_static) +numeric::numeric(int i) { // 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 @@ -106,7 +108,7 @@ numeric::numeric(int i) : basic(&numeric::tinfo_static) } -numeric::numeric(unsigned int i) : basic(&numeric::tinfo_static) +numeric::numeric(unsigned int i) { // Not the whole uint-range is available if we don't cast to ulong // first. This is due to the behaviour of the cl_I-ctor, which @@ -127,14 +129,14 @@ numeric::numeric(unsigned int i) : basic(&numeric::tinfo_static) } -numeric::numeric(long i) : basic(&numeric::tinfo_static) +numeric::numeric(long i) { value = cln::cl_I(i); setflag(status_flags::evaluated | status_flags::expanded); } -numeric::numeric(unsigned long i) : basic(&numeric::tinfo_static) +numeric::numeric(unsigned long i) { value = cln::cl_I(i); setflag(status_flags::evaluated | status_flags::expanded); @@ -144,7 +146,7 @@ numeric::numeric(unsigned long i) : basic(&numeric::tinfo_static) /** Constructor for rational numerics a/b. * * @exception overflow_error (division by zero) */ -numeric::numeric(long numer, long denom) : basic(&numeric::tinfo_static) +numeric::numeric(long numer, long denom) { if (!denom) throw std::overflow_error("division by zero"); @@ -153,7 +155,7 @@ numeric::numeric(long numer, long denom) : basic(&numeric::tinfo_static) } -numeric::numeric(double d) : basic(&numeric::tinfo_static) +numeric::numeric(double d) { // We really want to explicitly use the type cl_LF instead of the // more general cl_F, since that would give us a cl_DF only which @@ -165,7 +167,7 @@ numeric::numeric(double d) : basic(&numeric::tinfo_static) /** ctor from C-style string. It also accepts complex numbers in GiNaC * notation like "2+5*I". */ -numeric::numeric(const char *s) : basic(&numeric::tinfo_static) +numeric::numeric(const char *s) { cln::cl_N ctorval = 0; // parse complex numbers (functional but not completely safe, unfortunately @@ -244,7 +246,7 @@ numeric::numeric(const char *s) : basic(&numeric::tinfo_static) /** Ctor from CLN types. This is for the initiated user or internal use * only. */ -numeric::numeric(const cln::cl_N &z) : basic(&numeric::tinfo_static) +numeric::numeric(const cln::cl_N &z) { value = z; setflag(status_flags::evaluated | status_flags::expanded); @@ -278,8 +280,9 @@ static const cln::cl_F read_real_float(std::istream& s) return x; } -numeric::numeric(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) +void numeric::read_archive(const archive_node &n, lst &sym_lst) { + inherited::read_archive(n, sym_lst); value = 0; // Read number as string @@ -324,6 +327,7 @@ numeric::numeric(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) } setflag(status_flags::evaluated | status_flags::expanded); } +GINAC_BIND_UNARCHIVER(numeric); static void write_real_float(std::ostream& s, const cln::cl_R& n) { @@ -373,8 +377,6 @@ void numeric::archive(archive_node &n) const n.add_string("number", s.str()); } -DEFAULT_UNARCHIVE(numeric) - ////////// // functions overriding virtual functions from base classes ////////// @@ -700,7 +702,7 @@ bool numeric::info(unsigned inf) const case info_flags::negative: return is_negative(); case info_flags::nonnegative: - return !is_negative(); + return is_zero() || is_positive(); case info_flags::posint: return is_pos_integer(); case info_flags::negint: @@ -2278,11 +2280,14 @@ const numeric fibonacci(const numeric &n) // F(2n+2) = F(n+1)*(2*F(n) + F(n+1)) if (n.is_zero()) return *_num0_p; - if (n.is_negative()) - if (n.is_even()) + if (n.is_negative()) { + if (n.is_even()) { return -fibonacci(-n); - else + } + else { return fibonacci(-n); + } + } cln::cl_I u(0); cln::cl_I v(1); @@ -2334,15 +2339,18 @@ const numeric mod(const numeric &a, const numeric &b) /** Modulus (in symmetric representation). - * Equivalent to Maple's mods. * - * @return a mod b in the range [-iquo(abs(b)-1,2), iquo(abs(b),2)]. */ -const numeric smod(const numeric &a, const numeric &b) -{ - if (a.is_integer() && b.is_integer()) { - const cln::cl_I b2 = cln::ceiling1(cln::the(b.to_cl_N()) >> 1) - 1; - return numeric(cln::mod(cln::the(a.to_cl_N()) + b2, - cln::the(b.to_cl_N())) - b2); + * @return a mod b in the range [-iquo(abs(b),2), iquo(abs(b),2)]. */ +const numeric smod(const numeric &a_, const numeric &b_) +{ + if (a_.is_integer() && b_.is_integer()) { + const cln::cl_I a = cln::the(a_.to_cl_N()); + const cln::cl_I b = cln::the(b_.to_cl_N()); + const cln::cl_I b2 = b >> 1; + const cln::cl_I m = cln::mod(a, b); + const cln::cl_I m_b = m - b; + const cln::cl_I ret = m > b2 ? m_b : m; + return numeric(ret); } else return *_num0_p; }