dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/CORE/BigFloatRep.h

455 lines
13 KiB
C
Raw Normal View History

/****************************************************************************
* Core Library Version 1.7, August 2004
* Copyright (c) 1995-2004 Exact Computation Project
* All rights reserved.
*
* This file is part of CGAL (www.cgal.org);
* You can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*
* File: BigFloatRep.h
* Synopsis:
* Internal Representation BigFloat.
*
* 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
*
* $URL$
* $Id$
* SPDX-License-Identifier: LGPL-3.0+
***************************************************************************/
#ifndef _CORE_BIGFLOATREP_H_
#define _CORE_BIGFLOATREP_H_
#include <CGAL/CORE/BigRat.h>
#include <CGAL/CORE/CoreAux.h>
#include <CGAL/CORE/CoreDefs.h>
#include <CGAL/CORE/extLong.h>
namespace CORE {
// forward reference
class BigFloat;
// class BigFloatRep (internal representation for BigFloat)
class CGAL_CORE_EXPORT BigFloatRep : public RCRepImpl<BigFloatRep> {
public:
static long chunkCeil(long bits); //inline
static long chunkFloor(long bits); //inline
static long bits(long chunks); //inline
static BigInt chunkShift(const BigInt& x, long s); //inline
static double lg10(BigInt x); //inline
static long floorlg10(BigInt x); //inline
/// exp2(e) returns 2^e : called by BigFloat::exp2(e)
/** e can be negative */
static BigFloatRep* exp2(int e);
struct DecimalOutput;
friend class BigFloat;
BigInt m;
unsigned long err;
long exp;
public:
// constructors
BigFloatRep(int=0); //inline
BigFloatRep(unsigned int); //inline
BigFloatRep(short); //inline
BigFloatRep(float); //inline
BigFloatRep(long); //inline
BigFloatRep(double); //inline
BigFloatRep(const BigInt& I, unsigned long u, long l); //inline
BigFloatRep(const BigInt& I, long l); //inline
BigFloatRep(const BigInt& I); //inline
BigFloatRep(const char *); //inline
BigRat BigRatize() const; //inline
// the destructor
~BigFloatRep(); //inline
CORE_NEW(BigFloatRep) // allocate the memory pool, unless
CORE_DELETE(BigFloatRep) // memory pool feature is disabled.
// approximation
void trunc(const BigInt&, const extLong&, const extLong&);
void truncM(const BigFloatRep&, const extLong&, const extLong&);
void approx(const BigFloatRep&, const extLong&, const extLong&);
void div(const BigInt&, const BigInt&, const extLong&, const extLong&);
void approx(const BigRat&, const extLong&, const extLong&); //inline
// error-normalization
void eliminateTrailingZeroes(); //inline
void normal();
void bigNormal(BigInt&);
// arithmetics
public:
void add(const BigFloatRep&, const BigFloatRep&);
void sub(const BigFloatRep&, const BigFloatRep&);
void mul(const BigFloatRep&, const BigFloatRep&);
void div(const BigFloatRep&, const BigFloatRep&, const extLong&);
void div2(const BigFloatRep&); ///< exact division by 2
/// Converts a pair of BigFloatReps into one with error bounds
void centerize(const BigFloatRep&, const BigFloatRep&);
private:
// squareroot
// arguments: r = value whose square root we want
// a = absolute precision of the desired result
// init = initial approx. to the square root (for Newton)
void sqrt(const BigInt& r, const extLong& a);
/// sqrt(r,a,rr) -- compute sqrt(r) to absolute precision a,
/// starting from initial approximation of rr.
void sqrt(const BigInt& r, const extLong& a, const BigFloat& init);
void sqrt(const BigFloatRep& r, const extLong& a);
/// sqrt(r,a,rr) -- compute sqrt(r) to absolute precision a,
/// starting from initial approximation of rr.
void sqrt(const BigFloatRep& r, const extLong& a, const BigFloat& init);
// comparison
int compareMExp(const BigFloatRep&) const;
// builtin functions
extLong lMSB() const; //inline
extLong uMSB() const; //inline
extLong MSB() const; //inline
extLong flrLgErr() const; //inline
extLong clLgErr() const; //inline
bool isZeroIn() const; //inline
int signM() const; //inline
// cast functions
double toDouble() const;
long toLong() const;
BigInt toBigInt() const;
// conversion
// toString() Joaquin Grech 31/5/2003
std::string toString(long prec=get_static_defBigFloatOutputDigits(), bool sci=false) const;
std::string round(std::string inRep, long& L10, unsigned int width) const;
DecimalOutput toDecimal(unsigned int width=get_static_defBigFloatOutputDigits(),
bool Scientific=false) const;
void fromString(const char *p, extLong prec = getBigFloatInputDigits());
void dump() const; //inline
long adjustE(long E, BigInt M, long e) const;
public:
// stream operators
std::ostream& operator <<(std::ostream&) const; //inline
std::istream& operator >>(std::istream&);
};//class BigFloatRep
////////////////////////////////////////////////////////////
// Implementations
////////////////////////////////////////////////////////////
struct BigFloatRep::DecimalOutput {
std::string rep; // decimal output string
int sign; // 0, +1 or -1
bool isScientific; // false=positional notation
int noSignificant; // number of significant digits
// -1 means this information is not explicitly
// given, and must be determined from rep, etc.
bool isExact; //
int errorCode; // 0 = no error
// 1 = sign of number is unknown (e.g., mantissa
// is smaller than error)
DecimalOutput() : rep(""), sign(1), isScientific(false),
noSignificant(0), isExact(false), errorCode(0) {}
};//DecimalOutput
// constants used by BigFloatRep
// NOTES: CHUNK_BIT is the number of bits in each Chunk
// Since LONG_BIT = 32 or 64, then CHUNK_BIT = 14 or 30.
// We have: 0 <= err < 4 * 2^{CHUNK_BIT}
const long CHUNK_BIT = (long)(LONG_BIT / 2 - 2); // chunks
const long HALF_CHUNK_BIT = (CHUNK_BIT + 1) / 2;
const long DBL_MAX_CHUNK = (DBL_MAX_EXP - 1) / CHUNK_BIT + 1;
const double lgTenM = 3.321928094887362;
inline long BigFloatRep::chunkCeil(long bits) {
if (bits > 0)
return (bits - 1) / CHUNK_BIT + 1;
else
return - (- bits) / CHUNK_BIT;
}//chunkCeil
inline long BigFloatRep::chunkFloor(long bits) {
if (bits >= 0)
return bits / CHUNK_BIT;
else
return - (- bits - 1) / CHUNK_BIT - 1;
}//chunkFloor
// bits(c) returns the number of bits in c chunks:
inline long BigFloatRep::bits(long chunks) {
return CHUNK_BIT * chunks;
}
inline BigInt BigFloatRep::chunkShift(const BigInt& x, long s) {
if (!s || sign(x) == 0)
return x;
else if (s > 0)
// shift left
if (sign(x) > 0)
return x << static_cast<unsigned long>(bits(s));
else // x < 0
return - ((-x) << static_cast<unsigned long>(bits(s)));
else // shift right
if (sign(x) > 0)
return x >> static_cast<unsigned long>(bits(-s));
else // x < 0
return - ((-x) >> static_cast<unsigned long>(bits(-s)));
}//chunkShift
inline BigFloatRep* BigFloatRep::exp2(int e) {
long ee; // this is going to be the exponent
if (e >= 0)
ee = e/CHUNK_BIT;
else
ee = - ((-e + CHUNK_BIT -1)/CHUNK_BIT);
int rem = e - (ee * CHUNK_BIT); // Assert: 0 <= rem < CHUNK_BIT
return new BigFloatRep((1<<rem), 0, ee);
// Here, we assume CHUNK_BIT is less than int width
}
// constructors
inline BigFloatRep::BigFloatRep(short n)
: m(n), err(0), exp(0) {}
inline BigFloatRep::BigFloatRep(float n)
: m(n), err(0), exp(0) {}
// Chee (8/8/04) -- introduced constructor from int
inline BigFloatRep::BigFloatRep(int n)
: m(n), err(0), exp(0) {}
inline BigFloatRep::BigFloatRep(unsigned int n)
: m(n), err(0), exp(0) {}
// Chee (8/8/04) -- introduced constructor from long
inline BigFloatRep::BigFloatRep(long n)
: m(n), err(0), exp(0) {}
// Chee (8/8/04) -- introduced constructor from double
/* This turns out to be an alternative implementation of the
* original one in BigFloat.cpp!!
inline BigFloatRep::BigFloatRep(double d)
: m(IntMantissa(d)), err(0), exp(0) {
BigFloatRep * bfr = exp2(IntExponent(d)); // take care of the exponent
m *= bfr->m;
exp = bfr->exp;
}
*/
inline BigFloatRep::BigFloatRep(const BigInt& I, unsigned long er, long ex)
: m(I), err(er), exp(ex) {}
inline BigFloatRep::BigFloatRep(const BigInt& I)
: m(I), err(0), exp(0) {}
//Constructs the BigFloat representing I*2^{ex}.
//If ex >=0 then it is clear how to do it.
//Otherwise, let |ex| = CHUNK_BIT * q + r. Then
//I*2^{ex} = I*2^{CHUNK_BIT -r} 2^{-CHUNK_BIT * (q+1)}
inline BigFloatRep::BigFloatRep(const BigInt& I, long ex) {
err=0;
exp = chunkFloor(ex);
if(ex >= 0)
m = I<<(ex - bits(exp));
else{//ex < 0
exp = chunkFloor(abs(ex));
m = I << (CHUNK_BIT - (-ex - bits(exp)));
exp = -1*(1 + exp);
}
}
inline BigFloatRep::BigFloatRep(const char *str) : m(0), err(0), exp(0) {
fromString(str);
}
inline BigRat BigFloatRep::BigRatize() const {
if (exp >= 0)
return BigRat(chunkShift(m, exp), 1);
else
return BigRat(m, chunkShift(1, - exp));
}
// the destructor
inline BigFloatRep::~BigFloatRep() {}
inline void BigFloatRep::approx(const BigRat& R, const extLong& r, const extLong& a) {
div(numerator(R), denominator(R), r, a);
}
// eliminate trailing zeroes
inline void BigFloatRep::eliminateTrailingZeroes() {
// eliminate trailing 0's -- IP 10/9/98
/*if (err == 0 && m != 0) {
while ((m & ((1 << CHUNK_BIT) - 1)) == 0) {
m >>= CHUNK_BIT;
exp++;
}
}*/
// new code, much faster, Zilin Du (Nov, 2003)
if (err == 0 && sign(m) != 0) {
int r = getBinExpo(m) / CHUNK_BIT;
m >>= (r * CHUNK_BIT);
exp += r;
}
}
// bultin functions
inline extLong BigFloatRep::lMSB() const {
if (!isZeroIn())
return extLong(floorLg(abs(m) - err)) + bits(exp);
else
return extLong(CORE_negInfty);
}
/// uMSB() returns an upper bound on log_2(abs(*this)).
/** Returns -1 if (*this)=0.
* Not well-defined if zero is in the interval.
*/
inline extLong BigFloatRep::uMSB() const {
return extLong(floorLg(abs(m) + err)) + bits(exp);
}
inline extLong BigFloatRep::MSB() const {
// Note : MSB is undefined if it's not exact.
if (sign(m)) // sign(m) is non-zero
return extLong(floorLg(m)) + bits(exp);
else
return extLong(CORE_negInfty);
}
inline extLong BigFloatRep::flrLgErr() const {
if (err)
return extLong(flrLg(err)) + bits(exp);
else
return extLong(CORE_negInfty);
}
inline extLong BigFloatRep::clLgErr() const {
if (err)
return extLong(clLg(err)) + bits(exp);
else
return extLong(CORE_negInfty);
}
// isZero() = true iff zero is inside the interval of BigFloat:
inline bool BigFloatRep::isZeroIn() const {
if (err == 0){
return (m == 0); //Nov 6, 2002: bug fix!
}
long lm = bitLength(m);
if (lm > CHUNK_BIT+2) {
return false; // since err < 4 * 2^{CHUNK_BIT}
} else {
return (abs(m) <= BigInt(err));
}
}
inline int BigFloatRep::signM() const {
return sign(m);
}
inline double BigFloatRep::lg10(BigInt x) {
if (x == 0)
return 0;
BigInt t(abs(x));
long l = -1;
double d = 0;
while (t > 0) {
l++;
d /= 10;
d += ulongValue(t%10);
t /= 10;
}
return std::log10(d) + l;
}
// this is a simpler form of lg10()
inline long BigFloatRep::floorlg10(BigInt x) {
if (x == 0)
return 0;
BigInt t(abs(x));
long l = -1;
while (t > 0) {
l++;
t /= 10;
}
return l;
}
inline std::ostream& BigFloatRep::operator<<(std::ostream& o) const {
bool sci = (o.flags() & std::ios::scientific) > 0;
BigFloatRep::DecimalOutput r = toDecimal(o.precision(), sci);
if (r.sign == -1)
o << "-";
o << r.rep;
return o;
}
/* Returns a std::string with precision and format specified
Works as cout << with the exception that if the output
contains any error it returns a NULL
Joaquin Grech 31/5/03
*/
inline std::string BigFloatRep::toString(long prec, bool sci) const {
BigFloatRep::DecimalOutput r = toDecimal(prec, sci);
if (r.errorCode == 0) {
if (r.sign < 0)
return std::string("-")+r.rep;
else
return r.rep;
}
return NULL;
}
inline void BigFloatRep::dump() const {
std::cout << "---- BFRep: " << this << " ----" << std::endl;
std::cout << " BF value: ";
this->operator<<(std::cout);
std::cout << std::endl;
std::cout << " m = " << m << std::endl;
std::cout << " err = " << err << std::endl;
std::cout << " exp = " << exp << std::endl;
std::cout << " -- End of BFRep " << this << " -- " << std::endl;
}
} //namespace CORE
#endif // _CORE_BIGFLOATREP_H_