]> www.ginac.de Git - ginac.git/blobdiff - ginac/numeric.cpp
- doublefactorial now falls back directly to CLN, which is much faster.
[ginac.git] / ginac / numeric.cpp
index b5cc40b33b2659af8e3d07e6be9d4303b6c0f570..c0a2051b0ee311967bf29a01a80cd47eb8628ce0 100644 (file)
@@ -7,7 +7,7 @@
  *  of special functions or implement the interface to the bignum package. */
 
 /*
- *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2000 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
@@ -31,6 +31,7 @@
 #include "ex.h"
 #include "config.h"
 #include "debugmsg.h"
+#include "utils.h"
 
 // CLN should not pollute the global namespace, hence we include it here
 // instead of in some header file where it would propagate to other parts:
@@ -71,13 +72,13 @@ numeric::~numeric()
     destroy(0);
 }
 
-numeric::numeric(numeric const & other)
+numeric::numeric(const numeric & other)
 {
     debugmsg("numeric copy constructor", LOGLEVEL_CONSTRUCT);
     copy(other);
 }
 
-numeric const & numeric::operator=(numeric const & other)
+const numeric & numeric::operator=(const numeric & other)
 {
     debugmsg("numeric operator=", LOGLEVEL_ASSIGNMENT);
     if (this != &other) {
@@ -89,7 +90,7 @@ numeric const & numeric::operator=(numeric const & other)
 
 // protected
 
-void numeric::copy(numeric const & other)
+void numeric::copy(const numeric & other)
 {
     basic::copy(other);
     value = new cl_N(*other.value);
@@ -109,7 +110,7 @@ void numeric::destroy(bool call_parent)
 
 numeric::numeric(int i) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from int",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor 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:
@@ -121,7 +122,7 @@ numeric::numeric(int i) : basic(TINFO_numeric)
 
 numeric::numeric(unsigned int i) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from uint",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from uint",LOGLEVEL_CONSTRUCT);
     // 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
     // emphasizes efficiency:
@@ -133,7 +134,7 @@ numeric::numeric(unsigned int i) : basic(TINFO_numeric)
 
 numeric::numeric(long i) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from long",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
     calchash();
     setflag(status_flags::evaluated|
@@ -142,7 +143,7 @@ numeric::numeric(long i) : basic(TINFO_numeric)
 
 numeric::numeric(unsigned long i) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from ulong",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
     calchash();
     setflag(status_flags::evaluated|
@@ -154,7 +155,7 @@ numeric::numeric(unsigned long i) : basic(TINFO_numeric)
  *  @exception overflow_error (division by zero) */
 numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from long/long",LOGLEVEL_CONSTRUCT);
     if (!denom)
         throw (std::overflow_error("division by zero"));
     value = new cl_I(numer);
@@ -166,7 +167,7 @@ numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
 
 numeric::numeric(double d) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from double",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from double",LOGLEVEL_CONSTRUCT);
     // 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
     // will not be promoted to cl_LF if overflow occurs:
