// 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 #include #include #include #include // 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 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(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(*i), static_cast(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 to_interval(const MP_Float &b); template < typename > class Quotient; // Overloaded in order to protect against overflow. double to_double(const Quotient &b); std::pair to_interval(const Quotient &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