]> www.ginac.de Git - ginac.git/blobdiff - ginac/numeric.cpp
- Banned exZERO(), exONE(), exMINUSHALF() and all this from the interface.
[ginac.git] / ginac / numeric.cpp
index 4ab0c1758eed5562ad000b7850602aabbbe3806c..472d9c31034de58b38dfd40dbfd2da8ff0790962 100644 (file)
@@ -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:
@@ -275,6 +276,49 @@ void numeric::print(ostream & os, unsigned upper_precedence) const
     }
 }
 
+void numeric::printtree(ostream & os, unsigned indent) const
+{
+    debugmsg("numeric printtree", LOGLEVEL_PRINT);
+    os << string(indent,' ') << *value
+       << " (numeric): "
+       << "hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
+       << ", flags=" << flags << endl;
+}
+
+void numeric::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+{
+    debugmsg("numeric print csrc", LOGLEVEL_PRINT);
+    ios::fmtflags oldflags = os.flags();
+    os.setf(ios::scientific);
+    if (is_rational() && !is_integer()) {
+        if (compare(_num0()) > 0) {
+            os << "(";
+            if (type == csrc_types::ctype_cl_N)
+                os << "cl_F(\"" << numer().evalf() << "\")";
+            else
+                os << numer().to_double();
+        } else {
+            os << "-(";
+            if (type == csrc_types::ctype_cl_N)
+                os << "cl_F(\"" << -numer().evalf() << "\")";
+            else
+                os << -numer().to_double();
+        }
+        os << "/";
+        if (type == csrc_types::ctype_cl_N)
+            os << "cl_F(\"" << denom().evalf() << "\")";
+        else
+            os << denom().to_double();
+        os << ")";
+    } else {
+        if (type == csrc_types::ctype_cl_N)
+            os << "cl_F(\"" << evalf() << "\")";
+        else
+            os << to_double();
+    }
+    os.flags(oldflags);
+}
+
 bool numeric::info(unsigned inf) const
 {
     switch (inf) {
@@ -287,19 +331,25 @@ bool numeric::info(unsigned inf) const
     case info_flags::rational:
     case info_flags::rational_polynomial:
         return is_rational();
+    case info_flags::crational:
+    case info_flags::crational_polynomial:
+        return is_crational();
     case info_flags::integer:
     case info_flags::integer_polynomial:
         return is_integer();
+    case info_flags::cinteger:
+    case info_flags::cinteger_polynomial:
+        return is_cinteger();
     case info_flags::positive:
         return is_positive();
     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:
@@ -317,7 +367,7 @@ bool numeric::info(unsigned inf) const
  *  currently set.
  *
  *  @param level  ignored, but needed for overriding basic::evalf.
- *  @return an ex-handle to a numeric. */
+ *  @return  an ex-handle to a numeric. */
 ex numeric::evalf(int level) const
 {
     // level can safely be discarded for numeric objects.
@@ -390,10 +440,10 @@ numeric numeric::sub(numeric const & other) const
  *  result as a new numeric object. */
 numeric numeric::mul(numeric const & 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));
@@ -405,26 +455,25 @@ numeric numeric::mul(numeric const & other) const
  *  @exception overflow_error (division by zero) */
 numeric numeric::div(numeric const & other) const
 {
-    if (zerop(*other.value))
+    if (::zerop(*other.value))
         throw (std::overflow_error("division by zero"));
     return numeric((*value)/(*other.value));
 }
 
 numeric numeric::power(numeric const & 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)))
+    if (::zerop(*value) && other.is_real() && ::minusp(realpart(*other.value)))
         throw (std::overflow_error("division by zero"));
-    return numeric(expt(*value,*other.value));
+    return numeric(::expt(*value,*other.value));
 }
 
 /** Inverse of a number. */
 numeric numeric::inverse(void) const
 {
-    return numeric(recip(*value));  // -> CLN
+    return numeric(::recip(*value));  // -> CLN
 }
 
 numeric const & numeric::add_dyn(numeric const & other) const
