mirror of https://github.com/CGAL/cgal
308 lines
5.6 KiB
C++
308 lines
5.6 KiB
C++
// ============================================================================
|
|
//
|
|
// Copyright (c) 2001 The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// release :
|
|
// release_date :
|
|
//
|
|
// file : include/CGAL/MP_Float.h
|
|
// revision : $Revision$
|
|
// revision_date : $Date$
|
|
// package : Interval Arithmetic
|
|
// author(s) : Sylvain Pion
|
|
// coordinator : INRIA Sophia-Antipolis (<Mariette.Yvinec@sophia.inria.fr>)
|
|
//
|
|
// ============================================================================
|
|
|
|
#ifndef CGAL_MP_FLOAT_H
|
|
#define CGAL_MP_FLOAT_H
|
|
|
|
#include <CGAL/basic.h>
|
|
#include <CGAL/Interval_arithmetic.h>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <cmath>
|
|
|
|
// MP_Float : multiprecision scaled integers.
|
|
|
|
// Some invariants on the internal representation :
|
|
// - zero is represented by an empty vector, and whatever exp.
|
|
// - no leading or trailing zero in the vector => unique
|
|
|
|
// The main algorithms are :
|
|
// - Addition/Subtraction
|
|
// - Multiplication
|
|
// - Comparison
|
|
// - to_double() / to_interval()
|
|
// - Construction from a double.
|
|
// - IOs
|
|
|
|
// TODO :
|
|
// - Documentation.
|
|
// - Karatsuba (or other) ? Would be fun to implement at least.
|
|
// - Division, sqrt... : different options :
|
|
// - nothing
|
|
// - convert to double, take approximation, compute over double, reconstruct
|
|
// - exact division as separate function (for Bareiss...)
|
|
// - returns the quotient of the division, forgetting the rest.
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
class MP_Float;
|
|
|
|
namespace NTS {
|
|
Comparison_result
|
|
compare (const MP_Float & a, const MP_Float & b);
|
|
}
|
|
|
|
class MP_Float
|
|
{
|
|
public:
|
|
|
|
typedef short limb;
|
|
typedef int limb2;
|
|
|
|
#if defined _MSC_VER && _MSC_VER <= 1200
|
|
static const unsigned log_limb;
|
|
static const limb2 base;
|
|
static const unsigned limbs_per_double;
|
|
#else
|
|
static const unsigned log_limb = 8 * sizeof(limb);
|
|
static const limb2 base = 1 << log_limb;
|
|
static const unsigned limbs_per_double = 2 + 53/log_limb;
|
|
#endif
|
|
|
|
static const double trunc_max, trunc_min;
|
|
|
|
typedef std::vector<limb> V;
|
|
typedef V::const_iterator const_iterator;
|
|
typedef V::iterator iterator;
|
|
|
|
private:
|
|
|
|
void remove_leading_zeros()
|
|
{
|
|
while (!v.empty() && v.back() == 0)
|
|
v.pop_back();
|
|
}
|
|
|
|
void remove_trailing_zeros()
|
|
{
|
|
if (v.empty() || v.front() != 0)
|
|
return;
|
|
|
|
iterator i = v.begin();
|
|
for (i++; *i == 0; i++)
|
|
;
|
|
exp += i-v.begin();
|
|
v.erase(v.begin(), i);
|
|
}
|
|
|
|
public:
|
|
|
|
void canonicalize()
|
|
{
|
|
remove_leading_zeros();
|
|
remove_trailing_zeros();
|
|
}
|
|
|
|
// Accessory function : Given a limb2, this returns the higher limb.
|
|
// The lower limb is simply obtained by casting to a limb.
|
|
static
|
|
limb higher_limb(limb2 l)
|
|
{
|
|
return (l - (limb) l) >> log_limb;
|
|
}
|
|
|
|
MP_Float()
|
|
{
|
|
CGAL_assertion(sizeof(limb2) == 2*sizeof(limb));
|
|
CGAL_assertion(v.empty());
|
|
// Creates zero.
|
|
}
|
|
|
|
MP_Float(limb i)
|
|
: v(1,i), exp(0)
|
|
{
|
|
remove_leading_zeros();
|
|
}
|
|
|
|
MP_Float(limb2 i)
|
|
: v(2), exp(0)
|
|
{
|
|
v[0] = i;
|
|
v[1] = higher_limb(i);
|
|
canonicalize();
|
|
}
|
|
|
|
MP_Float(double d);
|
|
|
|
MP_Float operator-() const
|
|
{
|
|
return MP_Float() - *this;
|
|
}
|
|
|
|
MP_Float operator+(const MP_Float &) const;
|
|
MP_Float operator-(const MP_Float &) const;
|
|
MP_Float operator*(const MP_Float &) const;
|
|
MP_Float operator/(const MP_Float &) const;
|
|
|
|
MP_Float& operator+=(const MP_Float &a)
|
|
{
|
|
return *this = *this + a;
|
|
}
|
|
|
|
MP_Float& operator-=(const MP_Float &a)
|
|
{
|
|
return *this = *this - a;
|
|
}
|
|
|
|
MP_Float& operator*=(const MP_Float &a)
|
|
{
|
|
return *this = *this * a;
|
|
}
|
|
|
|
MP_Float& operator/=(const MP_Float &a)
|
|
{
|
|
return *this = *this / a;
|
|
}
|
|
|
|
bool operator<(const MP_Float &b) const
|
|
{
|
|
return CGAL_NTS compare(*this, b) == SMALLER;
|
|
}
|
|
|
|
bool operator>(const MP_Float &f) const
|
|
{
|
|
return f<*this;
|
|
}
|
|
|
|
bool operator>=(const MP_Float &f) const
|
|
{
|
|
return !(*this<f);
|
|
}
|
|
|
|
bool operator<=(const MP_Float &f) const
|
|
{
|
|
return !(*this>f);
|
|
}
|
|
|
|
bool operator==(const MP_Float &b) const
|
|
{
|
|
return (v == b.v) && ((exp == b.exp) || v.empty());
|
|
}
|
|
|
|
bool operator!=(const MP_Float &b) const
|
|
{
|
|
return ! (*this == b);
|
|
}
|
|
|
|
int max_exp() const
|
|
{
|
|
return v.size() + exp;
|
|
}
|
|
|
|
int min_exp() const
|
|
{
|
|
return exp;
|
|
}
|
|
|
|
limb of_exp(int i) const
|
|
{
|
|
if (i < exp || i >= max_exp())
|
|
return 0;
|
|
return v[i-exp];
|
|
}
|
|
|
|
bool is_zero() const
|
|
{
|
|
return v.empty();
|
|
}
|
|
|
|
bool is_one() const
|
|
{
|
|
return v.size() == 1 && v.back() == 1;
|
|
}
|
|
|
|
Sign sign() const
|
|
{
|
|
if (v.empty())
|
|
return ZERO;
|
|
if (v.back()>0)
|
|
return POSITIVE;
|
|
CGAL_assertion(v.back()<0);
|
|
return NEGATIVE;
|
|
}
|
|
|
|
V v;
|
|
int exp;
|
|
};
|
|
|
|
|
|
namespace NTS {
|
|
|
|
inline
|
|
Sign
|
|
sign (const MP_Float &a)
|
|
{
|
|
return a.sign();
|
|
}
|
|
|
|
} // namespace NTS
|
|
|
|
MP_Float
|
|
sqrt(const MP_Float &d);
|
|
|
|
// to_double() returns, not the closest double, but a one bit error is allowed.
|
|
// We guarantee : to_double(MPI(double d)) == d.
|
|
double
|
|
to_double(const MP_Float &b);
|
|
|
|
Interval_base
|
|
to_interval(const MP_Float &b);
|
|
|
|
inline
|
|
bool
|
|
is_finite(const MP_Float &)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
inline
|
|
bool
|
|
is_valid(const MP_Float &)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
inline
|
|
io_Operator
|
|
io_tag(const MP_Float &)
|
|
{
|
|
return io_Operator();
|
|
}
|
|
|
|
inline
|
|
Number_tag
|
|
number_type_tag(const MP_Float &)
|
|
{
|
|
return Number_tag();
|
|
}
|
|
|
|
std::ostream &
|
|
operator<< (std::ostream & os, const MP_Float &b);
|
|
|
|
std::istream &
|
|
operator>> (std::istream & is, MP_Float &b);
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif // CGAL_MP_FLOAT_H
|