mirror of https://github.com/CGAL/cgal
398 lines
11 KiB
C++
398 lines
11 KiB
C++
/******************************************************************
|
|
* Core Library Version 1.6, June 2003
|
|
* Copyright (c) 1995-2002 Exact Computation Project
|
|
*
|
|
* File: RealRep.h
|
|
*
|
|
* Synopsis: Internal Representation for Real
|
|
*
|
|
* Written by
|
|
* Koji Ouchi <ouchi@simulation.nyu.edu>
|
|
* Chee Yap <yap@cs.nyu.edu>
|
|
* Chen Li <chenli@cs.nyu.edu>
|
|
* Zilin Du <zilin@cs.nyu.edu>
|
|
* Sylvain Pion <pion@cs.nyu.edu>
|
|
*
|
|
* WWW URL: http://cs.nyu.edu/exact/
|
|
* Email: exact@cs.nyu.edu
|
|
*
|
|
* $Id$
|
|
*****************************************************************/
|
|
|
|
#include <CORE/CoreImpl.h>
|
|
#include <CORE/CoreAux.h>
|
|
#include <CORE/BigFloat.h>
|
|
#include <CORE/MemoryPool.h>
|
|
|
|
#ifndef CORE_REALREP_H
|
|
#define CORE_REALREP_H
|
|
|
|
CORE_BEGIN_NAMESPACE
|
|
template <class T>
|
|
class Realbase_for;
|
|
|
|
typedef Realbase_for<long> RealLong;
|
|
typedef Realbase_for<double> RealDouble;
|
|
typedef Realbase_for<BigInt> RealBigInt;
|
|
typedef Realbase_for<BigRat> RealBigRat;
|
|
typedef Realbase_for<BigFloat> RealBigFloat;
|
|
|
|
// forward reference
|
|
class Real;
|
|
|
|
/// \class RealRep
|
|
/// \brief The internal representation of Real
|
|
class RealRep
|
|
{
|
|
public:
|
|
/// reference counter
|
|
unsigned refCount;
|
|
|
|
/// most Significant Bit
|
|
/** DEFINITION: MSB(0)=-\infty. When E is not 0, and real, we define MSB(E)
|
|
to be the natural number m such that 2^{m} <= |E| < 2^{m+1}. Hence,
|
|
MSB(E) is equal to floor(log_2(|E|)). Intuitively, MSB is the position
|
|
of the most significant bit in a binary rational representation of |E|.
|
|
Thus, the bit before the binary point is considered to be position 0,
|
|
the the bit after the binary point is position -1. Thus,
|
|
... b_2 b_1 b_0.b_{-1} b_{-2} ...
|
|
E.g., MSB(1) = 0,
|
|
MSB(1/2) = MSB((0.1)_2) = -1
|
|
MSB(1/4) = MSB((0.01)_2) = -2.
|
|
MSB(2) = MSB(3) = 1, MSB(4) = 2.
|
|
Hence, if E is a non-zero integer, MSB(E) is equal to bitlength(|E|)-1.
|
|
We also need upper and lower bounds on MSB(E). This is defined to be
|
|
any numbers lMSB(E) and uMSB(E) such that lMSB(E) <= MSB(E) <= uMSB(E).
|
|
THIS implies the following inequality:
|
|
2^{lMSB(E)} <= |E| < 2^{1+uMSB(E)}.
|
|
When E is an interval (e.g., BigFloat with non-zero error), then MSB(E)
|
|
is not defined, but uMSB(E) and lMSB(E) is defined as follows:
|
|
Assume E = [a, b].
|
|
If 0 < a <= b, then lMSB(E) <= MSB(a) <= MSB(b) <= uMSB(E)
|
|
If a <= b < 0, then lMSB(E) <= MSB(b) <= MSB(a) <= uMSB(E)
|
|
If a <= 0 <= b, then lMSB(E) = MSB(0) = -\infty
|
|
uMSB(E) >= max( MSB(a), MSB(b) ) */
|
|
extLong mostSignificantBit;
|
|
|
|
/// \name Constructor and Destructor
|
|
//@{
|
|
/// Constructor
|
|
RealRep() : refCount(1) {}
|
|
/// Destructor
|
|
virtual ~RealRep() {}
|
|
//@}
|
|
|
|
/// \name Cast Operators
|
|
//@{
|
|
virtual operator double() const = 0;
|
|
virtual operator float() const = 0;
|
|
virtual operator long() const = 0;
|
|
virtual operator int() const = 0;
|
|
virtual BigInt BigIntValue() const = 0;
|
|
virtual BigRat BigRatValue() const = 0;
|
|
virtual BigFloat BigFloatValue() const = 0;
|
|
/// convert to \c string
|
|
/** give decimal string representation */
|
|
// Joaquin Grech 31/5/2003
|
|
virtual std::string toString(long prec, bool sci) const = 0;
|
|
|
|
//@}
|
|
|
|
/// \name Approximation
|
|
//@{
|
|
virtual Real approx(const extLong&, const extLong&) const = 0;
|
|
//@}
|
|
|
|
/// \name unary minus
|
|
//@{
|
|
virtual Real operator -() const = 0;
|
|
//@}
|
|
|
|
/// \name addition
|
|
//@{
|
|
virtual Real operator +(const Real&) const = 0;
|
|
virtual Real addLong(const RealLong&) const = 0;
|
|
virtual Real addDouble(const RealDouble&) const = 0;
|
|
virtual Real addBigInt(const RealBigInt&) const = 0;
|
|
virtual Real addBigFloat(const RealBigFloat&) const = 0;
|
|
virtual Real addBigRat(const RealBigRat&) const = 0;
|
|
//@}
|
|
|
|
/// \name subtraction
|
|
//@{
|
|
virtual Real operator -(const Real&) const = 0;
|
|
virtual Real subLong(const RealLong&) const = 0;
|
|
virtual Real subDouble(const RealDouble&) const = 0;
|
|
virtual Real subBigInt(const RealBigInt&) const = 0;
|
|
virtual Real subBigFloat(const RealBigFloat&) const = 0;
|
|
virtual Real subBigRat(const RealBigRat&) const = 0;
|
|
//@}
|
|
|
|
/// \name multiplication
|
|
//@{
|
|
virtual Real operator *(const Real&) const = 0;
|
|
virtual Real mulLong(const RealLong&) const = 0;
|
|
virtual Real mulDouble(const RealDouble&) const = 0;
|
|
virtual Real mulBigInt(const RealBigInt&) const = 0;
|
|
virtual Real mulBigFloat(const RealBigFloat&) const = 0;
|
|
virtual Real mulBigRat(const RealBigRat&) const = 0;
|
|
//@}
|
|
|
|
/// \name division
|
|
//@{
|
|
// virtual Real operator /(const Real&) const;
|
|
virtual Real div(const Real&, const extLong&) const = 0;
|
|
virtual Real divLong(const RealLong&, const extLong&) const = 0;
|
|
virtual Real divDouble(const RealDouble&, const extLong&) const = 0;
|
|
virtual Real divBigInt(const RealBigInt&, const extLong&) const = 0;
|
|
virtual Real divBigFloat(const RealBigFloat&, const extLong&) const = 0;
|
|
virtual Real divBigRat(const RealBigRat&, const extLong&) const = 0;
|
|
//@}
|
|
|
|
/// \name squareroot
|
|
//@{
|
|
virtual Real sqrt(const extLong&) const = 0;
|
|
// sqrt with initial approximation
|
|
virtual Real sqrt(const extLong&, const BigFloat &) const = 0;
|
|
//@}
|
|
|
|
/// \name equality
|
|
//@{
|
|
virtual bool operator ==(const Real&) const = 0;
|
|
virtual bool eqlLong(const RealLong&) const = 0;
|
|
virtual bool eqlDouble(const RealDouble&) const = 0;
|
|
virtual bool eqlBigInt(const RealBigInt&) const = 0;
|
|
virtual bool eqlBigFloat(const RealBigFloat&) const = 0;
|
|
virtual bool eqlBigRat(const RealBigRat&) const = 0;
|
|
//@}
|
|
|
|
/// \name smaller than
|
|
//@{
|
|
virtual bool operator <(const Real&) const = 0;
|
|
virtual bool grtLong(const RealLong&) const = 0;
|
|
virtual bool grtDouble(const RealDouble&) const = 0;
|
|
virtual bool grtBigInt(const RealBigInt&) const = 0;
|
|
virtual bool grtBigFloat(const RealBigFloat&) const = 0;
|
|
virtual bool grtBigRat(const RealBigRat&) const = 0;
|
|
//@}
|
|
|
|
// builtin functions
|
|
//@{
|
|
virtual bool isExact() const = 0;
|
|
virtual void ULV_E(extLong &up, extLong &lp, extLong &v2p, extLong &v2m,
|
|
extLong &v5p, extLong &v5m) const = 0;
|
|
virtual extLong flrLgErr() const = 0;
|
|
virtual extLong clLgErr() const = 0;
|
|
virtual bool isZeroIn() const = 0;
|
|
virtual unsigned long degree() const = 0;
|
|
virtual unsigned long length() const = 0;
|
|
virtual unsigned long height() const = 0;
|
|
virtual int sgn() const = 0;
|
|
//@}
|
|
// I/O Stream
|
|
//@{
|
|
virtual std::ostream& operator <<(std::ostream&) const = 0;
|
|
//@}
|
|
}; //class RealRep
|
|
|
|
|
|
template <class T>
|
|
class Realbase_for : public RealRep
|
|
{
|
|
public:
|
|
CORE_MEMORY(Realbase_for)
|
|
|
|
/// Kernel
|
|
T ker;
|
|
|
|
/// \name Constructor and Destructor
|
|
//@{
|
|
/// Constructor
|
|
Realbase_for(const T&);
|
|
/// Destructor
|
|
~Realbase_for() {}
|
|
//@}
|
|
|
|
/// Access to ker
|
|
const T& get_ker() const { return ker; }
|
|
|
|
/// \name cast operators
|
|
//@{
|
|
operator double() const;
|
|
operator float() const;
|
|
operator long() const;
|
|
operator int() const;
|
|
BigInt BigIntValue() const;
|
|
BigRat BigRatValue() const;
|
|
BigFloat BigFloatValue() const;
|
|
virtual std::string toString(long prec, bool sci) const;
|
|
//@}
|
|
|
|
/// \name approximation
|
|
//@{
|
|
Real approx(const extLong&, const extLong&) const;
|
|
//@}
|
|
|
|
/// \name unary minus
|
|
//@{
|
|
Real operator -() const;
|
|
//@}
|
|
|
|
/// \name addition
|
|
//@{
|
|
Real operator +(const Real&) const;
|
|
Real addLong(const RealLong&) const;
|
|
Real addDouble(const RealDouble&) const;
|
|
Real addBigInt(const RealBigInt&) const;
|
|
Real addBigFloat(const RealBigFloat&) const;
|
|
Real addBigRat(const RealBigRat&) const;
|
|
//@}
|
|
|
|
/// \name subtraction
|
|
//@{
|
|
Real operator -(const Real&) const;
|
|
Real subLong(const RealLong&) const;
|
|
Real subDouble(const RealDouble&) const;
|
|
Real subBigInt(const RealBigInt&) const;
|
|
Real subBigFloat(const RealBigFloat&) const;
|
|
Real subBigRat(const RealBigRat&) const;
|
|
//@}
|
|
|
|
/// \name multiplication
|
|
//@{
|
|
Real operator *(const Real&) const;
|
|
Real mulLong(const RealLong&) const;
|
|
Real mulDouble(const RealDouble&) const;
|
|
Real mulBigInt(const RealBigInt&) const;
|
|
Real mulBigFloat(const RealBigFloat&) const;
|
|
Real mulBigRat(const RealBigRat&) const;
|
|
//@}
|
|
|
|
/// \name division
|
|
//@{
|
|
Real div(const Real&, const extLong&) const;
|
|
Real divLong(const RealLong&, const extLong&) const;
|
|
Real divDouble(const RealDouble&, const extLong&) const;
|
|
Real divBigInt(const RealBigInt&, const extLong&) const;
|
|
Real divBigFloat(const RealBigFloat&, const extLong&) const;
|
|
Real divBigRat(const RealBigRat&, const extLong&) const;
|
|
//@}
|
|
|
|
/// \name squareroot
|
|
//@{
|
|
Real sqrt(const extLong&) const;
|
|
Real sqrt(const extLong&, const BigFloat&) const;
|
|
//@}
|
|
|
|
/// \name equality
|
|
//@{
|
|
bool operator ==(const Real&) const;
|
|
bool eqlLong(const RealLong&) const;
|
|
bool eqlDouble(const RealDouble&) const;
|
|
bool eqlBigInt(const RealBigInt&) const;
|
|
bool eqlBigFloat(const RealBigFloat&) const;
|
|
bool eqlBigRat(const RealBigRat&) const;
|
|
//@}
|
|
|
|
/// \name smaller-than
|
|
//@{
|
|
bool operator <(const Real&) const;
|
|
bool grtLong(const RealLong&) const;
|
|
bool grtDouble(const RealDouble&) const;
|
|
bool grtBigInt(const RealBigInt&) const;
|
|
bool grtBigFloat(const RealBigFloat&) const;
|
|
bool grtBigRat(const RealBigRat&) const;
|
|
//@}
|
|
|
|
/// \name builtin functions
|
|
//@{
|
|
bool isExact() const;
|
|
void ULV_E(extLong &up, extLong &lp, extLong &v2p, extLong &v2m,
|
|
extLong &v5p, extLong &v5m) const;
|
|
extLong flrLgErr() const;
|
|
extLong clLgErr() const;
|
|
bool isZeroIn() const;
|
|
unsigned long degree() const;
|
|
unsigned long length() const;
|
|
unsigned long height() const;
|
|
int sgn() const;
|
|
//@}
|
|
|
|
/// \name I/O stream
|
|
//@{
|
|
std::ostream& operator <<(std::ostream& o) const
|
|
{
|
|
o << ker;
|
|
return o;
|
|
};
|
|
//@}
|
|
};
|
|
|
|
// The constructors of Realbase_for<> are specialized.
|
|
template <>
|
|
inline
|
|
Realbase_for<long>::Realbase_for(const long &l)
|
|
: ker(l)
|
|
{
|
|
mostSignificantBit = ((ker != 0) ? extLong(flrLg(ker)) : CORE_negInfty);
|
|
// This computes the bit length of "ker" minus 1,
|
|
// i.e., floor(log_2(|ker|)) .
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
Realbase_for<double>::Realbase_for(const double& d)
|
|
: ker(d)
|
|
{
|
|
mostSignificantBit = BigFloat(ker).MSB();
|
|
}
|
|
|
|
template <>
|
|
inline Realbase_for<BigInt>::Realbase_for(const BigInt& I)
|
|
: ker(I)
|
|
{
|
|
mostSignificantBit = (sign(ker)? extLong(floorLg(ker)) : CORE_negInfty);
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
Realbase_for<BigFloat>::Realbase_for(const BigFloat& B)
|
|
: ker(B)
|
|
{
|
|
mostSignificantBit = ker.MSB();
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
Realbase_for<BigRat>::Realbase_for(const BigRat& R)
|
|
: ker(R)
|
|
{
|
|
// MSB of a rational x/y is given by floorLg(|x/y|)
|
|
BigInt x = ker.numerator();
|
|
BigInt y = ker.denominator();
|
|
if (ker.sign()) {
|
|
mostSignificantBit = extLong(floorLg(x) - floorLg(y));
|
|
x.abs();
|
|
if ((y << mostSignificantBit.asLong()) > x)
|
|
mostSignificantBit = mostSignificantBit - 1;
|
|
} else
|
|
mostSignificantBit = CORE_negInfty;
|
|
/*
|
|
mostSignificantBit = ker.sign() ? \
|
|
extLong(floorLg(x) - floorLg(y)) : CORE_negInfty;
|
|
|
|
// This gives us an approximation to msb that could off by 1 in
|
|
// one direction. So we next adjust for this possibility:
|
|
// The exact value of msb(x/y) is given by
|
|
// y.2^msb <= x < y.2^{msb+1}.
|
|
|
|
// 5/16/02: fixed a bug in logic (Pion/Zilin/Chee)
|
|
x.abs();
|
|
if ((y << mostSignificantBit.asLong()) > x)
|
|
mostSignificantBit = mostSignificantBit - 1;
|
|
*/
|
|
}
|
|
|
|
CORE_END_NAMESPACE
|
|
#endif
|