@@ -441,10 +490,10 @@ numeric const & numeric::sub_dyn(numeric const & other) const
 
 numeric const & numeric::mul_dyn(numeric const & 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)))->
@@ -453,7 +502,7 @@ numeric const & numeric::mul_dyn(numeric const & other) const
 
 numeric const & numeric::div_dyn(numeric const & other) const
 {
-    if (zerop(*other.value))
+    if (::zerop(*other.value))
         throw (std::overflow_error("division by zero"));
     return static_cast<numeric const &>((new numeric((*value)/(*other.value)))->
                                         setflag(status_flags::dynallocated));
@@ -461,30 +510,13 @@ numeric const & numeric::div_dyn(numeric const & other) const
 
 numeric const & numeric::power_dyn(numeric const & other) const
 {
-    static const numeric * numONEp=&numONE();
-    if (&other==numONEp) {
+    static const numeric * _num1p=&_num1();
+    if (&other==_num1p)
         return *this;
-    }
-    // The ifs are only a workaround for a bug in CLN. It gets stuck otherwise:
-    if ( !other.is_integer() &&
-         other.is_rational() &&
-         (*this).is_nonneg_integer() ) {
-        if ( !zerop(*value) ) {
-            return static_cast<numeric const &>((new numeric(exp(*other.value * log(*value))))->
-                                                setflag(status_flags::dynallocated));
-        } else {
-            if ( !zerop(*other.value) ) {  // 0^(n/m)
-                return static_cast<numeric const &>((new numeric(0))->
-                                                    setflag(status_flags::dynallocated));
-            } else {                       // raise FPE (0^0 requested)
-                return static_cast<numeric const &>((new numeric(1/(*other.value)))->
-                                                    setflag(status_flags::dynallocated));
-            }
-        }
-    } else {                               // default -> CLN
-        return static_cast<numeric const &>((new numeric(expt(*value,*other.value)))->
-                                            setflag(status_flags::dynallocated));
-    }
+    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)))->
+                                        setflag(status_flags::dynallocated));
 }
 
 numeric const & numeric::operator=(int i)