@@ -179,7 +180,7 @@ numeric::numeric(double d) : basic(TINFO_numeric)
 
 numeric::numeric(char const *s) : basic(TINFO_numeric)
 {   // MISSING: treatment of complex and ints and rationals.
-    debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from string",LOGLEVEL_CONSTRUCT);
     if (strchr(s, '.'))
         value = new cl_LF(s);
     else
@@ -193,7 +194,7 @@ numeric::numeric(char const *s) : basic(TINFO_numeric)
  *  only. */
 numeric::numeric(cl_N const & z) : basic(TINFO_numeric)
 {
-    debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT);
+    debugmsg("const numericructor from cl_N", LOGLEVEL_CONSTRUCT);
     value = new cl_N(z);
     calchash();
     setflag(status_flags::evaluated|
@@ -212,19 +213,11 @@ basic * numeric::duplicate() const
     return new numeric(*this);
 }
 
-// The method printraw doesn't do much, it simply uses CLN's operator<<() for
-// output, which is ugly but reliable. Examples:
-// 2+2i 
-void numeric::printraw(ostream & os) const
-{
-    debugmsg("numeric printraw", LOGLEVEL_PRINT);
-    os << "numeric(" << *value << ")";
-}
-
-// The method print adds to the output so it blends more consistently together
-// with the other routines and produces something compatible to Maple input.
 void numeric::print(ostream & os, unsigned upper_precedence) const
 {
+    // The method print adds to the output so it blends more consistently
+    // together with the other routines and produces something compatible to
+    // ginsh input.
     debugmsg("numeric print", LOGLEVEL_PRINT);
     if (is_real()) {
         // case 1, real:  x  or  -x
@@ -275,6 +268,14 @@ void numeric::print(ostream & os, unsigned upper_precedence) const
     }
 }
 
+
+void numeric::printraw(ostream & os) const
+{
+    // The method printraw doesn't do much, it simply uses CLN's operator<<()
+    // for output, which is ugly but reliable. e.g: 2+2i
+    debugmsg("numeric printraw", LOGLEVEL_PRINT);
+    os << "numeric(" << *value << ")";
+}
 void numeric::printtree(ostream & os, unsigned indent) const
 {
     debugmsg("numeric printtree", LOGLEVEL_PRINT);
@@ -290,7 +291,7 @@ void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence)
     ios::fmtflags oldflags = os.flags();
     os.setf(ios::scientific);
     if (is_rational() && !is_integer()) {
-        if (compare(numZERO()) > 0) {
+        if (compare(_num0()) > 0) {
             os << "(";
             if (type == csrc_types::ctype_cl_N)
                 os << "cl_F(\"" << numer().evalf() << "\")";
@@ -344,11 +345,11 @@ bool numeric::info(unsigned inf) const
     case info_flags::negative:
         return is_negative();
     case info_flags::nonnegative:
-        return compare(numZERO())>=0;
+        return compare(_num0())>=0;
     case info_flags::posint:
         return is_pos_integer();
     case info_flags::negint:
-        return is_integer() && (compare(numZERO())<0);
+        return is_integer() && (compare(_num0())<0);
     case info_flags::nonnegint:
         return is_nonneg_integer();
     case info_flags::even:
@@ -378,7 +379,7 @@ ex numeric::evalf(int level) const
 int numeric::compare_same_type(basic const & other) const
 {
     GINAC_ASSERT(is_exactly_of_type(other, numeric));
-    numeric const & o = static_cast<numeric &>(const_cast<basic &>(other));
+    const numeric & o = static_cast<numeric &>(const_cast<basic &>(other));
 
     if (*value == *o.value) {
         return 0;
@@ -390,7 +391,7 @@ int numeric::compare_same_type(basic const & other) const
 bool numeric::is_equal_same_type(basic const & other) const
 {
     GINAC_ASSERT(is_exactly_of_type(other,numeric));
-    numeric const *o = static_cast<numeric const *>(&other);
+    const numeric *o = static_cast<const numeric *>(&other);
     
     return is_equal(*o);
 }
@@ -423,26 +424,26 @@ unsigned numeric::calchash(void) const
 
 /** Numerical addition method.  Adds argument to *this and returns result as
  *  a new numeric object. */
-numeric numeric::add(numeric const & other) const
+numeric numeric::add(const numeric & other) const
 {
     return numeric((*value)+(*other.value));
 }
 
 /** Numerical subtraction method.  Subtracts argument from *this and returns
  *  result as a new numeric object. */
-numeric numeric::sub(numeric const & other) const
+numeric numeric::sub(const numeric & other) const
 {
     return numeric((*value)-(*other.value));
 }
 
 /** Numerical multiplication method.  Multiplies *this and argument and returns
  *  result as a new numeric object. */
-numeric numeric::mul(numeric const & other) const
+numeric numeric::mul(const numeric & other) const
 {
-    static const numeric * numONEp=&numONE();
-    if (this==numONEp) {
+    static const numeric * _num1p=&_num1();
+    if (this==_num1p) {
         return other;
-    } else if (&other==numONEp) {
+    } else if (&other==_num1p) {
         return *this;
     }
     return numeric((*value)*(*other.value));
@@ -452,17 +453,17 @@ numeric numeric::mul(numeric const & other) const
  *  a new numeric object.
  *
  *  @exception overflow_error (division by zero) */
-numeric numeric::div(numeric const & other) const
+numeric numeric::div(const numeric & other) const
 {
     if (::zerop(*other.value))
         throw (std::overflow_error("division by zero"));
     return numeric((*value)/(*other.value));
 }
 
-numeric numeric::power(numeric const & other) const
+numeric numeric::power(const numeric & other) const
 {
-    static const numeric * numONEp=&numONE();
-    if (&other==numONEp)
+    static const numeric * _num1p=&_num1();
+    if (&other==_num1p)
         return *this;
     if (::zerop(*value) && other.is_real() && ::minusp(realpart(*other.value)))
         throw (std::overflow_error("division by zero"));
@@ -475,75 +476,75 @@ numeric numeric::inverse(void) const
     return numeric(::recip(*value));  // -> CLN
 }
 
-numeric const & numeric::add_dyn(numeric const & other) const
+const numeric & numeric::add_dyn(const numeric & other) const
 {
-    return static_cast<numeric const &>((new numeric((*value)+(*other.value)))->
+    return static_cast<const numeric &>((new numeric((*value)+(*other.value)))->
                                         setflag(status_flags::dynallocated));
 }
 
-numeric const & numeric::sub_dyn(numeric const & other) const
+const numeric & numeric::sub_dyn(const numeric & other) const
 {
-    return static_cast<numeric const &>((new numeric((*value)-(*other.value)))->
+    return static_cast<const numeric &>((new numeric((*value)-(*other.value)))->
                                         setflag(status_flags::dynallocated));
 }
 
-numeric const & numeric::mul_dyn(numeric const & other) const
+const numeric & numeric::mul_dyn(const numeric & other) const
 {
-    static const numeric * numONEp=&numONE();
-    if (this==numONEp) {
+    static const numeric * _num1p=&_num1();
+    if (this==_num1p) {
         return other;
-    } else if (&other==numONEp) {
+    } else if (&other==_num1p) {
         return *this;
     }
-    return static_cast<numeric const &>((new numeric((*value)*(*other.value)))->
+    return static_cast<const numeric &>((new numeric((*value)*(*other.value)))->
                                         setflag(status_flags::dynallocated));
 }
 
-numeric const & numeric::div_dyn(numeric const & other) const
+const numeric & numeric::div_dyn(const numeric & other) const
 {
     if (::zerop(*other.value))
         throw (std::overflow_error("division by zero"));
-    return static_cast<numeric const &>((new numeric((*value)/(*other.value)))->
+    return static_cast<const numeric &>((new numeric((*value)/(*other.value)))->
                                         setflag(status_flags::dynallocated));
 }
 
-numeric const & numeric::power_dyn(numeric const & other) const
+const numeric & numeric::power_dyn(const numeric & other) const
 {
-    static const numeric * numONEp=&numONE();
-    if (&other==numONEp)
+    static const numeric * _num1p=&_num1();
+    if (&other==_num1p)
         return *this;
     if (::zerop(*value) && other.is_real() && ::minusp(realpart(*other.value)))
         throw (std::overflow_error("division by zero"));
-    return static_cast<numeric const &>((new numeric(::expt(*value,*other.value)))->
+    return static_cast<const numeric &>((new numeric(::expt(*value,*other.value)))->
                                         setflag(status_flags::dynallocated));
 }
 
-numeric const & numeric::operator=(int i)
+const numeric & numeric::operator=(int i)
 {
     return operator=(numeric(i));
 }
 
-numeric const & numeric::operator=(unsigned int i)
+const numeric & numeric::operator=(unsigned int i)
 {
     return operator=(numeric(i));
 }
 
-numeric const & numeric::operator=(long i)
+const numeric & numeric::operator=(long i)
 {
     return operator=(numeric(i));
 }
 
-numeric const & numeric::operator=(unsigned long i)
+const numeric & numeric::operator=(unsigned long i)
 {
     return operator=(numeric(i));
 }
 
-numeric const & numeric::operator=(double d)
+const numeric & numeric::operator=(double d)
 {
     return operator=(numeric(d));
 }
 
-numeric const & numeric::operator=(char const * s)
+const numeric & numeric::operator=(char const * s)
 {
     return operator=(numeric(s));
 }
@@ -552,7 +553,7 @@ numeric const & numeric::operator=(char const * s)
  *  csgn(x)==0 for x==0, csgn(x)==1 for Re(x)>0 or Re(x)=0 and Im(x)>0,
  *  csgn(x)==-1 for Re(x)<0 or Re(x)=0 and Im(x)<0.
  *
- *  @see numeric::compare(numeric const & other) */
+ *  @see numeric::compare(const numeric & other) */
 int numeric::csgn(void) const
 {
     if (is_zero())
@@ -577,7 +578,7 @@ int numeric::csgn(void) const
  *
  *  @return csgn(*this-other)
  *  @see numeric::csgn(void) */
-int numeric::compare(numeric const & other) const
+int numeric::compare(const numeric & other) const
 {
     // Comparing two real numbers?
     if (is_real() && other.is_real())
@@ -593,7 +594,7 @@ int numeric::compare(numeric const & other) const
     }
 }
 
-bool numeric::is_equal(numeric const & other) const
+bool numeric::is_equal(const numeric & other) const
 {
     return (*value == *other.value);
 }
@@ -671,12 +672,12 @@ bool numeric::is_real(void) const
     return ::instanceof(*value, cl_R_ring);  // -> CLN
 }
 
-bool numeric::operator==(numeric const & other) const
+bool numeric::operator==(const numeric & other) const
 {
     return (*value == *other.value);  // -> CLN
 }
 
-bool numeric::operator!=(numeric const & other) const
+bool numeric::operator!=(const numeric & other) const
 {
     return (*value != *other.value);  // -> CLN
 }
@@ -712,7 +713,7 @@ bool numeric::is_crational(void) const
 /** Numerical comparison: less.
  *
  *  @exception invalid_argument (complex inequality) */ 
-bool numeric::operator<(numeric const & other) const
+bool numeric::operator<(const numeric & other) const
 {
     if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) < The(cl_R)(*other.value));  // -> CLN
@@ -723,7 +724,7 @@ bool numeric::operator<(numeric const & other) const
 /** Numerical comparison: less or equal.
  *
  *  @exception invalid_argument (complex inequality) */ 
-bool numeric::operator<=(numeric const & other) const
+bool numeric::operator<=(const numeric & other) const
 {
     if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) <= The(cl_R)(*other.value));  // -> CLN
@@ -734,7 +735,7 @@ bool numeric::operator<=(numeric const & other) const
 /** Numerical comparison: greater.
  *
  *  @exception invalid_argument (complex inequality) */ 
-bool numeric::operator>(numeric const & other) const
+bool numeric::operator>(const numeric & other) const
 {
     if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) > The(cl_R)(*other.value));  // -> CLN
@@ -745,7 +746,7 @@ bool numeric::operator>(numeric const & other) const
 /** Numerical comparison: greater or equal.
  *
  *  @exception invalid_argument (complex inequality) */  
-bool numeric::operator>=(numeric const & other) const
+bool numeric::operator>=(const numeric & other) const
 {
     if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) >= The(cl_R)(*other.value));  // -> CLN
@@ -852,7 +853,7 @@ numeric numeric::numer(void) const
 numeric numeric::denom(void) const
 {
     if (is_integer()) {
-        return numONE();
+        return _num1();
     }
 #ifdef SANE_LINKER
     if (instanceof(*value, cl_RA_ring)) {
@@ -862,7 +863,7 @@ numeric numeric::denom(void) const
         cl_R r = realpart(*value);
         cl_R i = imagpart(*value);
         if (::instanceof(r, cl_I_ring) && ::instanceof(i, cl_I_ring))
-            return numONE();
+            return _num1();
         if (::instanceof(r, cl_I_ring) && ::instanceof(i, cl_RA_ring))
             return numeric(::denominator(The(cl_RA)(i)));
         if (::instanceof(r, cl_RA_ring) && ::instanceof(i, cl_I_ring))
@@ -878,7 +879,7 @@ numeric numeric::denom(void) const
         cl_R r = realpart(*value);
         cl_R i = imagpart(*value);
         if (instanceof(r, cl_I_ring) && instanceof(i, cl_I_ring))
-            return numONE();
+            return _num1();
         if (instanceof(r, cl_I_ring) && instanceof(i, cl_RA_ring))
             return numeric(TheRatio(i)->denominator);
         if (instanceof(r, cl_RA_ring) && instanceof(i, cl_I_ring))
@@ -888,7 +889,7 @@ numeric numeric::denom(void) const
     }
 #endif // def SANE_LINKER
     // at least one float encountered
-    return numONE();
+    return _num1();
 }
 
 /** Size in binary notation.  For integers, this is the smallest n >= 0 such
@@ -924,56 +925,10 @@ type_info const & typeid_numeric=typeid(some_numeric);
  *  natively handing complex numbers anyways. */
 const numeric I = numeric(complex(cl_I(0),cl_I(1)));
 
-//////////
-// global functions
-//////////
-
-numeric const & numZERO(void)
-{
-    const static ex eZERO = ex((new numeric(0))->setflag(status_flags::dynallocated));
-    const static numeric * nZERO = static_cast<const numeric *>(eZERO.bp);
-    return *nZERO;
-}
-
-numeric const & numONE(void)
-{
-    const static ex eONE = ex((new numeric(1))->setflag(status_flags::dynallocated));
-    const static numeric * nONE = static_cast<const numeric *>(eONE.bp);
-    return *nONE;
-}
-
-numeric const & numTWO(void)
-{
-    const static ex eTWO = ex((new numeric(2))->setflag(status_flags::dynallocated));
-    const static numeric * nTWO = static_cast<const numeric *>(eTWO.bp);
-    return *nTWO;
-}
-
-numeric const & numTHREE(void)
-{
-    const static ex eTHREE = ex((new numeric(3))->setflag(status_flags::dynallocated));
-    const static numeric * nTHREE = static_cast<const numeric *>(eTHREE.bp);
-    return *nTHREE;
-}
-
-numeric const & numMINUSONE(void)
-{
-    const static ex eMINUSONE = ex((new numeric(-1))->setflag(status_flags::dynallocated));
-    const static numeric * nMINUSONE = static_cast<const numeric *>(eMINUSONE.bp);
-    return *nMINUSONE;
-}
-
-numeric const & numHALF(void)
-{
-    const static ex eHALF = ex((new numeric(1, 2))->setflag(status_flags::dynallocated));
-    const static numeric * nHALF = static_cast<const numeric *>(eHALF.bp);
-    return *nHALF;
-}
-
 /** Exponential function.
  *
  *  @return  arbitrary precision numerical exp(x). */
-numeric exp(numeric const & x)
+numeric exp(const numeric & x)
 {
     return ::exp(*x.value);  // -> CLN
 }
@@ -983,7 +938,7 @@ numeric exp(numeric const & x)
  *  @param z complex number
  *  @return  arbitrary precision numerical log(x).
  *  @exception overflow_error (logarithmic singularity) */
-numeric log(numeric const & z)
+numeric log(const numeric & z)
 {
     if (z.is_zero())
         throw (std::overflow_error("log(): logarithmic singularity"));
@@ -993,7 +948,7 @@ numeric log(numeric const & z)
 /** Numeric sine (trigonometric function).
  *
  *  @return  arbitrary precision numerical sin(x). */
-numeric sin(numeric const & x)
+numeric sin(const numeric & x)
 {
     return ::sin(*x.value);  // -> CLN
 }
@@ -1001,7 +956,7 @@ numeric sin(numeric const & x)
 /** Numeric cosine (trigonometric function).
  *
  *  @return  arbitrary precision numerical cos(x). */
-numeric cos(numeric const & x)
+numeric cos(const numeric & x)
 {
     return ::cos(*x.value);  // -> CLN
 }
@@ -1009,7 +964,7 @@ numeric cos(numeric const & x)
 /** Numeric tangent (trigonometric function).
  *
  *  @return  arbitrary precision numerical tan(x). */
-numeric tan(numeric const & x)
+numeric tan(const numeric & x)
 {
     return ::tan(*x.value);  // -> CLN
 }
@@ -1017,7 +972,7 @@ numeric tan(numeric const & x)
 /** Numeric inverse sine (trigonometric function).
  *
  *  @return  arbitrary precision numerical asin(x). */
-numeric asin(numeric const & x)
+numeric asin(const numeric & x)
 {
     return ::asin(*x.value);  // -> CLN
 }
@@ -1025,7 +980,7 @@ numeric asin(numeric const & x)
 /** Numeric inverse cosine (trigonometric function).
  *
  *  @return  arbitrary precision numerical acos(x). */
-numeric acos(numeric const & x)
+numeric acos(const numeric & x)
 {
     return ::acos(*x.value);  // -> CLN
 }
@@ -1035,11 +990,11 @@ numeric acos(numeric const & x)
  *  @param z complex number
  *  @return atan(z)
  *  @exception overflow_error (logarithmic singularity) */
-numeric atan(numeric const & x)
+numeric atan(const numeric & x)
 {
     if (!x.is_real() &&
         x.real().is_zero() &&
-        !abs(x.imag()).is_equal(numONE()))
+        !abs(x.imag()).is_equal(_num1()))
         throw (std::overflow_error("atan(): logarithmic singularity"));
     return ::atan(*x.value);  // -> CLN
 }
@@ -1049,7 +1004,7 @@ numeric atan(numeric const & x)
  *  @param x real number
  *  @param y real number
  *  @return atan(y/x) */
-numeric atan(numeric const & y, numeric const & x)
+numeric atan(const numeric & y, const numeric & x)
 {
     if (x.is_real() && y.is_real())
         return ::atan(realpart(*x.value), realpart(*y.value));  // -> CLN
@@ -1060,7 +1015,7 @@ numeric atan(numeric const & y, numeric const & x)
 /** Numeric hyperbolic sine (trigonometric function).
  *
  *  @return  arbitrary precision numerical sinh(x). */
-numeric sinh(numeric const & x)
+numeric sinh(const numeric & x)
 {
     return ::sinh(*x.value);  // -> CLN
 }
@@ -1068,7 +1023,7 @@ numeric sinh(numeric const & x)
 /** Numeric hyperbolic cosine (trigonometric function).
  *
  *  @return  arbitrary precision numerical cosh(x). */
-numeric cosh(numeric const & x)
+numeric cosh(const numeric & x)
 {
     return ::cosh(*x.value);  // -> CLN
 }
@@ -1076,7 +1031,7 @@ numeric cosh(numeric const & x)
 /** Numeric hyperbolic tangent (trigonometric function).
  *
  *  @return  arbitrary precision numerical tanh(x). */
-numeric tanh(numeric const & x)
+numeric tanh(const numeric & x)
 {
     return ::tanh(*x.value);  // -> CLN
 }
@@ -1084,7 +1039,7 @@ numeric tanh(numeric const & x)
 /** Numeric inverse hyperbolic sine (trigonometric function).
  *
  *  @return  arbitrary precision numerical asinh(x). */
-numeric asinh(numeric const & x)
+numeric asinh(const numeric & x)
 {
     return ::asinh(*x.value);  // -> CLN
 }
@@ -1092,7 +1047,7 @@ numeric asinh(numeric const & x)
 /** Numeric inverse hyperbolic cosine (trigonometric function).
  *
  *  @return  arbitrary precision numerical acosh(x). */
-numeric acosh(numeric const & x)
+numeric acosh(const numeric & x)
 {
     return ::acosh(*x.value);  // -> CLN
 }
@@ -1100,14 +1055,14 @@ numeric acosh(numeric const & x)
 /** Numeric inverse hyperbolic tangent (trigonometric function).
  *
  *  @return  arbitrary precision numerical atanh(x). */
-numeric atanh(numeric const & x)
+numeric atanh(const numeric & x)
 {
     return ::atanh(*x.value);  // -> CLN
 }
 
 /** Numeric evaluation of Riemann's Zeta function.  Currently works only for
  *  integer arguments. */
-numeric zeta(numeric const & x)
+numeric zeta(const numeric & x)
 {
     // A dirty hack to allow for things like zeta(3.0), since CLN currently
     // only knows about integer arguments and zeta(3).evalf() automatically
@@ -1127,7 +1082,7 @@ numeric zeta(numeric const & x)
 
 /** The gamma function.
  *  This is only a stub! */
-numeric gamma(numeric const & x)
+numeric gamma(const numeric & x)
 {
     clog << "gamma(" << x
          << "): Does anybody know good way to calculate this numerically?"
@@ -1137,7 +1092,7 @@ numeric gamma(numeric const & x)
 
 /** The psi function (aka polygamma function).
  *  This is only a stub! */
-numeric psi(numeric const & x)
+numeric psi(const numeric & x)
 {
     clog << "psi(" << x
          << "): Does anybody know good way to calculate this numerically?"
@@ -1147,7 +1102,7 @@ numeric psi(numeric const & x)
 
 /** The psi functions (aka polygamma functions).
  *  This is only a stub! */
-numeric psi(numeric const & n, numeric const & x)
+numeric psi(const numeric & n, const numeric & x)
 {
     clog << "psi(" << n << "," << x
          << "): Does anybody know good way to calculate this numerically?"
@@ -1158,7 +1113,7 @@ numeric psi(numeric const & n, numeric const & x)
 /** Factorial combinatorial function.
  *
  *  @exception range_error (argument must be integer >= 0) */
-numeric factorial(numeric const & nn)
+numeric factorial(const numeric & nn)
 {
     if (!nn.is_nonneg_integer())
         throw (std::range_error("numeric::factorial(): argument must be integer >= 0"));
@@ -1169,82 +1124,33 @@ numeric factorial(numeric const & nn)
  *  useful in cases, like for exact results of Gamma(n+1/2) for instance.)
  *
  *  @param n  integer argument >= -1
- *  @return n!! == n * (n-2) * (n-4) * ... * ({1|2}) with 0!! == 1 == (-1)!!
+ *  @return n!! == n * (n-2) * (n-4) * ... * ({1|2}) with 0!! == (-1)!! == 1
  *  @exception range_error (argument must be integer >= -1) */
-numeric doublefactorial(numeric const & nn)
+numeric doublefactorial(const numeric & nn)
 {
-    // META-NOTE:  The whole shit here will become obsolete and may be moved
-    // out once CLN learns about double factorial, which should be as soon as
-    // 1.0.3 rolls out!
-    
-    // We store the results separately for even and odd arguments.  This has
-    // the advantage that we don't have to compute any even result at all if
-    // the function is always called with odd arguments and vice versa.  There
-    // is no tradeoff involved in this, it is guaranteed to save time as well
-    // as memory.  (If this is not enough justification consider the Gamma
-    // function of half integer arguments: it only needs odd doublefactorials.)
-    static vector<numeric> evenresults;
-    static int highest_evenresult = -1;
-    static vector<numeric> oddresults;
-    static int highest_oddresult = -1;
-    
     if (nn == numeric(-1)) {
-        return numONE();
+        return _num1();
     }
     if (!nn.is_nonneg_integer()) {
         throw (std::range_error("numeric::doublefactorial(): argument must be integer >= -1"));
     }
-    if (nn.is_even()) {
-        int n = nn.div(numTWO()).to_int();
-        if (n <= highest_evenresult) {
-            return evenresults[n];
-        }
-        if (evenresults.capacity() < (unsigned)(n+1)) {
-            evenresults.reserve(n+1);
-        }
-        if (highest_evenresult < 0) {
-            evenresults.push_back(numONE());
-            highest_evenresult=0;
-        }
-        for (int i=highest_evenresult+1; i<=n; i++) {
-            evenresults.push_back(numeric(evenresults[i-1].mul(numeric(i*2))));
-        }
-        highest_evenresult=n;
-        return evenresults[n];
-    } else {
-        int n = nn.sub(numONE()).div(numTWO()).to_int();
-        if (n <= highest_oddresult) {
-            return oddresults[n];
-        }
-        if (oddresults.capacity() < (unsigned)n) {
-            oddresults.reserve(n+1);
-        }
-        if (highest_oddresult < 0) {
-            oddresults.push_back(numONE());
-            highest_oddresult=0;
-        }
-        for (int i=highest_oddresult+1; i<=n; i++) {
-            oddresults.push_back(numeric(oddresults[i-1].mul(numeric(i*2+1))));
-        }
-        highest_oddresult=n;
-        return oddresults[n];
-    }
+    return numeric(::doublefactorial(nn.to_int()));  // -> CLN
 }
 
 /** The Binomial coefficients.  It computes the binomial coefficients.  For
  *  integer n and k and positive n this is the number of ways of choosing k
  *  objects from n distinct objects.  If n is negative, the formula
  *  binomial(n,k) == (-1)^k*binomial(k-n-1,k) is used to compute the result. */
-numeric binomial(numeric const & n, numeric const & k)
+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(numZERO())!=-1)
+            if (k.compare(n)!=1 && k.compare(_num0())!=-1)
                 return numeric(::binomial(n.to_int(),k.to_int()));  // -> CLN
             else
-                return numZERO();
+                return _num0();
         } else {
-            return numMINUSONE().power(k)*binomial(k-n-numONE(),k);
+            return _num_1().power(k)*binomial(k-n-_num1(),k);
         }
     }
     
@@ -1257,16 +1163,16 @@ numeric binomial(numeric const & n, numeric const & k)
  *
  *  @return the nth Bernoulli number (a rational number).
  *  @exception range_error (argument must be integer >= 0) */
-numeric bernoulli(numeric const & nn)
+numeric bernoulli(const numeric & nn)
 {
     if (!nn.is_integer() || nn.is_negative())
         throw (std::range_error("numeric::bernoulli(): argument must be integer >= 0"));
     if (nn.is_zero())
-        return numONE();
-    if (!nn.compare(numONE()))
+        return _num1();
+    if (!nn.compare(_num1()))
         return numeric(-1,2);
     if (nn.is_odd())
-        return numZERO();
+        return _num0();
     // Until somebody has the Blues and comes up with a much better idea and
     // codes it (preferably in CLN) we make this a remembering function which
     // computes its results using the formula
@@ -1274,7 +1180,7 @@ numeric bernoulli(numeric const & nn)
     // whith B(0) == 1.
     static vector<numeric> results;
     static int highest_result = -1;
-    int n = nn.sub(numTWO()).div(numTWO()).to_int();
+    int n = nn.sub(_num2()).div(_num2()).to_int();
     if (n <= highest_result)
         return results[n];
     if (results.capacity() < (unsigned)(n+1))
@@ -1295,7 +1201,7 @@ numeric bernoulli(numeric const & nn)
 }
 
 /** Absolute value. */
-numeric abs(numeric const & x)
+numeric abs(const numeric & x)
 {
     return ::abs(*x.value);  // -> CLN
 }
@@ -1307,25 +1213,26 @@ numeric abs(numeric const & x)
  *
  *  @return a mod b in the range [0,abs(b)-1] with sign of b if both are
  *  integer, 0 otherwise. */
-numeric mod(numeric const & a, numeric const & b)
+numeric mod(const numeric & a, const numeric & b)
 {
     if (a.is_integer() && b.is_integer())
         return ::mod(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
-        return numZERO();  // Throw?
+        return _num0();  // Throw?
 }
 
 /** Modulus (in symmetric representation).
  *  Equivalent to Maple's mods.
  *
  *  @return a mod b in the range [-iquo(abs(m)-1,2), iquo(abs(m),2)]. */
-numeric smod(numeric const & a, numeric const & b)
+numeric smod(const numeric & a, const numeric & b)
 {
+    //  FIXME: Should this become a member function?
     if (a.is_integer() && b.is_integer()) {
         cl_I b2 = The(cl_I)(ceiling1(The(cl_I)(*b.value) / 2)) - 1;
         return ::mod(The(cl_I)(*a.value) + b2, The(cl_I)(*b.value)) - b2;
     } else
-        return numZERO();  // Throw?
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1334,12 +1241,12 @@ numeric smod(numeric const & a, numeric const & b)
  *  sign of a or is zero.
  *
  *  @return remainder of a/b if both are integer, 0 otherwise. */
-numeric irem(numeric const & a, numeric const & b)
+numeric irem(const numeric & a, const numeric & b)
 {
     if (a.is_integer() && b.is_integer())
         return ::rem(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
-        return numZERO();  // Throw?
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1349,7 +1256,7 @@ numeric irem(numeric const & a, numeric const & b)
  *
  *  @return remainder of a/b and quotient stored in q if both are integer,
  *  0 otherwise. */
-numeric irem(numeric const & a, numeric const & b, numeric & q)
+numeric irem(const numeric & a, const numeric & b, numeric & q)
 {
     if (a.is_integer() && b.is_integer()) {  // -> CLN
         cl_I_div_t rem_quo = truncate2(The(cl_I)(*a.value), The(cl_I)(*b.value));
@@ -1357,8 +1264,8 @@ numeric irem(numeric const & a, numeric const & b, numeric & q)
         return rem_quo.remainder;
     }
     else {
-        q = numZERO();
-        return numZERO();  // Throw?
+        q = _num0();
+        return _num0();  // Throw?
     }
 }
 
@@ -1366,12 +1273,12 @@ numeric irem(numeric const & a, numeric const & b, numeric & q)
  *  Equivalent to Maple's iquo as far as sign conventions are concerned.
  *  
  *  @return truncated quotient of a/b if both are integer, 0 otherwise. */
-numeric iquo(numeric const & a, numeric const & b)
+numeric iquo(const numeric & a, const numeric & b)
 {
     if (a.is_integer() && b.is_integer())
         return truncate1(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
-        return numZERO();  // Throw?
+        return _num0();  // Throw?
 }
 
 /** Numeric integer quotient.
@@ -1380,15 +1287,15 @@ numeric iquo(numeric const & a, numeric const & b)
  *
  *  @return truncated quotient of a/b and remainder stored in r if both are
  *  integer, 0 otherwise. */
-numeric iquo(numeric const & a, numeric const & b, numeric & r)
+numeric iquo(const numeric & a, const numeric & b, numeric & r)
 {
     if (a.is_integer() && b.is_integer()) {  // -> CLN
         cl_I_div_t rem_quo = truncate2(The(cl_I)(*a.value), The(cl_I)(*b.value));
         r = rem_quo.remainder;
         return rem_quo.quotient;
     } else {
-        r = numZERO();
-        return numZERO();  // Throw?
+        r = _num0();
+        return _num0();  // Throw?
     }
 }
 
@@ -1400,39 +1307,39 @@ numeric iquo(numeric const & a, numeric const & b, numeric & r)
  *  @return square root of z. Branch cut along negative real axis, the negative
  *  real axis itself where imag(z)==0 and real(z)<0 belongs to the upper part
  *  where imag(z)>0. */
-numeric sqrt(numeric const & z)
+numeric sqrt(const numeric & z)
 {
     return ::sqrt(*z.value);  // -> CLN
 }
 
 /** Integer numeric square root. */
-numeric isqrt(numeric const & x)
+numeric isqrt(const numeric & x)
 {
     if (x.is_integer()) {
         cl_I root;
         ::isqrt(The(cl_I)(*x.value), &root);  // -> CLN
         return root;
     } else
-        return numZERO();  // Throw?
+        return _num0();  // Throw?
 }
 
 /** Greatest Common Divisor.
  *   
  *  @return  The GCD of two numbers if both are integer, a numerical 1
  *  if they are not. */
-numeric gcd(numeric const & a, numeric const & b)
+numeric gcd(const numeric & a, const numeric & b)
 {
     if (a.is_integer() && b.is_integer())
         return ::gcd(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
-        return numONE();
+        return _num1();
 }
 
 /** Least Common Multiple.
  *   
  *  @return  The LCM of two numbers if both are integer, the product of those
  *  two numbers if they are not. */
-numeric lcm(numeric const & a, numeric const & b)
+numeric lcm(const numeric & a, const numeric & b)
 {
     if (a.is_integer() && b.is_integer())
         return ::lcm(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN