]> 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 fa17175c47e4dc82907d875b3e2ddfbd77a0d574..472d9c31034de58b38dfd40dbfd2da8ff0790962 100644 (file)
@@ -4,8 +4,9 @@
  *  Its most important design principle is to completely hide the inner
  *  working of that other package from the user of GiNaC.  It must either 
  *  provide implementation of arithmetic operators and numerical evaluation
- *  of special functions or implement the interface to the bignum package.
- *
+ *  of special functions or implement the interface to the bignum package. */
+
+/*
  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
 #include <vector>
 #include <stdexcept>
 
-#include "ginac.h"
+#include "numeric.h"
+#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:
 #include <cln.h>
 #endif
 
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
 // linker has no problems finding text symbols for numerator or denominator
 //#define SANE_LINKER
 
@@ -48,7 +56,7 @@
 // public
 
 /** default ctor. Numerically it initializes to an integer zero. */
-numeric::numeric() : basic(TINFO_NUMERIC)
+numeric::numeric() : basic(TINFO_numeric)
 {
     debugmsg("numeric default constructor", LOGLEVEL_CONSTRUCT);
     value = new cl_N;
@@ -100,7 +108,7 @@ void numeric::destroy(bool call_parent)
 
 // public
 
-numeric::numeric(int i) : basic(TINFO_NUMERIC)
+numeric::numeric(int i) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from int",LOGLEVEL_CONSTRUCT);
     // Not the whole int-range is available if we don't cast to long
@@ -112,7 +120,7 @@ numeric::numeric(int i) : basic(TINFO_NUMERIC)
             status_flags::hash_calculated);
 }
 
-numeric::numeric(unsigned int i) : basic(TINFO_NUMERIC)
+numeric::numeric(unsigned int i) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from uint",LOGLEVEL_CONSTRUCT);
     // Not the whole uint-range is available if we don't cast to ulong
@@ -124,7 +132,7 @@ numeric::numeric(unsigned int i) : basic(TINFO_NUMERIC)
             status_flags::hash_calculated);
 }
 
-numeric::numeric(long i) : basic(TINFO_NUMERIC)
+numeric::numeric(long i) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
@@ -133,7 +141,7 @@ numeric::numeric(long i) : basic(TINFO_NUMERIC)
             status_flags::hash_calculated);
 }
 
-numeric::numeric(unsigned long i) : basic(TINFO_NUMERIC)
+numeric::numeric(unsigned long i) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
@@ -145,7 +153,7 @@ numeric::numeric(unsigned long i) : basic(TINFO_NUMERIC)
 /** Ctor for rational numerics a/b.
  *
  *  @exception overflow_error (division by zero) */
-numeric::numeric(long numer, long denom) : basic(TINFO_NUMERIC)
+numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT);
     if (!denom)
@@ -157,7 +165,7 @@ numeric::numeric(long numer, long denom) : basic(TINFO_NUMERIC)
             status_flags::hash_calculated);
 }
 
-numeric::numeric(double d) : basic(TINFO_NUMERIC)
+numeric::numeric(double d) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from double",LOGLEVEL_CONSTRUCT);
     // We really want to explicitly use the type cl_LF instead of the
@@ -170,7 +178,7 @@ numeric::numeric(double d) : basic(TINFO_NUMERIC)
             status_flags::hash_calculated);
 }
 
-numeric::numeric(char const *s) : 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);
     if (strchr(s, '.'))
@@ -184,7 +192,7 @@ numeric::numeric(char const *s) : basic(TINFO_NUMERIC)
 
 /** Ctor from CLN types.  This is for the initiated user or internal use
  *  only. */
-numeric::numeric(cl_N const & z) : basic(TINFO_NUMERIC)
+numeric::numeric(cl_N const & z) : basic(TINFO_numeric)
 {
     debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT);
     value = new cl_N(z);
@@ -219,7 +227,7 @@ void numeric::printraw(ostream & os) const
 void numeric::print(ostream & os, unsigned upper_precedence) const
 {
     debugmsg("numeric print", LOGLEVEL_PRINT);
-    if (is_real()) {  
+    if (is_real()) {
         // case 1, real:  x  or  -x
         if ((precedence<=upper_precedence) && (!is_pos_integer())) {
             os << "(" << *value << ")";
@@ -268,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) {
@@ -280,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:
@@ -310,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.
@@ -321,7 +378,7 @@ ex numeric::evalf(int level) const
 
 int numeric::compare_same_type(basic const & other) const
 {
-    ASSERT(is_exactly_of_type(other, numeric));
+    GINAC_ASSERT(is_exactly_of_type(other, numeric));
     numeric const & o = static_cast<numeric &>(const_cast<basic &>(other));
 
     if (*value == *o.value) {
@@ -333,7 +390,7 @@ int numeric::compare_same_type(basic const & other) const
 
 bool numeric::is_equal_same_type(basic const & other) const
 {
-    ASSERT(is_exactly_of_type(other,numeric));
+    GINAC_ASSERT(is_exactly_of_type(other,numeric));
     numeric const *o = static_cast<numeric const *>(&other);
     
     return is_equal(*o);
@@ -383,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));
@@ -398,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
@@ -434,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)))->
@@ -446,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));
@@ -454,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)
@@ -510,23 +549,48 @@ numeric const & numeric::operator=(char const * s)
     return operator=(numeric(s));
 }
 
+/** Return the complex half-plane (left or right) in which the number lies.
+ *  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) */
+int numeric::csgn(void) const
+{
+    if (is_zero())
+        return 0;
+    if (!::zerop(realpart(*value))) {
+        if (::plusp(realpart(*value)))
+            return 1;
+        else
+            return -1;
+    } else {
+        if (::plusp(imagpart(*value)))
+            return 1;
+        else
+            return -1;
+    }
+}
+
 /** This method establishes a canonical order on all numbers.  For complex
  *  numbers this is not possible in a mathematically consistent way but we need
  *  to establish some order and it ought to be fast.  So we simply define it
- *  similar to Maple's csgn. */
+ *  to be compatible with our method csgn.
+ *
+ *  @return csgn(*this-other)
+ *  @see numeric::csgn(void) */
 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));
     }
 }
 
@@ -538,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.
@@ -598,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
@@ -632,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
 }
@@ -649,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
 }
@@ -661,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
 }
@@ -673,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
 }
@@ -684,28 +758,28 @@ bool numeric::operator>=(numeric const & other) const
  *  if the number is really an integer before calling this method. */
 int numeric::to_int(void) const
 {
-    ASSERT(is_integer());
-    return cl_I_to_int(The(cl_I)(*value));
+    GINAC_ASSERT(is_integer());
+    return ::cl_I_to_int(The(cl_I)(*value));  // -> CLN
 }
 
 /** Converts numeric types to machine's double. You should check with is_real()
  *  if the number is really not complex before calling this method. */
 double numeric::to_double(void) const
 {
-    ASSERT(is_real());
-    return cl_double_approx(realpart(*value));
+    GINAC_ASSERT(is_real());
+    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
@@ -723,29 +797,30 @@ inline cl_heap_ratio* TheRatio (const cl_N& obj)
 
 /** Numerator.  Computes the numerator of rational numbers, rationalized
  *  numerator of complex if real and imaginary part are both rational numbers
- *  (i.e numer(4/3+5/6*I) == 8+5*I), the number itself in all other cases. */
+ *  (i.e numer(4/3+5/6*I) == 8+5*I), the number carrying the sign in all other
+ *  cases. */
 numeric numeric::numer(void) const
 {
     if (is_integer()) {
         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
@@ -778,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)) {
@@ -804,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))
@@ -814,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
@@ -825,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;
-    }
 }
 
 
@@ -849,60 +923,14 @@ const numeric some_numeric;
 type_info const & typeid_numeric=typeid(some_numeric);
 /** Imaginary unit.  This is not a constant but a numeric since we are
  *  natively handing complex numbers anyways. */
-const numeric I = (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;
-}
+const numeric I = numeric(complex(cl_I(0),cl_I(1)));
 
 /** Exponential function.
  *
  *  @return  arbitrary precision numerical exp(x). */
 numeric exp(numeric const & x)
 {
-    return exp(*x.value);  // -> CLN
+    return ::exp(*x.value);  // -> CLN
 }
 
 /** Natural logarithm.
@@ -914,7 +942,7 @@ numeric log(numeric const & z)
 {
     if (z.is_zero())
         throw (std::overflow_error("log(): logarithmic singularity"));
-    return log(*z.value);  // -> CLN
+    return ::log(*z.value);  // -> CLN
 }
 
 /** Numeric sine (trigonometric function).
@@ -922,7 +950,7 @@ numeric log(numeric const & z)
  *  @return  arbitrary precision numerical sin(x). */
 numeric sin(numeric const & x)
 {
-    return sin(*x.value);  // -> CLN
+    return ::sin(*x.value);  // -> CLN
 }
 
 /** Numeric cosine (trigonometric function).
@@ -930,7 +958,7 @@ numeric sin(numeric const & x)
  *  @return  arbitrary precision numerical cos(x). */
 numeric cos(numeric const & x)
 {
-    return cos(*x.value);  // -> CLN
+    return ::cos(*x.value);  // -> CLN
 }
     
 /** Numeric tangent (trigonometric function).
@@ -938,7 +966,7 @@ numeric cos(numeric const & x)
  *  @return  arbitrary precision numerical tan(x). */
 numeric tan(numeric const & x)
 {
-    return tan(*x.value);  // -> CLN
+    return ::tan(*x.value);  // -> CLN
 }
     
 /** Numeric inverse sine (trigonometric function).
@@ -946,7 +974,7 @@ numeric tan(numeric const & x)
  *  @return  arbitrary precision numerical asin(x). */
 numeric asin(numeric const & x)
 {
-    return asin(*x.value);  // -> CLN
+    return ::asin(*x.value);  // -> CLN
 }
     
 /** Numeric inverse cosine (trigonometric function).
@@ -954,7 +982,7 @@ numeric asin(numeric const & x)
  *  @return  arbitrary precision numerical acos(x). */
 numeric acos(numeric const & x)
 {
-    return acos(*x.value);  // -> CLN
+    return ::acos(*x.value);  // -> CLN
 }
     
 /** Arcustangents.
@@ -966,9 +994,9 @@ 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
+    return ::atan(*x.value);  // -> CLN
 }
 
 /** Arcustangents.
@@ -979,7 +1007,7 @@ numeric atan(numeric const & x)
 numeric atan(numeric const & y, numeric const & x)
 {
     if (x.is_real() && y.is_real())
-        return atan(realpart(*x.value), realpart(*y.value));  // -> CLN
+        return ::atan(realpart(*x.value), realpart(*y.value));  // -> CLN
     else
         throw (std::invalid_argument("numeric::atan(): complex argument"));        
 }
@@ -989,7 +1017,7 @@ numeric atan(numeric const & y, numeric const & x)
  *  @return  arbitrary precision numerical sinh(x). */
 numeric sinh(numeric const & x)
 {
-    return sinh(*x.value);  // -> CLN
+    return ::sinh(*x.value);  // -> CLN
 }
 
 /** Numeric hyperbolic cosine (trigonometric function).
@@ -997,7 +1025,7 @@ numeric sinh(numeric const & x)
  *  @return  arbitrary precision numerical cosh(x). */
 numeric cosh(numeric const & x)
 {
-    return cosh(*x.value);  // -> CLN
+    return ::cosh(*x.value);  // -> CLN
 }
     
 /** Numeric hyperbolic tangent (trigonometric function).
@@ -1005,7 +1033,7 @@ numeric cosh(numeric const & x)
  *  @return  arbitrary precision numerical tanh(x). */
 numeric tanh(numeric const & x)
 {
-    return tanh(*x.value);  // -> CLN
+    return ::tanh(*x.value);  // -> CLN
 }
     
 /** Numeric inverse hyperbolic sine (trigonometric function).
@@ -1013,7 +1041,7 @@ numeric tanh(numeric const & x)
  *  @return  arbitrary precision numerical asinh(x). */
 numeric asinh(numeric const & x)
 {
-    return asinh(*x.value);  // -> CLN
+    return ::asinh(*x.value);  // -> CLN
 }
 
 /** Numeric inverse hyperbolic cosine (trigonometric function).
@@ -1021,7 +1049,7 @@ numeric asinh(numeric const & x)
  *  @return  arbitrary precision numerical acosh(x). */
 numeric acosh(numeric const & x)
 {
-    return acosh(*x.value);  // -> CLN
+    return ::acosh(*x.value);  // -> CLN
 }
 
 /** Numeric inverse hyperbolic tangent (trigonometric function).
@@ -1029,14 +1057,56 @@ numeric acosh(numeric const & x)
  *  @return  arbitrary precision numerical atanh(x). */
 numeric atanh(numeric const & x)
 {
-    return atanh(*x.value);  // -> CLN
+    return ::atanh(*x.value);  // -> CLN
+}
+
+/** Numeric evaluation of Riemann's Zeta function.  Currently works only for
+ *  integer arguments. */
+numeric zeta(numeric const & 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
+    // 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);
 }
 
 /** The gamma function.
- *  stub stub stub stub stub stub! */
+ *  This is only a stub! */
 numeric gamma(numeric const & x)
 {
-    clog << "gamma(): Nobody expects the Spanish inquisition" << endl;
+    clog << "gamma(" << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
+    return numeric(0);
+}
+
+/** The psi function (aka polygamma function).
+ *  This is only a stub! */
+numeric psi(numeric const & x)
+{
+    clog << "psi(" << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
+    return numeric(0);
+}
+
+/** The psi functions (aka polygamma functions).
+ *  This is only a stub! */
+numeric psi(numeric const & n, numeric const & x)
+{
+    clog << "psi(" << n << "," << x
+         << "): Does anybody know good way to calculate this numerically?"
+         << endl;
     return numeric(0);
 }
 