@@ -526,13 +558,13 @@ int numeric::csgn(void) const
 {
     if (is_zero())
         return 0;
-    if (!zerop(realpart(*value))) {
-        if (plusp(realpart(*value)))
+    if (!::zerop(realpart(*value))) {
+        if (::plusp(realpart(*value)))
             return 1;
         else
             return -1;
     } else {
-        if (plusp(imagpart(*value)))
+        if (::plusp(imagpart(*value)))
             return 1;
         else
             return -1;
@@ -551,14 +583,14 @@ int numeric::compare(numeric const & other) const
     // Comparing two real numbers?
     if (is_real() && other.is_real())
         // Yes, just compare them
-        return cl_compare(The(cl_R)(*value), The(cl_R)(*other.value));    
+        return ::cl_compare(The(cl_R)(*value), The(cl_R)(*other.value));    
     else {
         // No, first compare real parts
-        cl_signean real_cmp = cl_compare(realpart(*value), realpart(*other.value));
+        cl_signean real_cmp = ::cl_compare(realpart(*value), realpart(*other.value));
         if (real_cmp)
             return real_cmp;
 
-        return cl_compare(imagpart(*value), imagpart(*other.value));
+        return ::cl_compare(imagpart(*value), imagpart(*other.value));
     }
 }
 
@@ -570,59 +602,53 @@ bool numeric::is_equal(numeric const & other) const
 /** True if object is zero. */
 bool numeric::is_zero(void) const
 {
-    return zerop(*value);  // -> CLN
+    return ::zerop(*value);  // -> CLN
 }
 
 /** True if object is not complex and greater than zero. */
 bool numeric::is_positive(void) const
 {
-    if (is_real()) {
-        return plusp(The(cl_R)(*value));  // -> CLN
-    }
+    if (is_real())
+        return ::plusp(The(cl_R)(*value));  // -> CLN
     return false;
 }
 
 /** True if object is not complex and less than zero. */
 bool numeric::is_negative(void) const
 {
-    if (is_real()) {
-        return minusp(The(cl_R)(*value));  // -> CLN
-    }
+    if (is_real())
+        return ::minusp(The(cl_R)(*value));  // -> CLN
     return false;
 }
 
 /** True if object is a non-complex integer. */
 bool numeric::is_integer(void) const
 {
-    return (bool)instanceof(*value, cl_I_ring);  // -> CLN
+    return ::instanceof(*value, cl_I_ring);  // -> CLN
 }
 
 /** True if object is an exact integer greater than zero. */
 bool numeric::is_pos_integer(void) const
 {
-    return (is_integer() &&
-            plusp(The(cl_I)(*value)));  // -> CLN
+    return (is_integer() && ::plusp(The(cl_I)(*value)));  // -> CLN
 }
 
 /** True if object is an exact integer greater or equal zero. */
 bool numeric::is_nonneg_integer(void) const
 {
-    return (is_integer() &&
-            !minusp(The(cl_I)(*value)));  // -> CLN
+    return (is_integer() && !::minusp(The(cl_I)(*value)));  // -> CLN
 }
 
 /** True if object is an exact even integer. */
 bool numeric::is_even(void) const
 {
-    return (is_integer() &&
-            evenp(The(cl_I)(*value)));  // -> CLN
+    return (is_integer() && ::evenp(The(cl_I)(*value)));  // -> CLN
 }
 
 /** True if object is an exact odd integer. */
 bool numeric::is_odd(void) const
 {
-    return (is_integer() &&
-            oddp(The(cl_I)(*value)));  // -> CLN
+    return (is_integer() && ::oddp(The(cl_I)(*value)));  // -> CLN
 }
 
 /** Probabilistic primality test.
@@ -630,28 +656,20 @@ bool numeric::is_odd(void) const
  *  @return  true if object is exact integer and prime. */
 bool numeric::is_prime(void) const
 {
-    return (is_integer() &&
-            isprobprime(The(cl_I)(*value)));  // -> CLN
+    return (is_integer() && ::isprobprime(The(cl_I)(*value)));  // -> CLN
 }
 
 /** True if object is an exact rational number, may even be complex
  *  (denominator may be unity). */
 bool numeric::is_rational(void) const
 {
-    if (instanceof(*value, cl_RA_ring)) {
-        return true;
-    } else if (!is_real()) {  // complex case, handle Q(i):
-        if ( instanceof(realpart(*value), cl_RA_ring) &&
-             instanceof(imagpart(*value), cl_RA_ring) )
-            return true;
-    }
-    return false;
+    return ::instanceof(*value, cl_RA_ring);  // -> CLN
 }
 
 /** True if object is a real integer, rational or float (but not complex). */
 bool numeric::is_real(void) const
 {
-    return (bool)instanceof(*value, cl_R_ring);  // -> CLN
+    return ::instanceof(*value, cl_R_ring);  // -> CLN
 }
 
 bool numeric::operator==(numeric const & other) const
@@ -664,14 +682,41 @@ bool numeric::operator!=(numeric const & other) const
     return (*value != *other.value);  // -> CLN
 }
 
+/** True if object is element of the domain of integers extended by I, i.e. is
+ *  of the form a+b*I, where a and b are integers. */
+bool numeric::is_cinteger(void) const
+{
+    if (::instanceof(*value, cl_I_ring))
+        return true;
+    else if (!is_real()) {  // complex case, handle n+m*I
+        if (::instanceof(realpart(*value), cl_I_ring) &&
+            ::instanceof(imagpart(*value), cl_I_ring))
+            return true;
+    }
+    return false;
+}
+
+/** True if object is an exact rational number, may even be complex
+ *  (denominator may be unity). */
+bool numeric::is_crational(void) const
+{
+    if (::instanceof(*value, cl_RA_ring))
+        return true;
+    else if (!is_real()) {  // complex case, handle Q(i):
+        if (::instanceof(realpart(*value), cl_RA_ring) &&
+            ::instanceof(imagpart(*value), cl_RA_ring))
+            return true;
+    }
+    return false;
+}
+
 /** Numerical comparison: less.
  *
  *  @exception invalid_argument (complex inequality) */ 
 bool numeric::operator<(numeric const & other) const
 {
-    if ( is_real() && other.is_real() ) {
+    if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) < The(cl_R)(*other.value));  // -> CLN
-    }
     throw (std::invalid_argument("numeric::operator<(): complex inequality"));
     return false;  // make compiler shut up
 }
