mirror of https://github.com/CGAL/cgal
318 lines
10 KiB
C++
318 lines
10 KiB
C++
/******************************************************************
|
|
* Core Library Version 1.6, June 2003
|
|
* Copyright (c) 1995-2003 Exact Computation Project
|
|
*
|
|
* File: BigFloat.h
|
|
*
|
|
* Synopsis: An implementation of BigFloat numbers with error bounds.
|
|
*
|
|
* Written by
|
|
* Chee Yap <yap@cs.nyu.edu>
|
|
* Chen Li <chenli@cs.nyu.edu>
|
|
* Zilin Du <zilin@cs.nyu.edu>
|
|
*
|
|
* WWW URL: http://cs.nyu.edu/exact/
|
|
* Email: exact@cs.nyu.edu
|
|
*
|
|
* $Id$
|
|
*****************************************************************/
|
|
|
|
#ifndef CORE_BIGFLOAT_H
|
|
#define CORE_BIGFLOAT_H
|
|
|
|
#include <CORE/BigFloatRep.h>
|
|
|
|
CORE_BEGIN_NAMESPACE
|
|
|
|
/// \class BigFloat BigFloat.h
|
|
/// \brief BigFloat is a class of Float-Point number with error bounds.
|
|
class BigFloat
|
|
{
|
|
public:
|
|
BigFloatRep* rep; ///< handle to the "real" representation
|
|
|
|
/// \name Constructors and Destructor
|
|
//@{
|
|
/// default constructor
|
|
BigFloat() { rep = new BigFloatRep(); rep->refCount++; }
|
|
/// copy constructor
|
|
BigFloat(const BigFloat& x) { rep = x.rep; rep->refCount++; }
|
|
|
|
/// constructor for <tt>int</tt>
|
|
BigFloat(int i) { rep = new BigFloatRep(i); rep->refCount++; }
|
|
/// constructor for <tt>long</tt>
|
|
BigFloat(long l) { rep = new BigFloatRep(l); rep->refCount++; }
|
|
|
|
/// constructor for <tt>double</tt>
|
|
BigFloat(double d) { rep = new BigFloatRep(d); rep->refCount++; }
|
|
|
|
/// constructor for <tt>const char* </tt>(default base = 10)
|
|
BigFloat(const char *s) { rep = new BigFloatRep(s); rep->refCount++; }
|
|
/// constructor for <tt>std::string</tt>(default base = 10)
|
|
BigFloat(const std::string& s)
|
|
{ rep = new BigFloatRep(s.c_str()); rep->refCount++; }
|
|
|
|
/// constructor for <tt>BigInt</tt>
|
|
BigFloat(const BigInt& I, unsigned long u = 0, long l = 0)
|
|
{ rep = new BigFloatRep(I, u, l); rep->refCount++; }
|
|
/// constructor for <tt>BigRat</tt>
|
|
BigFloat(const BigRat& R, const extLong& r = defRelPrec,
|
|
const extLong& a = defAbsPrec)
|
|
{ rep = new BigFloatRep(); rep->refCount++; rep->approx(R, r, a); }
|
|
|
|
/// constructor for <tt>BigFloatRep</tt>
|
|
BigFloat(BigFloatRep * r) { this->rep = r; rep->refCount++; }
|
|
|
|
/// destructor
|
|
~BigFloat() { if (--rep->refCount == 0) delete rep; }
|
|
//@}
|
|
|
|
/// \name Assignment Operator
|
|
//@{
|
|
/// assignment operator
|
|
BigFloat& operator= (const BigFloat& x) {
|
|
if (this == &x) return *this;
|
|
if (--rep->refCount == 0) delete rep;
|
|
rep = x.rep; rep->refCount++;
|
|
return *this;
|
|
}
|
|
//@}
|
|
|
|
/// \name Compound Assignment Operators
|
|
//@{
|
|
/// operator+=
|
|
BigFloat& operator+= (const BigFloat& x) {
|
|
BigFloat z; z.rep->add(*rep, *x.rep);
|
|
if (--rep->refCount == 0) delete rep;
|
|
rep = z.rep; rep->refCount++;
|
|
return *this;
|
|
}
|
|
/// operator-=
|
|
BigFloat& operator-= (const BigFloat& x) {
|
|
BigFloat z; z.rep->sub(*rep, *x.rep);
|
|
if (--rep->refCount == 0) delete rep;
|
|
rep = z.rep; rep->refCount++;
|
|
return *this;
|
|
}
|
|
/// operator*=
|
|
BigFloat& operator*= (const BigFloat& x) {
|
|
BigFloat z; z.rep->mul(*rep, *x.rep);
|
|
if (--rep->refCount == 0) delete rep;
|
|
rep = z.rep; rep->refCount++;
|
|
return *this;
|
|
}
|
|
/// operator/=
|
|
BigFloat& operator/= (const BigFloat& x) {
|
|
BigFloat z; z.rep->div(*rep, *x.rep, defBFdivRelPrec);
|
|
if (--rep->refCount == 0) delete rep;
|
|
rep = z.rep; rep->refCount++;
|
|
return *this;
|
|
}
|
|
//@}
|
|
|
|
/// \name Unary Minus Operator
|
|
//@{
|
|
/// unary minus
|
|
BigFloat operator- () const { return BigFloat(-rep->m, rep->err, rep->exp); }
|
|
//@}
|
|
|
|
/// \name String Conversion Functions
|
|
//@{
|
|
/// set value from <tt>const char*</tt> (base = 10)
|
|
void fromString(const char* s, const extLong& p=defBigFloatInputDigits)
|
|
{ rep->fromString(s, p); }
|
|
/// convert to <tt>std::string</tt> (base = 10)
|
|
std::string toString(long prec=defBigFloatOutputDigits, bool sci=false) const
|
|
{ return rep->toString(prec, sci); }
|
|
//@}
|
|
|
|
/// \name Conversion Functions
|
|
//@{
|
|
/// return int value
|
|
int intValue() const { return (int)rep->toLong(); }
|
|
/// return long value
|
|
long longValue() const {
|
|
long l = rep->toLong();
|
|
if ((l == LONG_MAX) || (l == LONG_MIN))
|
|
return l; // return the overflown value.
|
|
if ((sign() < 0) && (cmp(BigFloat(l)) != 0)) {
|
|
// a negative value not exactly rounded.
|
|
l--; // rounded to floor.
|
|
}
|
|
return l;
|
|
}
|
|
/// return float value
|
|
float floatValue() const { return (float)rep->toDouble(); }
|
|
/// return double value
|
|
double doubleValue() const { return rep->toDouble(); }
|
|
/// return BigInt value
|
|
BigInt BigIntValue() const { return rep->toBigInt(); }
|
|
/// return BigRat value
|
|
BigRat BigRatValue() const { return rep->BigRatize(); }
|
|
//@}
|
|
|
|
/// \name File I/O Functions
|
|
//@{
|
|
/// read from file
|
|
void readFromFile(std::istream& in, long maxLength = 0);
|
|
/// write to file
|
|
void writeToFile(std::ostream& in, int base=10, int charsPerLine=80) const;
|
|
//@}
|
|
|
|
/// \name Helper Functions
|
|
//@{
|
|
/// sign function
|
|
/** \note This is only the sign of the mantissa, it can be taken to be
|
|
the sign of the BigFloat only if !(isZeroIn()). */
|
|
int sign() const { return rep->signM(); }
|
|
/// check whether contains zero
|
|
/** \return true if contains zero, otherwise false */
|
|
bool isZeroIn() const { return rep->isZeroIn(); }
|
|
/// absolute value function
|
|
BigFloat abs() const
|
|
{ return (sign()>=0) ? BigFloat(*this):BigFloat(-rep->m,rep->err,rep->exp);}
|
|
/// comparison function
|
|
int cmp(const BigFloat& x) const { return rep->compareMExp(*x.rep); }
|
|
|
|
/// get mantissa
|
|
const BigInt& m() const { return rep->m; }
|
|
/// get error bits
|
|
unsigned long err() const { return rep->err; }
|
|
/// get exponent
|
|
long exp() const { return rep->exp; }
|
|
/// return rep
|
|
BigFloatRep* getRep() const { return rep; }
|
|
|
|
/// check whether err == 0
|
|
/** \return true if err == 0, otherwise false */
|
|
bool isExact() const { return rep->err == 0; }
|
|
/// set err to 0
|
|
/** \return an exact BigFloat, see Tutorial for why this is useful! */
|
|
BigFloat& makeExact() { rep->err =0; return *this;}
|
|
/// set err to 1
|
|
/** \return an inexact BigFloat, see Tutorial for why this is useful! */
|
|
BigFloat& makeInexact() { rep->err =1; return *this;}
|
|
|
|
/// return lower bound of Most Significant Bit
|
|
extLong lMSB() const { return rep->lMSB(); }
|
|
/// return upper bound of Most Significant Bit
|
|
extLong uMSB() const { return rep->uMSB(); }
|
|
/// return Most Significant Bit
|
|
extLong MSB() const { return rep->MSB(); }
|
|
|
|
/// floor of Lg(err)
|
|
extLong flrLgErr() const { return rep->flrLgErr(); }
|
|
/// ceil of Lg(err)
|
|
extLong clLgErr() const { return rep->clLgErr(); }
|
|
|
|
/// division with relative precsion <tt>r</tt>
|
|
BigFloat div(const BigFloat& x, const extLong& r) const
|
|
{ BigFloat y; y.rep->div(*rep, *x.rep, r); return y; }
|
|
/// exact division by 2
|
|
BigFloat div2() const
|
|
{ BigFloat y; y.rep->div2(*rep); return y; }
|
|
|
|
/// squareroot
|
|
BigFloat sqrt(const extLong& a) const
|
|
{ BigFloat x; x.rep->sqrt(*rep, a); return x; }
|
|
/// squareroot with initial approximation <tt>init</tt>
|
|
BigFloat sqrt(const extLong& a, const BigFloat& init) const
|
|
{ BigFloat x; x.rep->sqrt(*rep, a, init); return x; }
|
|
//@}
|
|
|
|
/// \name Utility Functions
|
|
//@{
|
|
/// approximate BigInt number
|
|
void approx(const BigInt& I, const extLong& r, const extLong& a) {
|
|
if ((rep->refCount) > 1) {// *rep is shared
|
|
--rep->refCount;
|
|
rep = new BigFloatRep();
|
|
rep->refCount++;
|
|
}
|
|
rep->trunc(I, r, a);
|
|
}
|
|
/// approximate BigFloat number
|
|
void approx(const BigFloat& B, const extLong& r, const extLong& a) {
|
|
if ((rep->refCount) > 1) {// *rep is shared
|
|
--rep->refCount;
|
|
rep = new BigFloatRep();
|
|
rep->refCount++;
|
|
}
|
|
rep->approx(*B.rep, r, a);
|
|
}
|
|
/// approximate BigRat number
|
|
void approx(const BigRat& R, const extLong& r, const extLong& a) {
|
|
if ((rep->refCount) > 1) {// *rep is shared
|
|
--rep->refCount;
|
|
rep = new BigFloatRep();
|
|
rep->refCount++;
|
|
}
|
|
rep->approx(R, r, a);
|
|
}
|
|
/// dump internal data
|
|
void dump() const { rep->dump(); }
|
|
//@}
|
|
|
|
/// returns a BigFloat of value \f$ 2^e \f$
|
|
static BigFloat exp2(int e) { return BigFloat(BigFloatRep::exp2(e)); }
|
|
};
|
|
|
|
/// IO stream operator<<
|
|
inline std::ostream& operator<< (std::ostream& o, const BigFloat& x)
|
|
{ x.rep->operator<<(o); return o; }
|
|
/// IO stream operator>>
|
|
inline std::istream& operator>> (std::istream& i, BigFloat& x)
|
|
{ x.rep->operator>>(i); return i; }
|
|
|
|
/// operator+
|
|
inline BigFloat operator+ (const BigFloat& x, const BigFloat& y)
|
|
{ BigFloat z; z.rep->add(*x.rep, *y.rep); return z; }
|
|
/// operator-
|
|
inline BigFloat operator- (const BigFloat& x, const BigFloat& y)
|
|
{ BigFloat z; z.rep->sub(*x.rep, *y.rep); return z; }
|
|
/// operator*
|
|
inline BigFloat operator* (const BigFloat& x, const BigFloat& y)
|
|
{ BigFloat z; z.rep->mul(*x.rep, *y.rep); return z; }
|
|
/// operator/
|
|
inline BigFloat operator/ (const BigFloat& x, const BigFloat& y)
|
|
{ BigFloat z; z.rep->div(*x.rep, *y.rep, defBFdivRelPrec); return z; }
|
|
|
|
/// operator==
|
|
inline bool operator== (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) == 0; }
|
|
/// operator!=
|
|
inline bool operator!= (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) != 0; }
|
|
/// operator>=
|
|
inline bool operator>= (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) >= 0; }
|
|
/// operator>
|
|
inline bool operator> (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) > 0; }
|
|
/// operator<=
|
|
inline bool operator<= (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) <= 0; }
|
|
/// operator<
|
|
inline bool operator< (const BigFloat& x, const BigFloat& y)
|
|
{ return x.cmp(y) < 0; }
|
|
|
|
/// sign
|
|
inline int sign(const BigFloat& x) { return x.sign(); }
|
|
/// abs
|
|
inline BigFloat abs(const BigFloat& x) { return x.abs(); }
|
|
/// cmp
|
|
inline int cmp(const BigFloat& x, const BigFloat& y) { return x.cmp(y); }
|
|
/// pow
|
|
BigFloat pow(const BigFloat&, unsigned long);
|
|
/// power
|
|
inline BigFloat power(const BigFloat& x, unsigned long p) { return pow(x, p); }
|
|
/// sqrt to defAbsPrec:
|
|
inline BigFloat sqrt(const BigFloat& x) { return x.sqrt(defBFsqrtAbsPrec); }
|
|
|
|
/// convert an BigFloat Interval to a BigFloat with error bits
|
|
inline BigFloat centerize(const BigFloat& a, const BigFloat& b)
|
|
{ BigFloat z; z.rep->centerize(*a.rep, *b.rep); return z;}
|
|
|
|
CORE_END_NAMESPACE
|
|
#endif // CORE_BIGFLOATT_H
|