]> www.ginac.de Git - ginac.git/blobdiff - ginac/numeric.cpp
Add support for Texinfo-5.0.
[ginac.git] / ginac / numeric.cpp
index 49951470475de6ccf9de61b97b9f76e03a259d88..795c76099172dba5d5284fd6fc08c4183428fc3d 100644 (file)
@@ -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
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
-
-#include <vector>
-#include <stdexcept>
-#include <string>
-#include <sstream>
-#include <limits>
+#endif
 
 #include "numeric.h"
 #include "ex.h"
 #include "tostring.h"
 #include "utils.h"
 
+#include <limits>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
 // 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<cln::cl_I>(b.to_cl_N()) >> 1) - 1;
-               return numeric(cln::mod(cln::the<cln::cl_I>(a.to_cl_N()) + b2,
-                               cln::the<cln::cl_I>(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<cln::cl_I>(a_.to_cl_N());
+               const cln::cl_I b = cln::the<cln::cl_I>(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;
 }