@@ -681,9 +726,8 @@ bool numeric::operator<(numeric const & other) const
  *  @exception invalid_argument (complex inequality) */ 
 bool numeric::operator<=(numeric const & other) const
 {
-    if ( is_real() && other.is_real() ) {
+    if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) <= The(cl_R)(*other.value));  // -> CLN
-    }
     throw (std::invalid_argument("numeric::operator<=(): complex inequality"));
     return false;  // make compiler shut up
 }
@@ -693,9 +737,8 @@ bool numeric::operator<=(numeric const & other) const
  *  @exception invalid_argument (complex inequality) */ 
 bool numeric::operator>(numeric const & other) const
 {
-    if ( is_real() && other.is_real() ) {
+    if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) > The(cl_R)(*other.value));  // -> CLN
-    }
     throw (std::invalid_argument("numeric::operator>(): complex inequality"));
     return false;  // make compiler shut up
 }
@@ -705,9 +748,8 @@ bool numeric::operator>(numeric const & other) const
  *  @exception invalid_argument (complex inequality) */  
 bool numeric::operator>=(numeric const & other) const
 {
-    if ( is_real() && other.is_real() ) {
+    if (is_real() && other.is_real())
         return (bool)(The(cl_R)(*value) >= The(cl_R)(*other.value));  // -> CLN
-    }
     throw (std::invalid_argument("numeric::operator>=(): complex inequality"));
     return false;  // make compiler shut up
 }
@@ -717,7 +759,7 @@ bool numeric::operator>=(numeric const & other) const
 int numeric::to_int(void) const
 {
     GINAC_ASSERT(is_integer());
-    return cl_I_to_int(The(cl_I)(*value));
+    return ::cl_I_to_int(The(cl_I)(*value));  // -> CLN
 }
 
 /** Converts numeric types to machine's double. You should check with is_real()
@@ -725,19 +767,19 @@ int numeric::to_int(void) const
 double numeric::to_double(void) const
 {
     GINAC_ASSERT(is_real());
-    return cl_double_approx(realpart(*value));
+    return ::cl_double_approx(realpart(*value));  // -> CLN
 }
 
 /** Real part of a number. */
 numeric numeric::real(void) const
 {
-    return numeric(realpart(*value));  // -> CLN
+    return numeric(::realpart(*value));  // -> CLN
 }
 
 /** Imaginary part of a number. */
 numeric numeric::imag(void) const
 {
-    return numeric(imagpart(*value));  // -> CLN
+    return numeric(::imagpart(*value));  // -> CLN
 }
 
 #ifndef SANE_LINKER
@@ -763,22 +805,22 @@ numeric numeric::numer(void) const
         return numeric(*this);
     }
 #ifdef SANE_LINKER
-    else if (instanceof(*value, cl_RA_ring)) {
-        return numeric(numerator(The(cl_RA)(*value)));
+    else if (::instanceof(*value, cl_RA_ring)) {
+        return numeric(::numerator(The(cl_RA)(*value)));
     }
     else if (!is_real()) {  // complex case, handle Q(i):
-        cl_R r = realpart(*value);
-        cl_R i = imagpart(*value);
-        if (instanceof(r, cl_I_ring) && instanceof(i, cl_I_ring))
+        cl_R r = ::realpart(*value);
+        cl_R i = ::imagpart(*value);
+        if (::instanceof(r, cl_I_ring) && ::instanceof(i, cl_I_ring))
             return numeric(*this);
-        if (instanceof(r, cl_I_ring) && instanceof(i, cl_RA_ring))
-            return numeric(complex(r*denominator(The(cl_RA)(i)), numerator(The(cl_RA)(i))));
-        if (instanceof(r, cl_RA_ring) && instanceof(i, cl_I_ring))
-            return numeric(complex(numerator(The(cl_RA)(r)), i*denominator(The(cl_RA)(r))));
-        if (instanceof(r, cl_RA_ring) && instanceof(i, cl_RA_ring)) {
-            cl_I s = lcm(denominator(The(cl_RA)(r)), denominator(The(cl_RA)(i)));
-            return numeric(complex(numerator(The(cl_RA)(r))*(exquo(s,denominator(The(cl_RA)(r)))),
-                                   numerator(The(cl_RA)(i))*(exquo(s,denominator(The(cl_RA)(i))))));
+        if (::instanceof(r, cl_I_ring) && ::instanceof(i, cl_RA_ring))
+            return numeric(complex(r*::denominator(The(cl_RA)(i)), ::numerator(The(cl_RA)(i))));
+        if (::instanceof(r, cl_RA_ring) && ::instanceof(i, cl_I_ring))
+            return numeric(complex(::numerator(The(cl_RA)(r)), i*::denominator(The(cl_RA)(r))));
+        if (::instanceof(r, cl_RA_ring) && ::instanceof(i, cl_RA_ring)) {
+            cl_I s = lcm(::denominator(The(cl_RA)(r)), ::denominator(The(cl_RA)(i)));
+            return numeric(complex(::numerator(The(cl_RA)(r))*(exquo(s,::denominator(The(cl_RA)(r)))),
+                                   ::numerator(The(cl_RA)(i))*(exquo(s,::denominator(The(cl_RA)(i))))));
         }
     }
 #else
@@ -811,23 +853,23 @@ 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)) {
-        return numeric(denominator(The(cl_RA)(*value)));
+        return numeric(::denominator(The(cl_RA)(*value)));
     }
     if (!is_real()) {  // complex case, handle Q(i):
         cl_R r = realpart(*value);
         cl_R i = imagpart(*value);
-        if (instanceof(r, cl_I_ring) && instanceof(i, cl_I_ring))
-            return numONE();
-        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))
-            return numeric(denominator(The(cl_RA)(r)));
-        if (instanceof(r, cl_RA_ring) && instanceof(i, cl_RA_ring))
-            return numeric(lcm(denominator(The(cl_RA)(r)), denominator(The(cl_RA)(i))));
+        if (::instanceof(r, cl_I_ring) && ::instanceof(i, cl_I_ring))
+            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))
+            return numeric(::denominator(The(cl_RA)(r)));
+        if (::instanceof(r, cl_RA_ring) && ::instanceof(i, cl_RA_ring))
+            return numeric(lcm(::denominator(The(cl_RA)(r)), ::denominator(The(cl_RA)(i))));
     }
 #else
     if (instanceof(*value, cl_RA_ring)) {
@@ -837,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))
@@ -847,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
@@ -858,11 +900,10 @@ numeric numeric::denom(void) const
  *  in two's complement if it is an integer, 0 otherwise. */    
 int numeric::int_length(void) const
 {
-    if (is_integer()) {
-        return integer_length(The(cl_I)(*value));  // -> CLN
-    } else {
+    if (is_integer())
+        return ::integer_length(The(cl_I)(*value));  // -> CLN
+    else
         return 0;
-    }
 }
 
 
@@ -884,52 +925,6 @@ 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). */
@@ -999,7 +994,7 @@ numeric atan(numeric const & 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
 }
@@ -1069,10 +1064,19 @@ numeric atanh(numeric const & x)
  *  integer arguments. */
 numeric zeta(numeric const & x)
 {
-    if (x.is_integer())
-        return ::cl_zeta(x.to_int());  // -> CLN
-    else
-        clog << "zeta(): Does anybody know good way to calculate this numerically?" << endl;
+    // A dirty hack to allow for things like zeta(3.0), since CLN currently
+    // only knows about integer arguments and zeta(3).evalf() automatically
+    // cascades down to zeta(3.0).evalf().  The trick is to rely on 3.0-3
+    // being an exact zero for CLN, which can be tested and then we can just
+    // pass the number casted to an int:
+    if (x.is_real()) {
+        int aux = (int)(::cl_double_approx(realpart(*x.value)));
+        if (zerop(*x.value-aux))
+            return ::cl_zeta(aux);  // -> CLN
+    }
+    clog << "zeta(" << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
     return numeric(0);
 }
 
@@ -1080,7 +1084,9 @@ numeric zeta(numeric const & x)
  *  This is only a stub! */
 numeric gamma(numeric const & x)
 {
-    clog << "gamma(): Does anybody know good way to calculate this numerically?" << endl;
+    clog << "gamma(" << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
     return numeric(0);
 }
 
@@ -1088,7 +1094,9 @@ numeric gamma(numeric const & x)
  *  This is only a stub! */
 numeric psi(numeric const & x)
 {
-    clog << "psi(): Does anybody know good way to calculate this numerically?" << endl;
+    clog << "psi(" << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
     return numeric(0);
 }
 
@@ -1096,7 +1104,9 @@ numeric psi(numeric const & x)
  *  This is only a stub! */
 numeric psi(numeric const & n, numeric const & x)
 {
-    clog << "psi(): Does anybody know good way to calculate this numerically?" << endl;
+    clog << "psi(" << n << "," << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
     return numeric(0);
 }
 
@@ -1105,10 +1115,8 @@ numeric psi(numeric const & n, numeric const & x)
  *  @exception range_error (argument must be integer >= 0) */
 numeric factorial(numeric const & nn)
 {
-    if ( !nn.is_nonneg_integer() ) {
+    if (!nn.is_nonneg_integer())
         throw (std::range_error("numeric::factorial(): argument must be integer >= 0"));
-    }
-    
     return numeric(::factorial(nn.to_int()));  // -> CLN
 }
 
@@ -1136,13 +1144,13 @@ numeric doublefactorial(numeric const & nn)
     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();
+        int n = nn.div(_num2()).to_int();
         if (n <= highest_evenresult) {
             return evenresults[n];
         }
@@ -1150,7 +1158,7 @@ numeric doublefactorial(numeric const & nn)
             evenresults.reserve(n+1);
         }
         if (highest_evenresult < 0) {
-            evenresults.push_back(numONE());
+            evenresults.push_back(_num1());
             highest_evenresult=0;
         }
         for (int i=highest_evenresult+1; i<=n; i++) {
@@ -1159,7 +1167,7 @@ numeric doublefactorial(numeric const & nn)
         highest_evenresult=n;
         return evenresults[n];
     } else {
-        int n = nn.sub(numONE()).div(numTWO()).to_int();
+        int n = nn.sub(_num1()).div(_num2()).to_int();
         if (n <= highest_oddresult) {
             return oddresults[n];
         }
@@ -1167,7 +1175,7 @@ numeric doublefactorial(numeric const & nn)
             oddresults.reserve(n+1);
         }
         if (highest_oddresult < 0) {
-            oddresults.push_back(numONE());
+            oddresults.push_back(_num1());
             highest_oddresult=0;
         }
         for (int i=highest_oddresult+1; i<=n; i++) {
@@ -1186,13 +1194,13 @@ numeric binomial(numeric const & n, numeric const & 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);
+        }
     }
     
     // should really be gamma(n+1)/(gamma(r+1)/gamma(n-r+1) or a suitable limit
@@ -1209,11 +1217,11 @@ numeric bernoulli(numeric const & 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
@@ -1221,7 +1229,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))
@@ -1256,12 +1264,10 @@ numeric abs(numeric const & x)
  *  integer, 0 otherwise. */
 numeric mod(numeric const & a, numeric const & b)
 {
-    if (a.is_integer() && b.is_integer()) {
+    if (a.is_integer() && b.is_integer())
         return ::mod(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
-    }
-    else {
-        return numZERO();  // Throw?
-    }
+    else
+        return _num0();  // Throw?
 }
 
 /** Modulus (in symmetric representation).
@@ -1270,12 +1276,12 @@ numeric mod(numeric const & a, numeric const & b)
  *  @return a mod b in the range [-iquo(abs(m)-1,2), iquo(abs(m),2)]. */
 numeric smod(numeric const & a, numeric const & 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?
-    }
+    } else
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1286,12 +1292,10 @@ numeric smod(numeric const & a, numeric const & b)
  *  @return remainder of a/b if both are integer, 0 otherwise. */
 numeric irem(numeric const & a, numeric const & b)
 {
-    if (a.is_integer() && b.is_integer()) {
+    if (a.is_integer() && b.is_integer())
         return ::rem(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
-    }
-    else {
-        return numZERO();  // Throw?
-    }
+    else
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1309,8 +1313,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?
     }
 }
 
@@ -1320,11 +1324,10 @@ numeric irem(numeric const & a, numeric const & b, numeric & q)
  *  @return truncated quotient of a/b if both are integer, 0 otherwise. */
 numeric iquo(numeric const & a, numeric const & b)
 {
-    if (a.is_integer() && b.is_integer()) {
+    if (a.is_integer() && b.is_integer())
         return truncate1(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
-    } else {
-        return numZERO();  // Throw?
-    }
+    else
+        return _num0();  // Throw?
 }
 
 /** Numeric integer quotient.
@@ -1340,8 +1343,8 @@ numeric iquo(numeric const & a, numeric const & b, numeric & r)
         r = rem_quo.remainder;
         return rem_quo.quotient;
     } else {
-        r = numZERO();
-        return numZERO();  // Throw?
+        r = _num0();
+        return _num0();  // Throw?
     }
 }
 
@@ -1361,12 +1364,12 @@ numeric sqrt(numeric const & z)
 /** Integer numeric square root. */
 numeric isqrt(numeric const & x)
 {
-       if (x.is_integer()) {
-               cl_I root;
-               ::isqrt(The(cl_I)(*x.value), &root);    // -> CLN
-               return root;
-       } else
-               return numZERO();  // Throw?
+    if (x.is_integer()) {
+        cl_I root;
+        ::isqrt(The(cl_I)(*x.value), &root);  // -> CLN
+        return root;
+    } else
+        return _num0();  // Throw?
 }
 
 /** Greatest Common Divisor.
@@ -1376,9 +1379,9 @@ numeric isqrt(numeric const & x)
 numeric gcd(numeric const & a, numeric const & b)
 {
     if (a.is_integer() && b.is_integer())
-        return ::gcd(The(cl_I)(*a.value), The(cl_I)(*b.value));        // -> CLN
+        return ::gcd(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
-        return numONE();
+        return _num1();
 }
 
 /** Least Common Multiple.
@@ -1388,7 +1391,7 @@ numeric gcd(numeric const & a, numeric const & b)
 numeric lcm(numeric const & a, numeric const & b)
 {
     if (a.is_integer() && b.is_integer())
-        return ::lcm(The(cl_I)(*a.value), The(cl_I)(*b.value));        // -> CLN
+        return ::lcm(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
     else
         return *a.value * *b.value;
 }