// Copyright (c) 2001-2004 Utrecht University (The Netherlands),
// ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
// INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
// (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
// and Tel-Aviv University (Israel). 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; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// 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.
//
// $Source: /CVSROOT/CGAL/Packages/Number_types/include/CGAL/MP_Float.h,v $
// $Revision: 1.26 $ $Date: 2004/09/30 07:51:51 $
// $Name: $
//
// Author(s) : Sylvain Pion
#ifndef CGAL_MP_FLOAT_H
#define CGAL_MP_FLOAT_H
#include <CGAL/basic.h>
#include <CGAL/Interval_arithmetic.h>
#include <iostream>
#include <vector>
#include <algorithm>
// 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 :
// - The exponent really overflows sometimes -> make it multiprecision.
// - Write a generic wrapper that adds an exponent to be used by MP integers.
// - 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;
MP_Float operator+(const MP_Float &a, const MP_Float &b);
MP_Float operator-(const MP_Float &a, const MP_Float &b);
MP_Float operator*(const MP_Float &a, const MP_Float &b);
MP_Float operator/(const MP_Float &a, const MP_Float &b);
Comparison_result
compare (const MP_Float & a, const MP_Float & b);
class MP_Float
{
public:
typedef Tag_false Has_gcd;
typedef Tag_true Has_division;
typedef Tag_true Has_sqrt;
typedef Tag_true Has_exact_ring_operations;
typedef Tag_false Has_exact_division;
typedef Tag_false Has_exact_sqrt;
typedef short limb;
typedef int limb2;
typedef double exponent_type;
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);
}
// This union is used to convert an unsigned short to a short with
// the same binary representation, without invoking implementation-defined
// behavior (standard 4.7.3).
// It is needed by PGCC, which behaves differently from the others.
union to_signed {
unsigned short us;
short s;
};
public:
// Splits a limb2 into 2 limbs (high and low).
static
void split(limb2 l, limb & high, limb & low)
{
to_signed l2 = {l};
low = l2.s;
high = (l - low) >> (8*sizeof(limb));
}
// Given a limb2, returns the higher limb.
static
limb higher_limb(limb2 l)
{
limb high, low;
split(l, high, low);
return high;
}
void canonicalize()
{
remove_leading_zeros();
remove_trailing_zeros();
}
MP_Float()
: exp(0)
{
CGAL_assertion(sizeof(limb2) == 2*sizeof(limb));
CGAL_assertion(v.empty());
// Creates zero.
}
#if 0
// Causes ambiguities
MP_Float(limb i)
: v(1,i), exp(0)
{
remove_leading_zeros();
}
#endif
MP_Float(limb2 i)
: v(2), exp(0)
{
split(i, v[1], v[0]);
canonicalize();
}
MP_Float(double d);
MP_Float operator-() const
{
return MP_Float() - *this;
}
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; }
exponent_type max_exp() const
{
return v.size() + exp;
}
exponent_type min_exp() const
{
return exp;
}
limb of_exp(exponent_type i) const
{
if (i < exp || i >= max_exp())
return 0;
return v[static_cast<int>(i-exp)];
}
bool is_zero() const
{
return v.empty();
}
Sign sign() const
{
if (v.empty())
return ZERO;
if (v.back()>0)
return POSITIVE;
CGAL_assertion(v.back()<0);
return NEGATIVE;
}
void swap(MP_Float &m)
{
std::swap(v, m.v);
std::swap(exp, m.exp);
}
// Converts to a rational type (e.g. Gmpq).
template < typename T >
T to_rational() const
{
const unsigned log_limb = 8 * sizeof(MP_Float::limb);
if (is_zero())
return 0;
MP_Float::const_iterator i;
exponent_type exp = min_exp() * log_limb;
T res = 0;
for (i = v.begin(); i != v.end(); i++)
{
res += CGAL_CLIB_STD::ldexp(static_cast<double>(*i),
static_cast<int>(exp));
exp += log_limb;
}
return res;
}
V v;
exponent_type exp;
};
inline
void swap(MP_Float &m, MP_Float &n)
{ m.swap(n); }
inline
bool operator<(const MP_Float &a, const MP_Float &b)
{ return CGAL_NTS compare(a, b) == SMALLER; }
inline
bool operator>(const MP_Float &a, const MP_Float &b)
{ return b < a; }
inline
bool operator>=(const MP_Float &a, const MP_Float &b)
{ return ! (a < b); }
inline
bool operator<=(const MP_Float &a, const MP_Float &b)
{ return ! (a > b); }
inline
bool operator==(const MP_Float &a, const MP_Float &b)
{ return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); }
inline
bool operator!=(const MP_Float &a, const MP_Float &b)
{ return ! (a == b); }
inline
Sign
sign (const MP_Float &a)
{
return a.sign();
}
MP_Float
square(const MP_Float&);
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(MP_Float(double d)) == d.
double
to_double(const MP_Float &b);
std::pair<double,double>
to_interval(const MP_Float &b);
template < typename > class Quotient;
// Overloaded in order to protect against overflow.
double
to_double(const Quotient<MP_Float> &b);
std::pair<double, double>
to_interval(const Quotient<MP_Float> &b);
inline
void
simplify_quotient(MP_Float & numerator, MP_Float & denominator)
{
// Currently only simplifies the two exponents.
numerator.exp -= denominator.exp;
denominator.exp = 0;
}
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();
}
std::ostream &
operator<< (std::ostream & os, const MP_Float &b);
// This one is for debug.
std::ostream &
print (std::ostream & os, const MP_Float &b);
std::istream &
operator>> (std::istream & is, MP_Float &b);
CGAL_END_NAMESPACE
#endif // CGAL_MP_FLOAT_H
syntax highlighted by Code2HTML, v. 0.9.1