@@ -1045,11 +1115,9 @@ numeric gamma(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
+    return numeric(::factorial(nn.to_int()));  // -> CLN
 }
 
 /** The double factorial combinatorial function.  (Scarcely used, but still
@@ -1060,6 +1128,10 @@ numeric factorial(numeric const & nn)
  *  @exception range_error (argument must be integer >= -1) */
 numeric doublefactorial(numeric const & 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
@@ -1071,22 +1143,22 @@ numeric doublefactorial(numeric const & nn)
     static vector<numeric> oddresults;
     static int highest_oddresult = -1;
     
-    if ( nn == numeric(-1) ) {
-        return numONE();
+    if (nn == numeric(-1)) {
+        return _num1();
     }
-    if ( !nn.is_nonneg_integer() ) {
+    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 ) {
+    if (nn.is_even()) {
+        int n = nn.div(_num2()).to_int();
+        if (n <= highest_evenresult) {
             return evenresults[n];
         }
-        if ( evenresults.capacity() < (unsigned)(n+1) ) {
+        if (evenresults.capacity() < (unsigned)(n+1)) {
             evenresults.reserve(n+1);
         }
-        if ( highest_evenresult < 0 ) {
-            evenresults.push_back(numONE());
+        if (highest_evenresult < 0) {
+            evenresults.push_back(_num1());
             highest_evenresult=0;
         }
         for (int i=highest_evenresult+1; i<=n; i++) {
@@ -1095,15 +1167,15 @@ numeric doublefactorial(numeric const & nn)
         highest_evenresult=n;
         return evenresults[n];
     } else {
-        int n = nn.sub(numONE()).div(numTWO()).to_int();
-        if ( n <= highest_oddresult ) {
+        int n = nn.sub(_num1()).div(_num2()).to_int();
+        if (n <= highest_oddresult) {
             return oddresults[n];
         }
-        if ( oddresults.capacity() < (unsigned)n ) {
+        if (oddresults.capacity() < (unsigned)n) {
             oddresults.reserve(n+1);
         }
-        if ( highest_oddresult < 0 ) {
-            oddresults.push_back(numONE());
+        if (highest_oddresult < 0) {
+            oddresults.push_back(_num1());
             highest_oddresult=0;
         }
         for (int i=highest_oddresult+1; i<=n; i++) {
@@ -1114,25 +1186,73 @@ numeric doublefactorial(numeric const & nn)
     }
 }
 
-/** The Binomial function. It computes the binomial coefficients. If the
- *  arguments are both nonnegative integers and 0 <= k <= n, then
- *  binomial(n, k) = n!/k!/(n-k)! which is the number of ways of choosing k
- *  objects from n distinct objects. If k > n, then binomial(n,k) returns 0. */
+/** 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)
 {
-    if (n.is_nonneg_integer() && k.is_nonneg_integer()) {
-        return numeric(binomial(n.to_int(),k.to_int()));  // -> CLN
-    } else {
-        // should really be gamma(n+1)/(gamma(r+1)/gamma(n-r+1)
-        return numeric(0);
+    if (n.is_integer() && k.is_integer()) {
+        if (n.is_nonneg_integer()) {
+            if (k.compare(n)!=1 && k.compare(_num0())!=-1)
+                return numeric(::binomial(n.to_int(),k.to_int()));  // -> CLN
+            else
+                return _num0();
+        } else {
+            return _num_1().power(k)*binomial(k-n-_num1(),k);
+        }
     }
-    // return factorial(n).div(factorial(k).mul(factorial(n.sub(k))));
+    
+    // should really be gamma(n+1)/(gamma(r+1)/gamma(n-r+1) or a suitable limit
+    throw (std::range_error("numeric::binomial(): donĀ“t know how to evaluate that."));
+}
+
+/** Bernoulli number.  The nth Bernoulli number is the coefficient of x^n/n!
+ *  in the expansion of the function x/(e^x-1).
+ *
+ *  @return the nth Bernoulli number (a rational number).
+ *  @exception range_error (argument must be integer >= 0) */
+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 _num1();
+    if (!nn.compare(_num1()))
+        return numeric(-1,2);
+    if (nn.is_odd())
+        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
+    // B(nn) == - 1/(nn+1) * sum_{k=0}^{nn-1}(binomial(nn+1,k)*B(k))
+    // whith B(0) == 1.
+    static vector<numeric> results;
+    static int highest_result = -1;
+    int n = nn.sub(_num2()).div(_num2()).to_int();
+    if (n <= highest_result)
+        return results[n];
+    if (results.capacity() < (unsigned)(n+1))
+        results.reserve(n+1);
+    
+    numeric tmp;  // used to store the sum
+    for (int i=highest_result+1; i<=n; ++i) {
+        // the first two elements:
+        tmp = numeric(-2*i-1,2);
+        // accumulate the remaining elements:
+        for (int j=0; j<i; ++j)
+            tmp += binomial(numeric(2*i+3),numeric(j*2+2))*results[j];
+        // divide by -(nn+1) and store result:
+        results.push_back(-tmp/numeric(2*i+3));
+    }
+    highest_result=n;
+    return results[n];
 }
 
 /** Absolute value. */
 numeric abs(numeric const & x)
 {
-    return abs(*x.value);  // -> CLN
+    return ::abs(*x.value);  // -> CLN
 }
 
 /** Modulus (in positive representation).
@@ -1144,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()) {
-        return mod(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
-    }
-    else {
-        return numZERO();  // Throw?
-    }
+    if (a.is_integer() && b.is_integer())
+        return ::mod(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
+    else
+        return _num0();  // Throw?
 }
 
 /** Modulus (in symmetric representation).
@@ -1158,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?
-    }
+        return ::mod(The(cl_I)(*a.value) + b2, The(cl_I)(*b.value)) - b2;
+    } else
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1174,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()) {
-        return rem(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
-    }
-    else {
-        return numZERO();  // Throw?
-    }
+    if (a.is_integer() && b.is_integer())
+        return ::rem(The(cl_I)(*a.value), The(cl_I)(*b.value));  // -> CLN
+    else
+        return _num0();  // Throw?
 }
 
 /** Numeric integer remainder.
@@ -1197,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?
     }
 }
 
@@ -1208,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.
@@ -1228,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?
     }
 }
 
@@ -1243,18 +1358,18 @@ numeric iquo(numeric const & a, numeric const & b, numeric & r)
  *  where imag(z)>0. */
 numeric sqrt(numeric const & z)
 {
-    return sqrt(*z.value);  // -> CLN
+    return ::sqrt(*z.value);  // -> CLN
 }
 
 /** 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.
@@ -1264,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.
@@ -1276,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;
 }
@@ -1342,3 +1457,7 @@ bool _numeric_digits::too_late = false;
 /** Accuracy in decimal digits.  Only object of this type!  Can be set using
  *  assignment from C++ unsigned ints and evaluated like any built-in type. */
 _numeric_digits Digits;
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE