Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76656 - in sandbox/gtl: boost/polygon boost/polygon/detail libs/polygon/test libs/polygon/voronoi_example
From: sydorchuk.andriy_at_[hidden]
Date: 2012-01-23 17:22:46


Author: asydorchuk
Date: 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
New Revision: 76656
URL: http://svn.boost.org/trac/boost/changeset/76656

Log:
Added voronoi_ctypes (coordinate types).
Added voronoi_ctype_traits.
Removed output type specification from template arguments of the voronoi_builder class.
Added:
   sandbox/gtl/boost/polygon/detail/voronoi_ctypes.hpp (contents, props changed)
Text files modified:
   sandbox/gtl/boost/polygon/detail/voronoi_predicates.hpp | 129 +-
   sandbox/gtl/boost/polygon/detail/voronoi_robust_fpt.hpp | 1510 ++++++++++-----------------------------
   sandbox/gtl/boost/polygon/detail/voronoi_structures.hpp | 6
   sandbox/gtl/boost/polygon/voronoi.hpp | 21
   sandbox/gtl/boost/polygon/voronoi_builder.hpp | 87 +-
   sandbox/gtl/boost/polygon/voronoi_diagram.hpp | 21
   sandbox/gtl/libs/polygon/test/voronoi_benchmark_test.cpp | 9
   sandbox/gtl/libs/polygon/voronoi_example/voronoi_visualizer.cpp | 5
   8 files changed, 542 insertions(+), 1246 deletions(-)

Added: sandbox/gtl/boost/polygon/detail/voronoi_ctypes.hpp
==============================================================================
--- (empty file)
+++ sandbox/gtl/boost/polygon/detail/voronoi_ctypes.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -0,0 +1,744 @@
+// Boost.Polygon library detail/voronoi_ctypes.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_VORONOI_DETAIL_CTYPES
+#define BOOST_POLYGON_VORONOI_DETAIL_CTYPES
+
+#include <cmath>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace polygon {
+namespace detail {
+
+typedef boost::int32_t int32;
+typedef boost::int64_t int64;
+typedef boost::uint32_t uint32;
+typedef boost::uint64_t uint64;
+typedef double fpt64;
+
+// If two floating-point numbers in the same format are ordered (x < y),
+// then they are ordered the same way when their bits are reinterpreted as
+// sign-magnitude integers. Values are considered to be almost equal if
+// their integer reinterpretations differ in not more than maxUlps units.
+template <typename _fpt>
+struct ulp_comparison;
+
+template <>
+struct ulp_comparison<fpt64> {
+ enum kResult {
+ LESS = -1,
+ EQUAL = 0,
+ MORE = 1
+ };
+
+ kResult operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const {
+ uint64 ll_a, ll_b;
+
+ // Reinterpret double bits as 64-bit signed integer.
+ memcpy(&ll_a, &a, sizeof(fpt64));
+ memcpy(&ll_b, &b, sizeof(fpt64));
+
+ // Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000.
+ // Map negative zero to an integer zero representation - making it
+ // identical to positive zero - the smallest negative number is
+ // represented by negative one, and downwards from there.
+ if (ll_a < 0x8000000000000000ULL)
+ ll_a = 0x8000000000000000ULL - ll_a;
+ if (ll_b < 0x8000000000000000ULL)
+ ll_b = 0x8000000000000000ULL - ll_b;
+
+ // Compare 64-bit signed integer representations of input values.
+ // Difference in 1 Ulp is equivalent to a relative error of between
+ // 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
+ if (ll_a > ll_b)
+ return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS;
+ return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE;
+ }
+};
+
+// Manages exponent of the floating-point value.
+template <typename _fpt>
+struct fpt_exponent_accessor;
+
+template <>
+class fpt_exponent_accessor<fpt64> {
+public:
+ static const int64 kExponentMask;
+ static const int64 kSignedMantissaMask;
+ static const int64 kMinExponent;
+ static const int64 kMaxExponent;
+ static const int64 kMaxSignificantExpDif;
+
+ static int64 set_exponent(fpt64& value, int64 exponent) {
+ int64 bits;
+ memcpy(&bits, &value, sizeof(fpt64));
+ int64 exp = ((bits & kExponentMask) >> 52) - 1023;
+ if (exp == exponent) {
+ return exp;
+ }
+ bits = (bits & kSignedMantissaMask) | ((exponent + 1023) << 52);
+ memcpy(&value, &bits, sizeof(fpt64));
+ return exp;
+ }
+};
+
+const int64 fpt_exponent_accessor<fpt64>::kExponentMask = 0x7ff0000000000000LL;
+const int64 fpt_exponent_accessor<fpt64>::kSignedMantissaMask = 0x800fffffffffffffLL;
+const int64 fpt_exponent_accessor<fpt64>::kMinExponent = -1023LL;
+const int64 fpt_exponent_accessor<fpt64>::kMaxExponent = 1024LL;
+const int64 fpt_exponent_accessor<fpt64>::kMaxSignificantExpDif = 54;
+
+// Allows to extend floating-point type exponent boundaries to the 64 bit
+// integer range. This class does not handle division by zero, subnormal
+// numbers or NaNs.
+template <typename _fpt>
+class extended_exponent_fpt {
+public:
+ typedef _fpt fpt_type;
+ typedef int64 exp_type;
+ typedef fpt_exponent_accessor<fpt_type> fea;
+
+ explicit extended_exponent_fpt(fpt_type value) {
+ if (value == 0.0) {
+ exponent_ = 0;
+ value_ = 0.0;
+ } else {
+ exponent_ = fea::set_exponent(value, 0);
+ value_ = value;
+ }
+ }
+
+ extended_exponent_fpt(fpt_type value, exp_type exponent) {
+ if (value == 0.0) {
+ exponent_ = 0;
+ value_ = 0.0;
+ } else {
+ exponent_ = fea::set_exponent(value, 0) + exponent;
+ value_ = value;
+ }
+ }
+
+ bool is_pos() const {
+ return value_ > 0;
+ }
+
+ bool is_neg() const {
+ return value_ < 0;
+ }
+
+ bool is_zero() const {
+ return value_ == 0;
+ }
+
+ extended_exponent_fpt operator-() const {
+ return extended_exponent_fpt(-value_, exponent_);
+ }
+
+ extended_exponent_fpt operator+(const extended_exponent_fpt& that) const {
+ if (this->value_ == 0.0 ||
+ that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
+ return that;
+ }
+ if (that.value_ == 0.0 ||
+ this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
+ return *this;
+ }
+ if (this->exponent_ >= that.exponent_) {
+ exp_type exp_dif = this->exponent_ - that.exponent_;
+ fpt_type value = this->value_;
+ fea::set_exponent(value, exp_dif);
+ value += that.value_;
+ return extended_exponent_fpt(value, that.exponent_);
+ } else {
+ exp_type exp_dif = that.exponent_ - this->exponent_;
+ fpt_type value = that.value_;
+ fea::set_exponent(value, exp_dif);
+ value += this->value_;
+ return extended_exponent_fpt(value, this->exponent_);
+ }
+ }
+
+ extended_exponent_fpt operator-(const extended_exponent_fpt& that) const {
+ if (this->value_ == 0.0 ||
+ that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
+ return extended_exponent_fpt(-that.value_, that.exponent_);
+ }
+ if (that.value_ == 0.0 ||
+ this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
+ return *this;
+ }
+ if (this->exponent_ >= that.exponent_) {
+ exp_type exp_dif = this->exponent_ - that.exponent_;
+ fpt_type value = this->value_;
+ fea::set_exponent(value, exp_dif);
+ value -= that.value_;
+ return extended_exponent_fpt(value, that.exponent_);
+ } else {
+ exp_type exp_dif = that.exponent_ - this->exponent_;
+ fpt_type value = -that.value_;
+ fea::set_exponent(value, exp_dif);
+ value += this->value_;
+ return extended_exponent_fpt(value, this->exponent_);
+ }
+ }
+
+ extended_exponent_fpt operator*(const extended_exponent_fpt& that) const {
+ fpt_type value = this->value_ * that.value_;
+ exp_type exponent = this->exponent_ + that.exponent_;
+ return extended_exponent_fpt(value, exponent);
+ }
+
+ extended_exponent_fpt operator/(const extended_exponent_fpt& that) const {
+ fpt_type value = this->value_ / that.value_;
+ exp_type exponent = this->exponent_ - that.exponent_;
+ return extended_exponent_fpt(value, exponent);
+ }
+
+ extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) {
+ return *this = *this + that;
+ }
+
+ extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) {
+ return *this = *this - that;
+ }
+
+ extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) {
+ return *this = *this * that;
+ }
+
+ extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) {
+ return *this = *this / that;
+ }
+
+ extended_exponent_fpt sqrt() const {
+ fpt_type val = value_;
+ exp_type exp = exponent_;
+ if (exp & 1) {
+ val *= 2.0;
+ --exp;
+ }
+ return extended_exponent_fpt(get_sqrt(val), exp >> 1);
+ }
+
+ fpt_type d() const {
+ fpt_type ret_val = value_;
+ exp_type exp = exponent_;
+ if (ret_val == 0.0) {
+ return ret_val;
+ }
+ if (exp >= fea::kMaxExponent) {
+ ret_val = 1.0;
+ exp = fea::kMaxExponent;
+ } else if (exp <= fea::kMinExponent) {
+ ret_val = 1.0;
+ exp = fea::kMinExponent;
+ }
+ fea::set_exponent(ret_val, exp);
+ return ret_val;
+ }
+
+private:
+ fpt_type value_;
+ exp_type exponent_;
+};
+typedef extended_exponent_fpt<double> efpt64;
+
+template <typename _fpt>
+extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) {
+ return that.sqrt();
+}
+
+template <typename _fpt>
+bool is_pos(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_pos();
+}
+
+template <typename _fpt>
+bool is_neg(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_neg();
+}
+
+template <typename _fpt>
+bool is_zero(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_zero();
+}
+
+template<size_t N>
+class extended_int {
+public:
+ static const uint64 kUInt64LowMask;
+ static const uint64 kUInt64HighMask;
+
+ extended_int() {}
+
+ extended_int(int32 that) {
+ if (that > 0) {
+ this->chunks_[0] = that;
+ this->count_ = 1;
+ } else if (that < 0) {
+ this->chunks_[0] = -that;
+ this->count_ = -1;
+ } else {
+ this->chunks_[0] = this->count_ = 0;
+ }
+ }
+
+ extended_int(int64 that) {
+ if (that > 0) {
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ uint32 high = (that & kUInt64HighMask) >> 32;
+ if (high) {
+ this->chunks_[1] = high;
+ this->count_ = 2;
+ } else {
+ this->count_ = 1;
+ }
+ } else if (that < 0) {
+ that = -that;
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ uint32 high = (that & kUInt64HighMask) >> 32;
+ if (high) {
+ this->chunks_[1] = high;
+ this->count_ = -2;
+ } else {
+ this->count_ = -1;
+ }
+ } else {
+ this->chunks_[0] = this->count_ = 0;
+ }
+ }
+
+ extended_int(const std::vector<uint32>& chunks, bool plus = true) {
+ this->count_ = static_cast<int32>(chunks.size());
+ for (size_t i = 0; i < chunks.size(); ++i) {
+ this->chunks_[i] = chunks[chunks.size() - i - 1];
+ }
+ if (!plus) {
+ this->count_ = -this->count_;
+ }
+ }
+
+ template <size_t M>
+ extended_int(const extended_int<M>& that) {
+ this->count_ = that.count();
+ memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
+ }
+
+ extended_int<N>& operator=(int32 that) {
+ if (that > 0) {
+ this->chunks_[0] = that;
+ this->count_ = 1;
+ } else if (that < 0) {
+ this->chunks_[0] = -that;
+ this->count_ = -1;
+ } else {
+ this->chunks_[0] = this->count_ = 0;
+ }
+ return *this;
+ }
+
+ extended_int<N>& operator=(int64 that) {
+ if (that > 0) {
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ uint32 high = (that & kUInt64HighMask) >> 32;
+ if (high) {
+ this->chunks_[1] = high;
+ this->count_ = 2;
+ } else {
+ this->count_ = 1;
+ }
+ } else if (that < 0) {
+ that = -that;
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ uint32 high = (that & kUInt64HighMask) >> 32;
+ if (high) {
+ this->chunks_[1] = high;
+ this->count_ = -2;
+ } else {
+ this->count_ = -1;
+ }
+ } else {
+ this->chunks_[0] = this->count_ = 0;
+ }
+ return *this;
+ }
+
+ template <size_t M>
+ extended_int<N>& operator=(const extended_int<M>& that) {
+ this->count_ = that.count();
+ size_t sz = (std::min)(N, that.size());
+ memcpy(this->chunks_, that.chunks(), sz * sizeof(uint32));
+ return *this;
+ }
+
+ bool is_pos() const {
+ return this->count_ > 0;
+ }
+
+ bool is_neg() const {
+ return this->count_ < 0;
+ }
+
+ bool is_zero() const {
+ return this->count_ == 0;
+ }
+
+ template <size_t M>
+ bool operator==(const extended_int<M>& that) const {
+ if (this->count_ != that.count()) {
+ return false;
+ }
+ for (size_t i = 0; i < this->size(); ++i) {
+ if (this->chunks_[i] != that.chunks()[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template <size_t M>
+ bool operator!=(const extended_int<M>& that) const {
+ return !(*this == that);
+ }
+
+ template <size_t M>
+ bool operator<(const extended_int<M>& that) const {
+ if (this->count_ != that.count()) {
+ return this->count_ < that.count();
+ }
+ size_t i = this->size();
+ if (!i) {
+ return false;
+ }
+ do {
+ --i;
+ if (this->chunks_[i] != that.chunks()[i]) {
+ return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0);
+ }
+ } while (i);
+ return false;
+ }
+
+ template <size_t M>
+ bool operator>(const extended_int<M>& that) const {
+ return that < *this;
+ }
+
+ template <size_t M>
+ bool operator<=(const extended_int<M>& that) const {
+ return !(that < *this);
+ }
+
+ template <size_t M>
+ bool operator>=(const extended_int<M>& that) const {
+ return !(*this < that);
+ }
+
+ extended_int<N> operator-() const {
+ extended_int<N> ret_val = *this;
+ ret_val.neg();
+ return ret_val;
+ }
+
+ void neg() {
+ this->count_ = -this->count_;
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator+(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.add(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void add(const extended_int<N1>& e1, const extended_int<N2>& e2) {
+ if (!e1.count()) {
+ *this = e2;
+ return;
+ }
+ if (!e2.count()) {
+ *this = e1;
+ return;
+ }
+ if ((e1.count() > 0) ^ (e2.count() > 0)) {
+ dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ } else {
+ add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ }
+ if (e1.count() < 0) {
+ this->count_ = -this->count_;
+ }
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator-(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.dif(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void dif(const extended_int<N1>& e1, const extended_int<N2> &e2) {
+ if (!e1.count()) {
+ *this = e2;
+ this->count_ = -this->count_;
+ return;
+ }
+ if (!e2.count()) {
+ *this = e1;
+ return;
+ }
+ if ((e1.count() > 0) ^ (e2.count() > 0)) {
+ add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ } else {
+ dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ }
+ if (e1.count() < 0) {
+ this->count_ = -this->count_;
+ }
+ }
+
+ extended_int<N> operator*(int32 that) const {
+ extended_int<N> temp(that);
+ return (*this) * temp;
+ }
+
+ extended_int<N> operator*(int64 that) const {
+ extended_int<N> temp(that);
+ return (*this) * temp;
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator*(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.mul(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void mul(const extended_int<N1>& e1, const extended_int<N2>& e2) {
+ if (!e1.count() || !e2.count()) {
+ this->chunks_[0] = this->count_ = 0;
+ return;
+ }
+ mul(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ if ((e1.count() > 0) ^ (e2.count() > 0)) {
+ this->count_ = -this->count_;
+ }
+ }
+
+ const uint32* chunks() const {
+ return chunks_;
+ }
+
+ int32 count() const {
+ return count_;
+ }
+
+ size_t size() const {
+ return (std::abs)(count_);
+ }
+
+ std::pair<fpt64, int64> p() const {
+ std::pair<fpt64, int64> ret_val(0, 0);
+ size_t sz = this->size();
+ if (!sz) {
+ return ret_val;
+ } else {
+ if (sz == 1) {
+ ret_val.first = static_cast<fpt64>(this->chunks_[0]);
+ ret_val.second = 0;
+ } else if (sz == 2) {
+ ret_val.first = static_cast<fpt64>(this->chunks_[1]) *
+ static_cast<fpt64>(0x100000000LL) +
+ static_cast<fpt64>(this->chunks_[0]);
+ ret_val.second = 0;
+ } else {
+ for (size_t i = 1; i <= 3; ++i) {
+ ret_val.first *= static_cast<fpt64>(0x100000000LL);
+ ret_val.first += static_cast<fpt64>(this->chunks_[sz - i]);
+ }
+ ret_val.second = (sz - 3) << 5;
+ }
+ }
+ if (this->count_ < 0) {
+ ret_val.first = -ret_val.first;
+ }
+ return ret_val;
+ }
+
+ fpt64 d() const {
+ std::pair<fpt64, int64> p = this->p();
+ extended_exponent_fpt<fpt64> efpt(p.first, p.second);
+ return efpt.d();
+ }
+
+private:
+ void add(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
+ if (sz1 < sz2) {
+ add(c2, sz2, c1, sz1);
+ return;
+ }
+ this->count_ = sz1;
+ uint64 temp = 0;
+ for (size_t i = 0; i < sz2; ++i) {
+ temp += static_cast<uint64>(c1[i]) +
+ static_cast<uint64>(c2[i]);
+ this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
+ temp = (temp & kUInt64HighMask) >> 32;
+ }
+ for (size_t i = sz2; i < sz1; ++i) {
+ temp += static_cast<uint64>(c1[i]);
+ this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
+ temp = (temp & kUInt64HighMask) >> 32;
+ }
+ if (temp && (this->count_ != N)) {
+ this->chunks_[this->count_] = static_cast<uint32>(temp & kUInt64LowMask);
+ ++this->count_;
+ }
+ }
+
+ void dif(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2, bool rec = false) {
+ if (sz1 < sz2) {
+ dif(c2, sz2, c1, sz1, true);
+ this->count_ = -this->count_;
+ return;
+ } else if ((sz1 == sz2) && !rec) {
+ do {
+ --sz1;
+ if (c1[sz1] < c2[sz1]) {
+ ++sz1;
+ dif(c2, sz1, c1, sz1, true);
+ this->count_ = -this->count_;
+ return;
+ } else if (c1[sz1] > c2[sz1]) {
+ ++sz1;
+ break;
+ } else if (!sz1) {
+ this->chunks_[0] = this->count_ = 0;
+ return;
+ }
+ } while (sz1);
+ sz2 = sz1;
+ }
+ this->count_ = sz1-1;
+ bool flag = false;
+ for (size_t i = 0; i < sz2; ++i) {
+ this->chunks_[i] = c1[i] - c2[i] - (flag?1:0);
+ flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag);
+ }
+ for (size_t i = sz2; i < sz1; ++i) {
+ this->chunks_[i] = c1[i] - (flag?1:0);
+ flag = !c1[i] && flag;
+ }
+ if (this->chunks_[this->count_]) {
+ ++this->count_;
+ }
+ }
+
+ void mul(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
+ uint64 cur = 0, nxt, tmp;
+ this->count_ = static_cast<int32>((std::min)(N, sz1 + sz2 - 1));
+ for (size_t shift = 0; shift < static_cast<size_t>(this->count_); ++shift) {
+ nxt = 0;
+ for (size_t first = 0; first <= shift; ++first) {
+ if (first >= sz1) {
+ break;
+ }
+ size_t second = shift - first;
+ if (second >= sz2) {
+ continue;
+ }
+ tmp = static_cast<uint64>(c1[first]) *
+ static_cast<uint64>(c2[second]);
+ cur += tmp & kUInt64LowMask;
+ nxt += (tmp & kUInt64HighMask) >> 32;
+ }
+ this->chunks_[shift] = static_cast<uint32>(cur & kUInt64LowMask);
+ cur = nxt + ((cur & kUInt64HighMask) >> 32);
+ }
+ if (cur && (this->count_ != N)) {
+ this->chunks_[this->count_] = static_cast<uint32>(cur & kUInt64LowMask);
+ ++this->count_;
+ }
+ }
+
+ uint32 chunks_[N];
+ int32 count_;
+};
+
+template <size_t N>
+const uint64 extended_int<N>::kUInt64LowMask = 0x00000000ffffffffULL;
+template <size_t N>
+const uint64 extended_int<N>::kUInt64HighMask = 0xffffffff00000000ULL;
+
+template <size_t N>
+bool is_pos(const extended_int<N>& that) {
+ return that.count() > 0;
+}
+
+template <size_t N>
+bool is_neg(const extended_int<N>& that) {
+ return that.count() < 0;
+}
+
+template <size_t N>
+bool is_zero(const extended_int<N>& that) {
+ return !that.count();
+}
+
+struct type_converter_fpt {
+ template <typename T>
+ fpt64 operator()(const T& that) const {
+ return static_cast<fpt64>(that);
+ }
+
+ template <size_t N>
+ fpt64 operator()(const extended_int<N>& that) const {
+ return that.d();
+ }
+
+ template <>
+ fpt64 operator()< extended_exponent_fpt<fpt64> >(const extended_exponent_fpt<fpt64>& that) const {
+ return that.d();
+ }
+};
+
+struct type_converter_efpt {
+ template <size_t N>
+ extended_exponent_fpt<fpt64> operator()(const extended_int<N>& that) const {
+ std::pair<fpt64, int64> p = that.p();
+ return extended_exponent_fpt<fpt64>(p.first, p.second);
+ }
+};
+
+template <typename T>
+struct voronoi_ctype_traits;
+
+template <>
+struct voronoi_ctype_traits<int32> {
+ typedef int32 int_type;
+ typedef uint32 uint_type;
+ typedef int64 int_x2_type;
+ typedef uint64 uint_x2_type;
+ typedef extended_int<128> big_int_type;
+ typedef fpt64 fpt_type;
+ typedef extended_exponent_fpt<fpt_type> efpt_type;
+ typedef ulp_comparison<fpt_type> ulp_cmp_type;
+ typedef type_converter_fpt to_fpt_converter_type;
+ typedef type_converter_efpt to_efpt_converter_type;
+};
+
+} // detail
+} // polygon
+} // boost
+
+#endif
\ No newline at end of file

Modified: sandbox/gtl/boost/polygon/detail/voronoi_predicates.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/detail/voronoi_predicates.hpp (original)
+++ sandbox/gtl/boost/polygon/detail/voronoi_predicates.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,14 +1,14 @@
 // Boost.Polygon library detail/voronoi_predicates.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
 // See http://www.boost.org for updates, documentation, and revision history.
 
-#ifndef BOOST_POLYGON_VORONOI_CALC_UTILS
-#define BOOST_POLYGON_VORONOI_CALC_UTILS
+#ifndef BOOST_POLYGON_VORONOI_DETAIL_PREDICATES
+#define BOOST_POLYGON_VORONOI_DETAIL_PREDICATES
 
 #include "voronoi_robust_fpt.hpp"
 
@@ -16,24 +16,21 @@
 namespace polygon {
 namespace detail {
 
-template <typename T>
-class voronoi_predicates;
-
 // Predicate utilities. Operates with the coordinate types that could
 // be converted to the 32-bit signed integer without precision loss.
-template <>
-class voronoi_predicates<int32> {
+template <typename CTYPE_TRAITS>
+class voronoi_predicates {
 public:
- typedef int32 int_type;
- typedef uint32 uint_type;
- typedef int64 int_x2_type;
- typedef uint64 uint_x2_type;
- typedef eint4096 int_x128_type;
- typedef fpt64 fpt_type;
- typedef efpt64 efpt_type;
- typedef ulp_comparison<fpt_type> ulp_cmp_type;
- typedef type_converter_fpt to_fpt_converter;
- typedef type_converter_efpt to_efpt_converter;
+ typedef typename CTYPE_TRAITS::int_type int_type;
+ typedef typename CTYPE_TRAITS::uint_type uint_type;
+ typedef typename CTYPE_TRAITS::int_x2_type int_x2_type;
+ typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type;
+ typedef typename CTYPE_TRAITS::big_int_type big_int_type;
+ typedef typename CTYPE_TRAITS::fpt_type fpt_type;
+ typedef typename CTYPE_TRAITS::efpt_type efpt_type;
+ typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type;
+ typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter;
+ typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter;
 
     static const unsigned int ULPS;
     static const unsigned int ULPSx2;
@@ -529,7 +526,7 @@
         typedef typename Site::point_type point_type;
         typedef Site site_type;
         typedef Circle circle_type;
- typedef robust_sqrt_expr<int_x128_type, efpt_type, to_efpt_converter> robust_sqrt_expr_type;
+ typedef robust_sqrt_expr<big_int_type, efpt_type, to_efpt_converter> robust_sqrt_expr_type;
 
         void ppp(const site_type &site1,
                  const site_type &site2,
@@ -538,7 +535,7 @@
                  bool recompute_c_x = true,
                  bool recompute_c_y = true,
                  bool recompute_lower_x = true) {
- int_x128_type dif_x[3], dif_y[3], sum_x[2], sum_y[2];
+ big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2];
             dif_x[0] = static_cast<int_x2_type>(site1.x()) -
                        static_cast<int_x2_type>(site2.x());
             dif_x[1] = static_cast<int_x2_type>(site2.x()) -
@@ -560,16 +557,16 @@
             sum_y[1] = static_cast<int_x2_type>(site2.y()) +
                        static_cast<int_x2_type>(site3.y());
             fpt_type inv_denom = to_fpt(0.5) / to_fpt(dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0]);
- int_x128_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0];
- int_x128_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1];
+ big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0];
+ big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1];
 
             if (recompute_c_x || recompute_lower_x) {
- int_x128_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0];
+ big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0];
                 circle.x(to_fpt(c_x) * inv_denom);
 
                 if (recompute_lower_x) {
                     // Evaluate radius of the circle.
- int_x128_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) *
+ big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) *
                                           (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) *
                                           (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]);
                     fpt_type r = get_sqrt(to_fpt(sqr_r));
@@ -584,7 +581,7 @@
                             circle.lower_x(circle.x() - r * inv_denom);
                         }
                     } else {
- int_x128_type numer = c_x * c_x - sqr_r;
+ big_int_type numer = c_x * c_x - sqr_r;
                         fpt_type lower_x = to_fpt(numer) * inv_denom /
                                            (to_fpt(c_x) + r);
                         circle.lower_x(lower_x);
@@ -593,7 +590,7 @@
             }
 
             if (recompute_c_y) {
- int_x128_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1];
+ big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1];
                 circle.y(to_fpt(c_y) * inv_denom);
             }
         }
@@ -607,38 +604,38 @@
                  bool recompute_c_x = true,
                  bool recompute_c_y = true,
                  bool recompute_lower_x = true) {
- int_x128_type cA[4], cB[4];
- int_x128_type line_a = static_cast<int_x2_type>(site3.point1(true).y()) -
+ big_int_type cA[4], cB[4];
+ big_int_type line_a = static_cast<int_x2_type>(site3.point1(true).y()) -
                                    static_cast<int_x2_type>(site3.point0(true).y());
- int_x128_type line_b = static_cast<int_x2_type>(site3.point0(true).x()) -
+ big_int_type line_b = static_cast<int_x2_type>(site3.point0(true).x()) -
                                    static_cast<int_x2_type>(site3.point1(true).x());
- int_x128_type segm_len = line_a * line_a + line_b * line_b;
- int_x128_type vec_x = static_cast<int_x2_type>(site2.y()) -
+ big_int_type segm_len = line_a * line_a + line_b * line_b;
+ big_int_type vec_x = static_cast<int_x2_type>(site2.y()) -
                                   static_cast<int_x2_type>(site1.y());
- int_x128_type vec_y = static_cast<int_x2_type>(site1.x()) -
+ big_int_type vec_y = static_cast<int_x2_type>(site1.x()) -
                                   static_cast<int_x2_type>(site2.x());
- int_x128_type sum_x = static_cast<int_x2_type>(site1.x()) +
+ big_int_type sum_x = static_cast<int_x2_type>(site1.x()) +
                                   static_cast<int_x2_type>(site2.x());
- int_x128_type sum_y = static_cast<int_x2_type>(site1.y()) +
+ big_int_type sum_y = static_cast<int_x2_type>(site1.y()) +
                                   static_cast<int_x2_type>(site2.y());
- int_x128_type teta = line_a * vec_x + line_b * vec_y;
- int_x128_type denom = vec_x * line_b - vec_y * line_a;
+ big_int_type teta = line_a * vec_x + line_b * vec_y;
+ big_int_type denom = vec_x * line_b - vec_y * line_a;
 
- int_x128_type dif0 = static_cast<int_x2_type>(site3.point1().y()) -
+ big_int_type dif0 = static_cast<int_x2_type>(site3.point1().y()) -
                                  static_cast<int_x2_type>(site1.y());
- int_x128_type dif1 = static_cast<int_x2_type>(site1.x()) -
+ big_int_type dif1 = static_cast<int_x2_type>(site1.x()) -
                                  static_cast<int_x2_type>(site3.point1().x());
- int_x128_type A = line_a * dif1 - line_b * dif0;
+ big_int_type A = line_a * dif1 - line_b * dif0;
             dif0 = static_cast<int_x2_type>(site3.point1().y()) -
                    static_cast<int_x2_type>(site2.y());
             dif1 = static_cast<int_x2_type>(site2.x()) -
                    static_cast<int_x2_type>(site3.point1().x());
- int_x128_type B = line_a * dif1 - line_b * dif0;
- int_x128_type sum_AB = A + B;
+ big_int_type B = line_a * dif1 - line_b * dif0;
+ big_int_type sum_AB = A + B;
 
             if (is_zero(denom)) {
- int_x128_type numer = teta * teta - sum_AB * sum_AB;
- int_x128_type denom = teta * sum_AB;
+ big_int_type numer = teta * teta - sum_AB * sum_AB;
+ big_int_type denom = teta * sum_AB;
                 cA[0] = denom * sum_x * 2 + numer * vec_x;
                 cB[0] = segm_len;
                 cA[1] = denom * sum_AB * 2 + numer * teta;
@@ -658,7 +655,7 @@
                 return;
             }
 
- int_x128_type det = (teta * teta + denom * denom) * A * B * 4;
+ big_int_type det = (teta * teta + denom * denom) * A * B * 4;
             fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom);
             inv_denom_sqr *= inv_denom_sqr;
 
@@ -704,7 +701,7 @@
                  bool recompute_c_x = true,
                  bool recompute_c_y = true,
                  bool recompute_lower_x = true) {
- int_x128_type a[2], b[2], c[2], cA[4], cB[4];
+ big_int_type a[2], b[2], c[2], cA[4], cB[4];
             const point_type &segm_start1 = site2.point1(true);
             const point_type &segm_end1 = site2.point0(true);
             const point_type &segm_start2 = site3.point0(true);
@@ -717,18 +714,18 @@
                    static_cast<int_x2_type>(segm_start2.x());
             b[1] = static_cast<int_x2_type>(segm_end2.y()) -
                    static_cast<int_x2_type>(segm_start2.y());
- int_x128_type orientation = a[1] * b[0] - a[0] * b[1];
+ big_int_type orientation = a[1] * b[0] - a[0] * b[1];
             if (is_zero(orientation)) {
                 fpt_type denom = to_fpt(2.0) * to_fpt(a[0] * a[0] + b[0] * b[0]);
                 c[0] = b[0] * (static_cast<int_x2_type>(segm_start2.x()) -
                                static_cast<int_x2_type>(segm_start1.x())) -
                        a[0] * (static_cast<int_x2_type>(segm_start2.y()) -
                                static_cast<int_x2_type>(segm_start1.y()));
- int_x128_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) -
+ big_int_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) -
                                            static_cast<int_x2_type>(segm_start1.y())) -
                                    b[0] * (static_cast<int_x2_type>(site1.x()) -
                                            static_cast<int_x2_type>(segm_start1.x()));
- int_x128_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) -
+ big_int_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) -
                                            static_cast<int_x2_type>(segm_start2.x())) -
                                    a[0] * (static_cast<int_x2_type>(site1.y()) -
                                            static_cast<int_x2_type>(segm_start2.y()));
@@ -774,10 +771,10 @@
                    a[0] * segm_end1.y();
             c[1] = a[1] * segm_end2.y() -
                    b[1] * segm_end2.x();
- int_x128_type ix = a[0] * c[1] + a[1] * c[0];
- int_x128_type iy = b[0] * c[1] + b[1] * c[0];
- int_x128_type dx = ix - orientation * site1.x();
- int_x128_type dy = iy - orientation * site1.y();
+ big_int_type ix = a[0] * c[1] + a[1] * c[0];
+ big_int_type iy = b[0] * c[1] + b[1] * c[0];
+ big_int_type dx = ix - orientation * site1.x();
+ big_int_type dy = iy - orientation * site1.y();
             if (is_zero(dx) && is_zero(dy)) {
                 fpt_type denom = to_fpt(orientation);
                 fpt_type c_x = to_fpt(ix) / denom;
@@ -786,7 +783,7 @@
                 return;
             }
 
- int_x128_type sign = ((point_index == 2) ? 1 : -1) * (is_neg(orientation) ? 1 : -1);
+ big_int_type sign = ((point_index == 2) ? 1 : -1) * (is_neg(orientation) ? 1 : -1);
             cA[0] = a[1] * -dx + b[1] * -dy;
             cA[1] = a[0] * -dx + b[0] * -dy;
             cA[2] = sign;
@@ -795,14 +792,14 @@
             cB[1] = a[1] * a[1] + b[1] * b[1];
             cB[2] = a[0] * a[1] + b[0] * b[1];
             cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2;
- fpt_type temp = to_fpt(sqrt_expr_evaluator_pss4<int_x128_type, efpt_type>(cA, cB));
+ fpt_type temp = to_fpt(sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
             fpt_type denom = temp * to_fpt(orientation);
 
             if (recompute_c_y) {
                 cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]);
                 cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]);
                 cA[2] = iy * sign;
- fpt_type cy = to_fpt(sqrt_expr_evaluator_pss4<int_x128_type, efpt_type>(cA, cB));
+ fpt_type cy = to_fpt(sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
                 c_event.y(cy / denom);
             }
 
@@ -812,13 +809,13 @@
                 cA[2] = ix * sign;
 
                 if (recompute_c_x) {
- fpt_type cx = to_fpt(sqrt_expr_evaluator_pss4<int_x128_type, efpt_type>(cA, cB));
+ fpt_type cx = to_fpt(sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
                     c_event.x(cx / denom);
                 }
 
                 if (recompute_lower_x) {
                     cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1);
- fpt_type lower_x = to_fpt(sqrt_expr_evaluator_pss4<int_x128_type, efpt_type>(cA, cB));
+ fpt_type lower_x = to_fpt(sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
                     c_event.lower_x(lower_x / denom);
                 }
             }
@@ -832,7 +829,7 @@
                  bool recompute_c_x = true,
                  bool recompute_c_y = true,
                  bool recompute_lower_x = true) {
- int_x128_type a[3], b[3], c[3], cA[4], cB[4];
+ big_int_type a[3], b[3], c[3], cA[4], cB[4];
             // cA - corresponds to the cross product.
             // cB - corresponds to the squared length.
             a[0] = static_cast<int_x2_type>(site1.x1(true)) -
@@ -1381,12 +1378,16 @@
     }
 };
 
-const unsigned int voronoi_predicates<int>::ULPS = 64;
-const unsigned int voronoi_predicates<int>::ULPSx2 = 128;
-const voronoi_predicates<int>::fpt_type voronoi_predicates<int>::fULPS =
- voronoi_predicates<int>::ULPS;
-const voronoi_predicates<int>::fpt_type voronoi_predicates<int>::fULPSx2 =
- voronoi_predicates<int>::ULPSx2;
+template <typename CTYPE_TRAITS>
+const unsigned int voronoi_predicates<CTYPE_TRAITS>::ULPS = 64;
+template <typename CTYPE_TRAITS>
+const unsigned int voronoi_predicates<CTYPE_TRAITS>::ULPSx2 = 128;
+template <typename CTYPE_TRAITS>
+const typename voronoi_predicates<CTYPE_TRAITS>::fpt_type voronoi_predicates<CTYPE_TRAITS>::fULPS =
+ voronoi_predicates<CTYPE_TRAITS>::ULPS;
+template <typename CTYPE_TRAITS>
+const typename voronoi_predicates<CTYPE_TRAITS>::fpt_type voronoi_predicates<CTYPE_TRAITS>::fULPSx2 =
+ voronoi_predicates<CTYPE_TRAITS>::ULPSx2;
 
 } // detail
 } // polygon

Modified: sandbox/gtl/boost/polygon/detail/voronoi_robust_fpt.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/detail/voronoi_robust_fpt.hpp (original)
+++ sandbox/gtl/boost/polygon/detail/voronoi_robust_fpt.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,19 +1,17 @@
 // Boost.Polygon library detail/voronoi_robust_fpt.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
 // See http://www.boost.org for updates, documentation, and revision history.
 
-#ifndef BOOST_POLYGON_VORONOI_ROBUST_FPT
-#define BOOST_POLYGON_VORONOI_ROBUST_FPT
+#ifndef BOOST_POLYGON_VORONOI_DETAIL_ROBUST_FPT
+#define BOOST_POLYGON_VORONOI_DETAIL_ROBUST_FPT
 
 #include <cmath>
 
-#include <boost/cstdint.hpp>
-
 // Geometry predicates with floating-point variables usually require
 // high-precision predicates to retrieve the correct result.
 // Epsilon robust predicates give the result within some epsilon relative
@@ -56,1181 +54,467 @@
 namespace boost {
 namespace polygon {
 namespace detail {
- typedef boost::int32_t int32;
- typedef boost::int64_t int64;
- typedef boost::uint32_t uint32;
- typedef boost::uint64_t uint64;
- typedef double fpt64;
-
- // If two floating-point numbers in the same format are ordered (x < y),
- // then they are ordered the same way when their bits are reinterpreted as
- // sign-magnitude integers. Values are considered to be almost equal if
- // their integer reinterpretations differ in not more than maxUlps units.
- template <typename _fpt>
- struct ulp_comparison;
-
- template <>
- struct ulp_comparison<fpt64> {
- enum kResult {
- LESS = -1,
- EQUAL = 0,
- MORE = 1
- };
-
- kResult operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const {
- uint64 ll_a, ll_b;
-
- // Reinterpret double bits as 64-bit signed integer.
- memcpy(&ll_a, &a, sizeof(fpt64));
- memcpy(&ll_b, &b, sizeof(fpt64));
-
- // Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000.
- // Map negative zero to an integer zero representation - making it
- // identical to positive zero - the smallest negative number is
- // represented by negative one, and downwards from there.
- if (ll_a < 0x8000000000000000ULL)
- ll_a = 0x8000000000000000ULL - ll_a;
- if (ll_b < 0x8000000000000000ULL)
- ll_b = 0x8000000000000000ULL - ll_b;
-
- // Compare 64-bit signed integer representations of input values.
- // Difference in 1 Ulp is equivalent to a relative error of between
- // 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
- if (ll_a > ll_b)
- return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS;
- return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE;
- }
- };
 
- template <typename T>
- T get_sqrt(const T& that) {
- return (std::sqrt)(that);
- }
+template <typename T>
+T get_sqrt(const T& that) {
+ return (std::sqrt)(that);
+}
 
- template <typename T>
- bool is_pos(const T& that) {
- return that > 0;
- }
+template <typename T>
+bool is_pos(const T& that) {
+ return that > 0;
+}
 
- template <typename T>
- bool is_neg(const T& that) {
- return that < 0;
- }
+template <typename T>
+bool is_neg(const T& that) {
+ return that < 0;
+}
 
- template <typename T>
- bool is_zero(const T& that) {
- return that == 0;
- }
+template <typename T>
+bool is_zero(const T& that) {
+ return that == 0;
+}
 
- template <typename _fpt>
- class robust_fpt {
- public:
- typedef _fpt floating_point_type;
- typedef _fpt relative_error_type;
+template <typename _fpt>
+class robust_fpt {
+public:
+ typedef _fpt floating_point_type;
+ typedef _fpt relative_error_type;
 
- // Rounding error is at most 1 EPS.
- static const relative_error_type ROUNDING_ERROR;
+ // Rounding error is at most 1 EPS.
+ static const relative_error_type ROUNDING_ERROR;
 
- robust_fpt() : fpv_(0.0), re_(0.0) {}
- explicit robust_fpt(floating_point_type fpv,
- bool rounded = true) : fpv_(fpv) {
- re_ = rounded ? ROUNDING_ERROR : 0;
- }
- robust_fpt(floating_point_type fpv, relative_error_type error) :
- fpv_(fpv), re_(error) {}
+ robust_fpt() : fpv_(0.0), re_(0.0) {}
+ explicit robust_fpt(floating_point_type fpv,
+ bool rounded = true) : fpv_(fpv) {
+ re_ = rounded ? ROUNDING_ERROR : 0;
+ }
+ robust_fpt(floating_point_type fpv, relative_error_type error) :
+ fpv_(fpv), re_(error) {}
 
- floating_point_type fpv() const { return fpv_; }
- relative_error_type re() const { return re_; }
- relative_error_type ulp() const { return re_; }
-
- robust_fpt& operator=(const robust_fpt &that) {
- this->fpv_ = that.fpv_;
- this->re_ = that.re_;
- return *this;
- }
+ floating_point_type fpv() const { return fpv_; }
+ relative_error_type re() const { return re_; }
+ relative_error_type ulp() const { return re_; }
 
- bool has_pos_value() const {
- return is_pos(fpv_);
- }
+ robust_fpt& operator=(const robust_fpt &that) {
+ this->fpv_ = that.fpv_;
+ this->re_ = that.re_;
+ return *this;
+ }
 
- bool has_neg_value() const {
- return is_neg(fpv_);
- }
+ bool has_pos_value() const {
+ return is_pos(fpv_);
+ }
 
- bool has_zero_value() const {
- return is_zero(fpv_);
- }
+ bool has_neg_value() const {
+ return is_neg(fpv_);
+ }
 
- robust_fpt operator-() const {
- return robust_fpt(-fpv_, re_);
- }
+ bool has_zero_value() const {
+ return is_zero(fpv_);
+ }
+
+ robust_fpt operator-() const {
+ return robust_fpt(-fpv_, re_);
+ }
 
- robust_fpt& operator+=(const robust_fpt &that) {
- floating_point_type fpv = this->fpv_ + that.fpv_;
- if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
- (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
- this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
- else {
- floating_point_type temp =
- (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
- if (is_neg(temp)) {
- temp = -temp;
- }
- this->re_ = temp + ROUNDING_ERROR;
+ robust_fpt& operator+=(const robust_fpt &that) {
+ floating_point_type fpv = this->fpv_ + that.fpv_;
+ if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
+ this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp)) {
+ temp = -temp;
             }
- this->fpv_ = fpv;
- return *this;
+ this->re_ = temp + ROUNDING_ERROR;
         }
+ this->fpv_ = fpv;
+ return *this;
+ }
 
- robust_fpt& operator-=(const robust_fpt &that) {
- floating_point_type fpv = this->fpv_ - that.fpv_;
- if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
- (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
- this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
- else {
- floating_point_type temp =
- (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
- if (is_neg(temp)) {
- temp = -temp;
- }
- this->re_ = temp + ROUNDING_ERROR;
+ robust_fpt& operator-=(const robust_fpt &that) {
+ floating_point_type fpv = this->fpv_ - that.fpv_;
+ if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
+ this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp)) {
+ temp = -temp;
             }
- this->fpv_ = fpv;
- return *this;
+ this->re_ = temp + ROUNDING_ERROR;
         }
+ this->fpv_ = fpv;
+ return *this;
+ }
 
- robust_fpt& operator*=(const robust_fpt &that) {
- this->re_ += that.re_ + ROUNDING_ERROR;
- this->fpv_ *= that.fpv_;
- return *this;
- }
+ robust_fpt& operator*=(const robust_fpt &that) {
+ this->re_ += that.re_ + ROUNDING_ERROR;
+ this->fpv_ *= that.fpv_;
+ return *this;
+ }
 
- robust_fpt& operator/=(const robust_fpt &that) {
- this->re_ += that.re_ + ROUNDING_ERROR;
- this->fpv_ /= that.fpv_;
- return *this;
- }
+ robust_fpt& operator/=(const robust_fpt &that) {
+ this->re_ += that.re_ + ROUNDING_ERROR;
+ this->fpv_ /= that.fpv_;
+ return *this;
+ }
 
- robust_fpt operator+(const robust_fpt &that) const {
- floating_point_type fpv = this->fpv_ + that.fpv_;
- relative_error_type re;
- if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
- (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
- re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
- else {
- floating_point_type temp =
- (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
- if (is_neg(temp)) {
- temp = -temp;
- }
- re = temp + ROUNDING_ERROR;
+ robust_fpt operator+(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ + that.fpv_;
+ relative_error_type re;
+ if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
+ re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp)) {
+ temp = -temp;
             }
- return robust_fpt(fpv, re);
+ re = temp + ROUNDING_ERROR;
         }
+ return robust_fpt(fpv, re);
+ }
 
- robust_fpt operator-(const robust_fpt &that) const {
- floating_point_type fpv = this->fpv_ - that.fpv_;
- relative_error_type re;
- if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
- (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
- re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
- else {
- floating_point_type temp =
- (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
- if (is_neg(temp)) {
- temp = -temp;
- }
- re = temp + ROUNDING_ERROR;
+ robust_fpt operator-(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ - that.fpv_;
+ relative_error_type re;
+ if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
+ re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp)) {
+ temp = -temp;
             }
- return robust_fpt(fpv, re);
- }
-
- robust_fpt operator*(const robust_fpt &that) const {
- floating_point_type fpv = this->fpv_ * that.fpv_;
- relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
- return robust_fpt(fpv, re);
+ re = temp + ROUNDING_ERROR;
         }
-
- robust_fpt operator/(const robust_fpt &that) const {
- floating_point_type fpv = this->fpv_ / that.fpv_;
- relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
- return robust_fpt(fpv, re);
- }
-
- robust_fpt sqrt() const {
- return robust_fpt(get_sqrt(fpv_),
- re_ * static_cast<relative_error_type>(0.5) +
- ROUNDING_ERROR);
- }
-
- private:
- floating_point_type fpv_;
- relative_error_type re_;
- };
-
- template <typename T>
- const typename robust_fpt<T>::relative_error_type
- robust_fpt<T>::ROUNDING_ERROR = 1;
-
- template <typename T>
- robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
- return that.sqrt();
+ return robust_fpt(fpv, re);
     }
 
- template <typename T>
- bool is_pos(const robust_fpt<T>& that) {
- return that.has_pos_value();
+ robust_fpt operator*(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ * that.fpv_;
+ relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
+ return robust_fpt(fpv, re);
     }
 
- template <typename T>
- bool is_neg(const robust_fpt<T>& that) {
- return that.has_neg_value();
+ robust_fpt operator/(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ / that.fpv_;
+ relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
+ return robust_fpt(fpv, re);
     }
 
- template <typename T>
- bool is_zero(const robust_fpt<T>& that) {
- return that.has_zero_value();
+ robust_fpt sqrt() const {
+ return robust_fpt(get_sqrt(fpv_),
+ re_ * static_cast<relative_error_type>(0.5) +
+ ROUNDING_ERROR);
     }
 
- // robust_dif consists of two not negative values: value1 and value2.
- // The resulting expression is equal to the value1 - value2.
- // Substraction of a positive value is equivalent to the addition to value2
- // and substraction of a negative value is equivalent to the addition to
- // value1. The structure implicitly avoids difference computation.
- template <typename T>
- class robust_dif {
- public:
- robust_dif() :
- positive_sum_(0),
- negative_sum_(0) {}
+private:
+ floating_point_type fpv_;
+ relative_error_type re_;
+};
 
- robust_dif(const T &value) :
- positive_sum_((value>0)?value:0),
- negative_sum_((value<0)?-value:0) {}
+template <typename T>
+const typename robust_fpt<T>::relative_error_type
+ robust_fpt<T>::ROUNDING_ERROR = 1;
 
- robust_dif(const T &pos, const T &neg) :
- positive_sum_(pos),
- negative_sum_(neg) {}
-
- T dif() const {
- return positive_sum_ - negative_sum_;
- }
-
- T pos() const {
- return positive_sum_;
- }
+template <typename T>
+robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
+ return that.sqrt();
+}
 
- T neg() const {
- return negative_sum_;
- }
-
- robust_dif<T> operator-() const {
- return robust_dif(negative_sum_, positive_sum_);
- }
-
- robust_dif<T> &operator+=(const T &val) {
- if (!is_neg(val))
- positive_sum_ += val;
- else
- negative_sum_ -= val;
- return *this;
- }
-
- robust_dif<T> &operator+=(const robust_dif<T> &that) {
- positive_sum_ += that.positive_sum_;
- negative_sum_ += that.negative_sum_;
- return *this;
- }
+template <typename T>
+bool is_pos(const robust_fpt<T>& that) {
+ return that.has_pos_value();
+}
 
- robust_dif<T> &operator-=(const T &val) {
- if (!is_neg(val))
- negative_sum_ += val;
- else
- positive_sum_ -= val;
- return *this;
- }
+template <typename T>
+bool is_neg(const robust_fpt<T>& that) {
+ return that.has_neg_value();
+}
 
- robust_dif<T> &operator-=(const robust_dif<T> &that) {
- positive_sum_ += that.negative_sum_;
- negative_sum_ += that.positive_sum_;
- return *this;
- }
+template <typename T>
+bool is_zero(const robust_fpt<T>& that) {
+ return that.has_zero_value();
+}
 
- robust_dif<T> &operator*=(const T &val) {
- if (!is_neg(val)) {
- positive_sum_ *= val;
- negative_sum_ *= val;
- } else {
- positive_sum_ *= -val;
- negative_sum_ *= -val;
- swap();
- }
- return *this;
- }
+// robust_dif consists of two not negative values: value1 and value2.
+// The resulting expression is equal to the value1 - value2.
+// Substraction of a positive value is equivalent to the addition to value2
+// and substraction of a negative value is equivalent to the addition to
+// value1. The structure implicitly avoids difference computation.
+template <typename T>
+class robust_dif {
+public:
+ robust_dif() :
+ positive_sum_(0),
+ negative_sum_(0) {}
 
- robust_dif<T> &operator*=(const robust_dif<T> &that) {
- T positive_sum = this->positive_sum_ * that.positive_sum_ +
- this->negative_sum_ * that.negative_sum_;
- T negative_sum = this->positive_sum_ * that.negative_sum_ +
- this->negative_sum_ * that.positive_sum_;
- positive_sum_ = positive_sum;
- negative_sum_ = negative_sum;
- return *this;
- }
+ robust_dif(const T &value) :
+ positive_sum_((value>0)?value:0),
+ negative_sum_((value<0)?-value:0) {}
 
- robust_dif<T> &operator/=(const T &val) {
- if (!is_neg(val)) {
- positive_sum_ /= val;
- negative_sum_ /= val;
- } else {
- positive_sum_ /= -val;
- negative_sum_ /= -val;
- swap();
- }
- return *this;
- }
+ robust_dif(const T &pos, const T &neg) :
+ positive_sum_(pos),
+ negative_sum_(neg) {}
 
- private:
- void swap() {
- (std::swap)(positive_sum_, negative_sum_);
- }
+ T dif() const {
+ return positive_sum_ - negative_sum_;
+ }
 
- T positive_sum_;
- T negative_sum_;
- };
-
- template<typename T>
- robust_dif<T> operator+(const robust_dif<T>& lhs,
- const robust_dif<T>& rhs) {
- return robust_dif<T>(lhs.pos() + rhs.pos(),
- lhs.neg() + rhs.neg());
+ T pos() const {
+ return positive_sum_;
     }
 
- template<typename T>
- robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
- if (!is_neg(rhs)) {
- return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
- } else {
- return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
- }
+ T neg() const {
+ return negative_sum_;
     }
 
- template<typename T>
- robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
- if (!is_neg(lhs)) {
- return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
- } else {
- return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
- }
+ robust_dif<T> operator-() const {
+ return robust_dif(negative_sum_, positive_sum_);
     }
 
- template<typename T>
- robust_dif<T> operator-(const robust_dif<T>& lhs,
- const robust_dif<T>& rhs) {
- return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
+ robust_dif<T> &operator+=(const T &val) {
+ if (!is_neg(val))
+ positive_sum_ += val;
+ else
+ negative_sum_ -= val;
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
- if (!is_neg(rhs)) {
- return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
- } else {
- return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
- }
+ robust_dif<T> &operator+=(const robust_dif<T> &that) {
+ positive_sum_ += that.positive_sum_;
+ negative_sum_ += that.negative_sum_;
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
- if (!is_neg(lhs)) {
- return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
- } else {
- return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
- }
+ robust_dif<T> &operator-=(const T &val) {
+ if (!is_neg(val))
+ negative_sum_ += val;
+ else
+ positive_sum_ -= val;
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator*(const robust_dif<T>& lhs,
- const robust_dif<T>& rhs) {
- T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
- T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
- return robust_dif<T>(res_pos, res_neg);
+ robust_dif<T> &operator-=(const robust_dif<T> &that) {
+ positive_sum_ += that.negative_sum_;
+ negative_sum_ += that.positive_sum_;
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
+ robust_dif<T> &operator*=(const T &val) {
         if (!is_neg(val)) {
- return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
+ positive_sum_ *= val;
+ negative_sum_ *= val;
         } else {
- return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
+ positive_sum_ *= -val;
+ negative_sum_ *= -val;
+ swap();
         }
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
- if (!is_neg(val)) {
- return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
- } else {
- return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
- }
+ robust_dif<T> &operator*=(const robust_dif<T> &that) {
+ T positive_sum = this->positive_sum_ * that.positive_sum_ +
+ this->negative_sum_ * that.negative_sum_;
+ T negative_sum = this->positive_sum_ * that.negative_sum_ +
+ this->negative_sum_ * that.positive_sum_;
+ positive_sum_ = positive_sum;
+ negative_sum_ = negative_sum;
+ return *this;
     }
 
- template<typename T>
- robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
+ robust_dif<T> &operator/=(const T &val) {
         if (!is_neg(val)) {
- return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
+ positive_sum_ /= val;
+ negative_sum_ /= val;
         } else {
- return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
- }
- }
-
- // Manages exponent of the floating-point value.
- template <typename _fpt>
- struct fpt_exponent_accessor;
-
- template <>
- class fpt_exponent_accessor<fpt64> {
- public:
- static const int64 kExponentMask;
- static const int64 kSignedMantissaMask;
- static const int64 kMinExponent;
- static const int64 kMaxExponent;
- static const int64 kMaxSignificantExpDif;
-
- static int64 set_exponent(fpt64& value, int64 exponent) {
- int64 bits;
- memcpy(&bits, &value, sizeof(fpt64));
- int64 exp = ((bits & kExponentMask) >> 52) - 1023;
- if (exp == exponent) {
- return exp;
- }
- bits = (bits & kSignedMantissaMask) | ((exponent + 1023) << 52);
- memcpy(&value, &bits, sizeof(fpt64));
- return exp;
- }
- };
-
- const int64 fpt_exponent_accessor<fpt64>::kExponentMask = 0x7ff0000000000000LL;
- const int64 fpt_exponent_accessor<fpt64>::kSignedMantissaMask = 0x800fffffffffffffLL;
- const int64 fpt_exponent_accessor<fpt64>::kMinExponent = -1023LL;
- const int64 fpt_exponent_accessor<fpt64>::kMaxExponent = 1024LL;
- const int64 fpt_exponent_accessor<fpt64>::kMaxSignificantExpDif = 54;
-
- // Allows to extend floating-point type exponent boundaries to the 64 bit
- // integer range. This class does not handle division by zero, subnormal
- // numbers or NaNs.
- template <typename _fpt>
- class extended_exponent_fpt {
- public:
- typedef _fpt fpt_type;
- typedef int64 exp_type;
- typedef fpt_exponent_accessor<fpt_type> fea;
-
- explicit extended_exponent_fpt(fpt_type value) {
- if (value == 0.0) {
- exponent_ = 0;
- value_ = 0.0;
- } else {
- exponent_ = fea::set_exponent(value, 0);
- value_ = value;
- }
- }
-
- extended_exponent_fpt(fpt_type value, exp_type exponent) {
- if (value == 0.0) {
- exponent_ = 0;
- value_ = 0.0;
- } else {
- exponent_ = fea::set_exponent(value, 0) + exponent;
- value_ = value;
- }
- }
-
- bool is_pos() const {
- return value_ > 0;
- }
-
- bool is_neg() const {
- return value_ < 0;
- }
-
- bool is_zero() const {
- return value_ == 0;
- }
-
- extended_exponent_fpt operator-() const {
- return extended_exponent_fpt(-value_, exponent_);
- }
-
- extended_exponent_fpt operator+(const extended_exponent_fpt& that) const {
- if (this->value_ == 0.0 ||
- that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
- return that;
- }
- if (that.value_ == 0.0 ||
- this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
- return *this;
- }
- if (this->exponent_ >= that.exponent_) {
- exp_type exp_dif = this->exponent_ - that.exponent_;
- fpt_type value = this->value_;
- fea::set_exponent(value, exp_dif);
- value += that.value_;
- return extended_exponent_fpt(value, that.exponent_);
- } else {
- exp_type exp_dif = that.exponent_ - this->exponent_;
- fpt_type value = that.value_;
- fea::set_exponent(value, exp_dif);
- value += this->value_;
- return extended_exponent_fpt(value, this->exponent_);
- }
- }
-
- extended_exponent_fpt operator-(const extended_exponent_fpt& that) const {
- if (this->value_ == 0.0 ||
- that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
- return extended_exponent_fpt(-that.value_, that.exponent_);
- }
- if (that.value_ == 0.0 ||
- this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
- return *this;
- }
- if (this->exponent_ >= that.exponent_) {
- exp_type exp_dif = this->exponent_ - that.exponent_;
- fpt_type value = this->value_;
- fea::set_exponent(value, exp_dif);
- value -= that.value_;
- return extended_exponent_fpt(value, that.exponent_);
- } else {
- exp_type exp_dif = that.exponent_ - this->exponent_;
- fpt_type value = -that.value_;
- fea::set_exponent(value, exp_dif);
- value += this->value_;
- return extended_exponent_fpt(value, this->exponent_);
- }
- }
-
- extended_exponent_fpt operator*(const extended_exponent_fpt& that) const {
- fpt_type value = this->value_ * that.value_;
- exp_type exponent = this->exponent_ + that.exponent_;
- return extended_exponent_fpt(value, exponent);
- }
-
- extended_exponent_fpt operator/(const extended_exponent_fpt& that) const {
- fpt_type value = this->value_ / that.value_;
- exp_type exponent = this->exponent_ - that.exponent_;
- return extended_exponent_fpt(value, exponent);
- }
-
- extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) {
- return *this = *this + that;
- }
-
- extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) {
- return *this = *this - that;
- }
-
- extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) {
- return *this = *this * that;
- }
-
- extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) {
- return *this = *this / that;
- }
-
- extended_exponent_fpt sqrt() const {
- fpt_type val = value_;
- exp_type exp = exponent_;
- if (exp & 1) {
- val *= 2.0;
- --exp;
- }
- return extended_exponent_fpt(get_sqrt(val), exp >> 1);
- }
-
- fpt_type d() const {
- fpt_type ret_val = value_;
- exp_type exp = exponent_;
- if (ret_val == 0.0) {
- return ret_val;
- }
- if (exp >= fea::kMaxExponent) {
- ret_val = 1.0;
- exp = fea::kMaxExponent;
- } else if (exp <= fea::kMinExponent) {
- ret_val = 1.0;
- exp = fea::kMinExponent;
- }
- fea::set_exponent(ret_val, exp);
- return ret_val;
- }
-
- private:
- fpt_type value_;
- exp_type exponent_;
- };
- typedef extended_exponent_fpt<double> efpt64;
-
- template <typename _fpt>
- extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) {
- return that.sqrt();
- }
-
- template <typename _fpt>
- bool is_pos(const extended_exponent_fpt<_fpt>& that) {
- return that.is_pos();
- }
-
- template <typename _fpt>
- bool is_neg(const extended_exponent_fpt<_fpt>& that) {
- return that.is_neg();
- }
-
- template <typename _fpt>
- bool is_zero(const extended_exponent_fpt<_fpt>& that) {
- return that.is_zero();
- }
-
- template<size_t N>
- class extended_int {
- public:
- static const uint64 kUInt64LowMask;
- static const uint64 kUInt64HighMask;
-
- extended_int() {}
-
- extended_int(int32 that) {
- if (that > 0) {
- this->chunks_[0] = that;
- this->count_ = 1;
- } else if (that < 0) {
- this->chunks_[0] = -that;
- this->count_ = -1;
- } else {
- this->chunks_[0] = this->count_ = 0;
- }
- }
-
- extended_int(int64 that) {
- if (that > 0) {
- this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
- uint32 high = (that & kUInt64HighMask) >> 32;
- if (high) {
- this->chunks_[1] = high;
- this->count_ = 2;
- } else {
- this->count_ = 1;
- }
- } else if (that < 0) {
- that = -that;
- this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
- uint32 high = (that & kUInt64HighMask) >> 32;
- if (high) {
- this->chunks_[1] = high;
- this->count_ = -2;
- } else {
- this->count_ = -1;
- }
- } else {
- this->chunks_[0] = this->count_ = 0;
- }
- }
-
- extended_int(const std::vector<uint32>& chunks, bool plus = true) {
- this->count_ = static_cast<int32>(chunks.size());
- for (size_t i = 0; i < chunks.size(); ++i) {
- this->chunks_[i] = chunks[chunks.size() - i - 1];
- }
- if (!plus) {
- this->count_ = -this->count_;
- }
- }
-
- template <size_t M>
- extended_int(const extended_int<M>& that) {
- this->count_ = that.count();
- memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
- }
-
- extended_int<N>& operator=(int32 that) {
- if (that > 0) {
- this->chunks_[0] = that;
- this->count_ = 1;
- } else if (that < 0) {
- this->chunks_[0] = -that;
- this->count_ = -1;
- } else {
- this->chunks_[0] = this->count_ = 0;
- }
- return *this;
- }
-
- extended_int<N>& operator=(int64 that) {
- if (that > 0) {
- this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
- uint32 high = (that & kUInt64HighMask) >> 32;
- if (high) {
- this->chunks_[1] = high;
- this->count_ = 2;
- } else {
- this->count_ = 1;
- }
- } else if (that < 0) {
- that = -that;
- this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
- uint32 high = (that & kUInt64HighMask) >> 32;
- if (high) {
- this->chunks_[1] = high;
- this->count_ = -2;
- } else {
- this->count_ = -1;
- }
- } else {
- this->chunks_[0] = this->count_ = 0;
- }
- return *this;
- }
-
- template <size_t M>
- extended_int<N>& operator=(const extended_int<M>& that) {
- this->count_ = that.count();
- size_t sz = (std::min)(N, that.size());
- memcpy(this->chunks_, that.chunks(), sz * sizeof(uint32));
- return *this;
- }
-
- bool is_pos() const {
- return this->count_ > 0;
- }
-
- bool is_neg() const {
- return this->count_ < 0;
- }
-
- bool is_zero() const {
- return this->count_ == 0;
- }
-
- template <size_t M>
- bool operator==(const extended_int<M>& that) const {
- if (this->count_ != that.count()) {
- return false;
- }
- for (size_t i = 0; i < this->size(); ++i) {
- if (this->chunks_[i] != that.chunks()[i]) {
- return false;
- }
- }
- return true;
- }
-
- template <size_t M>
- bool operator!=(const extended_int<M>& that) const {
- return !(*this == that);
- }
-
- template <size_t M>
- bool operator<(const extended_int<M>& that) const {
- if (this->count_ != that.count()) {
- return this->count_ < that.count();
- }
- size_t i = this->size();
- if (!i) {
- return false;
- }
- do {
- --i;
- if (this->chunks_[i] != that.chunks()[i]) {
- return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0);
- }
- } while (i);
- return false;
- }
-
- template <size_t M>
- bool operator>(const extended_int<M>& that) const {
- return that < *this;
- }
-
- template <size_t M>
- bool operator<=(const extended_int<M>& that) const {
- return !(that < *this);
- }
-
- template <size_t M>
- bool operator>=(const extended_int<M>& that) const {
- return !(*this < that);
- }
-
- extended_int<N> operator-() const {
- extended_int<N> ret_val = *this;
- ret_val.neg();
- return ret_val;
- }
-
- void neg() {
- this->count_ = -this->count_;
- }
-
- template <size_t M>
- extended_int<(N>M?N:M)> operator+(const extended_int<M>& that) const {
- extended_int<(N>M?N:M)> ret_val;
- ret_val.add(*this, that);
- return ret_val;
- }
-
- template <size_t N1, size_t N2>
- void add(const extended_int<N1>& e1, const extended_int<N2>& e2) {
- if (!e1.count()) {
- *this = e2;
- return;
- }
- if (!e2.count()) {
- *this = e1;
- return;
- }
- if ((e1.count() > 0) ^ (e2.count() > 0)) {
- dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
- } else {
- add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
- }
- if (e1.count() < 0) {
- this->count_ = -this->count_;
- }
- }
-
- template <size_t M>
- extended_int<(N>M?N:M)> operator-(const extended_int<M>& that) const {
- extended_int<(N>M?N:M)> ret_val;
- ret_val.dif(*this, that);
- return ret_val;
- }
-
- template <size_t N1, size_t N2>
- void dif(const extended_int<N1>& e1, const extended_int<N2> &e2) {
- if (!e1.count()) {
- *this = e2;
- this->count_ = -this->count_;
- return;
- }
- if (!e2.count()) {
- *this = e1;
- return;
- }
- if ((e1.count() > 0) ^ (e2.count() > 0)) {
- add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
- } else {
- dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
- }
- if (e1.count() < 0) {
- this->count_ = -this->count_;
- }
- }
-
- extended_int<N> operator*(int32 that) const {
- extended_int<N> temp(that);
- return (*this) * temp;
- }
-
- extended_int<N> operator*(int64 that) const {
- extended_int<N> temp(that);
- return (*this) * temp;
- }
-
- template <size_t M>
- extended_int<(N>M?N:M)> operator*(const extended_int<M>& that) const {
- extended_int<(N>M?N:M)> ret_val;
- ret_val.mul(*this, that);
- return ret_val;
- }
-
- template <size_t N1, size_t N2>
- void mul(const extended_int<N1>& e1, const extended_int<N2>& e2) {
- if (!e1.count() || !e2.count()) {
- this->chunks_[0] = this->count_ = 0;
- return;
- }
- mul(e1.chunks(), e1.size(), e2.chunks(), e2.size());
- if ((e1.count() > 0) ^ (e2.count() > 0)) {
- this->count_ = -this->count_;
- }
- }
-
- const uint32* chunks() const {
- return chunks_;
- }
-
- int32 count() const {
- return count_;
- }
-
- size_t size() const {
- return (std::abs)(count_);
- }
-
- std::pair<fpt64, int64> p() const {
- std::pair<fpt64, int64> ret_val(0, 0);
- size_t sz = this->size();
- if (!sz) {
- return ret_val;
- } else {
- if (sz == 1) {
- ret_val.first = static_cast<fpt64>(this->chunks_[0]);
- ret_val.second = 0;
- } else if (sz == 2) {
- ret_val.first = static_cast<fpt64>(this->chunks_[1]) *
- static_cast<fpt64>(0x100000000LL) +
- static_cast<fpt64>(this->chunks_[0]);
- ret_val.second = 0;
- } else {
- for (size_t i = 1; i <= 3; ++i) {
- ret_val.first *= static_cast<fpt64>(0x100000000LL);
- ret_val.first += static_cast<fpt64>(this->chunks_[sz - i]);
- }
- ret_val.second = (sz - 3) << 5;
- }
- }
- if (this->count_ < 0) {
- ret_val.first = -ret_val.first;
- }
- return ret_val;
- }
-
- fpt64 d() const {
- std::pair<fpt64, int64> p = this->p();
- extended_exponent_fpt<fpt64> efpt(p.first, p.second);
- return efpt.d();
- }
-
- private:
- void add(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
- if (sz1 < sz2) {
- add(c2, sz2, c1, sz1);
- return;
- }
- this->count_ = sz1;
- uint64 temp = 0;
- for (size_t i = 0; i < sz2; ++i) {
- temp += static_cast<uint64>(c1[i]) +
- static_cast<uint64>(c2[i]);
- this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
- temp = (temp & kUInt64HighMask) >> 32;
- }
- for (size_t i = sz2; i < sz1; ++i) {
- temp += static_cast<uint64>(c1[i]);
- this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
- temp = (temp & kUInt64HighMask) >> 32;
- }
- if (temp && (this->count_ != N)) {
- this->chunks_[this->count_] = static_cast<uint32>(temp & kUInt64LowMask);
- ++this->count_;
- }
- }
-
- void dif(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2, bool rec = false) {
- if (sz1 < sz2) {
- dif(c2, sz2, c1, sz1, true);
- this->count_ = -this->count_;
- return;
- } else if ((sz1 == sz2) && !rec) {
- do {
- --sz1;
- if (c1[sz1] < c2[sz1]) {
- ++sz1;
- dif(c2, sz1, c1, sz1, true);
- this->count_ = -this->count_;
- return;
- } else if (c1[sz1] > c2[sz1]) {
- ++sz1;
- break;
- } else if (!sz1) {
- this->chunks_[0] = this->count_ = 0;
- return;
- }
- } while (sz1);
- sz2 = sz1;
- }
- this->count_ = sz1-1;
- bool flag = false;
- for (size_t i = 0; i < sz2; ++i) {
- this->chunks_[i] = c1[i] - c2[i] - (flag?1:0);
- flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag);
- }
- for (size_t i = sz2; i < sz1; ++i) {
- this->chunks_[i] = c1[i] - (flag?1:0);
- flag = !c1[i] && flag;
- }
- if (this->chunks_[this->count_]) {
- ++this->count_;
- }
- }
-
- void mul(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
- uint64 cur = 0, nxt, tmp;
- this->count_ = static_cast<int32>((std::min)(N, sz1 + sz2 - 1));
- for (size_t shift = 0; shift < static_cast<size_t>(this->count_); ++shift) {
- nxt = 0;
- for (size_t first = 0; first <= shift; ++first) {
- if (first >= sz1) {
- break;
- }
- size_t second = shift - first;
- if (second >= sz2) {
- continue;
- }
- tmp = static_cast<uint64>(c1[first]) *
- static_cast<uint64>(c2[second]);
- cur += tmp & kUInt64LowMask;
- nxt += (tmp & kUInt64HighMask) >> 32;
- }
- this->chunks_[shift] = static_cast<uint32>(cur & kUInt64LowMask);
- cur = nxt + ((cur & kUInt64HighMask) >> 32);
- }
- if (cur && (this->count_ != N)) {
- this->chunks_[this->count_] = static_cast<uint32>(cur & kUInt64LowMask);
- ++this->count_;
- }
- }
-
- uint32 chunks_[N];
- int32 count_;
- };
-
- template <size_t N>
- const uint64 extended_int<N>::kUInt64LowMask = 0x00000000ffffffffULL;
- template <size_t N>
- const uint64 extended_int<N>::kUInt64HighMask = 0xffffffff00000000ULL;
-
- typedef extended_int<1> eint32;
- typedef extended_int<2> eint64;
- typedef extended_int<4> eint128;
- typedef extended_int<8> eint256;
- typedef extended_int<16> eint512;
- typedef extended_int<32> eint1024;
- typedef extended_int<64> eint2048;
- typedef extended_int<128> eint4096;
- typedef extended_int<256> eint8192;
- typedef extended_int<512> eint16384;
- typedef extended_int<1024> eint32768;
-
- template <size_t N>
- bool is_pos(const extended_int<N>& that) {
- return that.count() > 0;
- }
-
- template <size_t N>
- bool is_neg(const extended_int<N>& that) {
- return that.count() < 0;
- }
-
- template <size_t N>
- bool is_zero(const extended_int<N>& that) {
- return !that.count();
- }
-
- struct type_converter_fpt {
- template <typename T>
- fpt64 operator()(const T& that) const {
- return static_cast<fpt64>(that);
- }
-
- template <size_t N>
- fpt64 operator()(const extended_int<N>& that) const {
- return that.d();
- }
-
- template <>
- fpt64 operator()< extended_exponent_fpt<fpt64> >(const extended_exponent_fpt<fpt64>& that) const {
- return that.d();
- }
- };
-
- struct type_converter_efpt {
- template <size_t N>
- extended_exponent_fpt<fpt64> operator()(const extended_int<N>& that) const {
- std::pair<fpt64, int64> p = that.p();
- return extended_exponent_fpt<fpt64>(p.first, p.second);
- }
- };
-
- // Used to compute expressions that operate with sqrts with predefined
- // relative error. Evaluates expressions of the next type:
- // sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4.
- template <typename _int, typename _fpt, typename _converter>
- class robust_sqrt_expr {
- public:
- static const unsigned int EVAL1_MAX_RELATIVE_ERROR;
- static const unsigned int EVAL2_MAX_RELATIVE_ERROR;
- static const unsigned int EVAL3_MAX_RELATIVE_ERROR;
- static const unsigned int EVAL4_MAX_RELATIVE_ERROR;
-
- // Evaluates expression (re = 4 EPS):
- // A[0] * sqrt(B[0]).
- _fpt eval1(_int *A, _int *B) {
- _fpt a = convert(A[0]);
- _fpt b = convert(B[0]);
- return a * get_sqrt(b);
- }
-
- // Evaluates expression (re = 7 EPS):
- // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]).
- _fpt eval2(_int *A, _int *B) {
- _fpt a = eval1(A, B);
- _fpt b = eval1(A + 1, B + 1);
- if ((!is_neg(a) && !is_neg(b)) ||
- (!is_pos(a) && !is_pos(b)))
- return a + b;
- return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
- }
-
- // Evaluates expression (re = 16 EPS):
- // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]).
- _fpt eval3(_int *A, _int *B) {
- _fpt a = eval2(A, B);
- _fpt b = eval1(A + 2, B + 2);
- if ((!is_neg(a) && !is_neg(b)) ||
- (!is_pos(a) && !is_pos(b)))
- return a + b;
- tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
- tB[3] = 1;
- tA[4] = A[0] * A[1] * 2;
- tB[4] = B[0] * B[1];
- return eval2(tA + 3, tB + 3) / (a - b);
- }
-
-
- // Evaluates expression (re = 25 EPS):
- // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
- // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]).
- _fpt eval4(_int *A, _int *B) {
- _fpt a = eval2(A, B);
- _fpt b = eval2(A + 2, B + 2);
- if ((!is_neg(a) && !is_neg(b)) ||
- (!is_pos(a) && !is_pos(b)))
- return a + b;
- tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
- A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
- tB[0] = 1;
- tA[1] = A[0] * A[1] * 2;
- tB[1] = B[0] * B[1];
- tA[2] = A[2] * A[3] * -2;
- tB[2] = B[2] * B[3];
- return eval3(tA, tB) / (a - b);
- }
-
- private:
- _int tA[5];
- _int tB[5];
- _converter convert;
- };
-
- template <typename _int, typename _fpt, typename _converter>
- const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL1_MAX_RELATIVE_ERROR = 4;
- template <typename _int, typename _fpt, typename _converter>
- const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL2_MAX_RELATIVE_ERROR = 7;
- template <typename _int, typename _fpt, typename _converter>
- const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL3_MAX_RELATIVE_ERROR = 16;
- template <typename _int, typename _fpt, typename _converter>
- const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL4_MAX_RELATIVE_ERROR = 25;
+ positive_sum_ /= -val;
+ negative_sum_ /= -val;
+ swap();
+ }
+ return *this;
+ }
+
+private:
+ void swap() {
+ (std::swap)(positive_sum_, negative_sum_);
+ }
+
+ T positive_sum_;
+ T negative_sum_;
+};
+
+template<typename T>
+robust_dif<T> operator+(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ return robust_dif<T>(lhs.pos() + rhs.pos(),
+ lhs.neg() + rhs.neg());
+}
+
+template<typename T>
+robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
+ if (!is_neg(rhs)) {
+ return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
+ } else {
+ return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
+ if (!is_neg(lhs)) {
+ return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
+ } else {
+ return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator-(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
+}
+
+template<typename T>
+robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
+ if (!is_neg(rhs)) {
+ return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
+ } else {
+ return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
+ }
+}
+
+template<typename T>
+robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
+ if (!is_neg(lhs)) {
+ return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
+ } else {
+ return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator*(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
+ T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
+ return robust_dif<T>(res_pos, res_neg);
+}
+
+template<typename T>
+robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
+ } else {
+ return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
+ } else {
+ return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
+ }
+}
+
+template<typename T>
+robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
+ } else {
+ return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
+ }
+}
+
+// Used to compute expressions that operate with sqrts with predefined
+// relative error. Evaluates expressions of the next type:
+// sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4.
+template <typename _int, typename _fpt, typename _converter>
+class robust_sqrt_expr {
+public:
+ static const unsigned int EVAL1_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL2_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL3_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL4_MAX_RELATIVE_ERROR;
+
+ // Evaluates expression (re = 4 EPS):
+ // A[0] * sqrt(B[0]).
+ _fpt eval1(_int *A, _int *B) {
+ _fpt a = convert(A[0]);
+ _fpt b = convert(B[0]);
+ return a * get_sqrt(b);
+ }
+
+ // Evaluates expression (re = 7 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]).
+ _fpt eval2(_int *A, _int *B) {
+ _fpt a = eval1(A, B);
+ _fpt b = eval1(A + 1, B + 1);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
+ }
+
+ // Evaluates expression (re = 16 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]).
+ _fpt eval3(_int *A, _int *B) {
+ _fpt a = eval2(A, B);
+ _fpt b = eval1(A + 2, B + 2);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
+ tB[3] = 1;
+ tA[4] = A[0] * A[1] * 2;
+ tB[4] = B[0] * B[1];
+ return eval2(tA + 3, tB + 3) / (a - b);
+ }
+
+
+ // Evaluates expression (re = 25 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
+ // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]).
+ _fpt eval4(_int *A, _int *B) {
+ _fpt a = eval2(A, B);
+ _fpt b = eval2(A + 2, B + 2);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
+ A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
+ tB[0] = 1;
+ tA[1] = A[0] * A[1] * 2;
+ tB[1] = B[0] * B[1];
+ tA[2] = A[2] * A[3] * -2;
+ tB[2] = B[2] * B[3];
+ return eval3(tA, tB) / (a - b);
+ }
+
+private:
+ _int tA[5];
+ _int tB[5];
+ _converter convert;
+};
+
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL1_MAX_RELATIVE_ERROR = 4;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL2_MAX_RELATIVE_ERROR = 7;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL3_MAX_RELATIVE_ERROR = 16;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL4_MAX_RELATIVE_ERROR = 25;
 } // detail
 } // polygon
 } // boost

Modified: sandbox/gtl/boost/polygon/detail/voronoi_structures.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/detail/voronoi_structures.hpp (original)
+++ sandbox/gtl/boost/polygon/detail/voronoi_structures.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,14 +1,14 @@
 // Boost.Polygon library detail/voronoi_structures.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
 // See http://www.boost.org for updates, documentation, and revision history.
 
-#ifndef BOOST_POLYGON_VORONOI_STRUCTURES
-#define BOOST_POLYGON_VORONOI_STRUCTURES
+#ifndef BOOST_POLYGON_VORONOI_DETAIL_STRUCTURES
+#define BOOST_POLYGON_VORONOI_DETAIL_STRUCTURES
 
 #include <list>
 #include <queue>

Modified: sandbox/gtl/boost/polygon/voronoi.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/voronoi.hpp (original)
+++ sandbox/gtl/boost/polygon/voronoi.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,6 +1,6 @@
 // Boost.Polygon library voronoi.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -10,7 +10,6 @@
 #ifndef BOOST_POLYGON_VORONOI
 #define BOOST_POLYGON_VORONOI
 
-#include "polygon.hpp"
 #include "voronoi_builder.hpp"
 #include "voronoi_diagram.hpp"
 
@@ -26,28 +25,28 @@
     // the signed integer range [-2^31, 2^31-1].
     // Complexity - O(N*logN), memory usage - O(N), where N is the total
     // number of points and segments.
- template <typename T, typename PC, typename VD>
+ template <typename PC, typename VD>
     static inline void construct_voronoi_points(
- const PC &points, VD &output) {
- voronoi_builder<T, VD> builder;
+ const PC &points, VD *output) {
+ default_voronoi_builder builder;
         builder.insert_points(points.begin(), points.end());
         builder.construct(output);
         builder.clear();
     }
 
- template <typename T, typename SC, typename VD>
+ template <typename SC, typename VD>
     static inline void construct_voronoi_segments(
- const SC &segments, VD &output) {
- voronoi_builder<T, VD> builder;
+ const SC &segments, VD *output) {
+ default_voronoi_builder builder;
         builder.insert_segments(segments.begin(), segments.end());
         builder.construct(output);
         builder.clear();
     }
 
- template <typename T, typename PC, typename SC, typename VD>
+ template <typename PC, typename SC, typename VD>
     static inline void construct_voronoi(
- const PC &points, const SC &segments, VD &output) {
- voronoi_builder<T, VD> builder;
+ const PC &points, const SC &segments, VD *output) {
+ default_voronoi_builder builder;
         builder.insert_sites(points.begin(), points.end(),
                              segments.begin(), segments.end());
         builder.construct(output);

Modified: sandbox/gtl/boost/polygon/voronoi_builder.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/voronoi_builder.hpp (original)
+++ sandbox/gtl/boost/polygon/voronoi_builder.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,6 +1,6 @@
 // Boost.Polygon library voronoi_builder.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -14,8 +14,7 @@
 #include <map>
 #include <vector>
 
-#include "polygon.hpp"
-
+#include "detail/voronoi_ctypes.hpp"
 #include "detail/voronoi_predicates.hpp"
 #include "detail/voronoi_structures.hpp"
 
@@ -61,11 +60,11 @@
     // defined comparison functor is used to make the beach line correctly
     // ordered. Epsilon-based and high-precision approaches are used to guarantee
     // efficiency and robustness of the algorithm implementation.
- template <typename T, typename VD>
+ template <typename T,
+ typename CTT = detail::voronoi_ctype_traits<T>,
+ typename VP = detail::voronoi_predicates<CTT> >
     class voronoi_builder {
     public:
- typedef VD output_type;
-
         voronoi_builder() {}
 
         template <typename PointIterator>
@@ -108,13 +107,12 @@
         }
 
         // Run the sweepline algorithm.
- void construct(output_type &output) {
+ template <typename OUTPUT>
+ void construct(OUTPUT *output) {
             // Init structures.
- output_ = &output;
- output_->clear();
- output_->reserve(site_events_.size());
+ output->reserve(site_events_.size());
             init_sites_queue();
- init_beach_line();
+ init_beach_line(output);
 
             // The algorithm stops when there are no events to process.
             // The circle events with the same rightmost point as the next
@@ -123,14 +121,14 @@
             while (!circle_events_.empty() ||
                    !(site_event_iterator_ == site_events_.end())) {
                 if (circle_events_.empty()) {
- process_site_event();
+ process_site_event(output);
                 } else if (site_event_iterator_ == site_events_.end()) {
- process_circle_event();
+ process_circle_event(output);
                 } else {
                     if (event_comparison(*site_event_iterator_, circle_events_.top().first)) {
- process_site_event();
+ process_site_event(output);
                     } else {
- process_circle_event();
+ process_circle_event(output);
                     }
                 }
                 while (!circle_events_.empty() && !circle_events_.top().first.is_active()) {
@@ -141,7 +139,7 @@
             beach_line_.clear();
 
             // Clean the output (remove zero-length edges).
- output_->clean();
+ output->clean();
         }
 
         void clear() {
@@ -149,9 +147,8 @@
         }
 
     private:
- typedef detail::voronoi_predicates<T> VP;
- typedef typename VP::int_type int_type;
- typedef typename VP::fpt_type fpt_type;
+ typedef typename CTT::int_type int_type;
+ typedef typename CTT::fpt_type fpt_type;
 
         typedef detail::point_2d<int_type> point_type;
         typedef detail::site_event<int_type> site_event_type;
@@ -166,7 +163,7 @@
         typedef typename VP::
             template circle_formation_predicate<site_event_type, circle_event_type>
             circle_formation_predicate_type;
- typedef typename output_type::voronoi_edge_type edge_type;
+ typedef void edge_type;
         typedef detail::beach_line_node_key<site_event_type> key_type;
         typedef detail::beach_line_node_data<edge_type, circle_event_type> value_type;
         typedef typename VP::
@@ -204,11 +201,12 @@
             site_event_iterator_ = site_events_.begin();
         }
 
- void init_beach_line() {
+ template <typename OUTPUT>
+ void init_beach_line(OUTPUT *output) {
             if (site_events_.empty()) return;
             if (site_events_.size() == 1) {
                 // Handle one input site case.
- output_->process_single_site(site_events_[0]);
+ output->process_single_site(site_events_[0]);
                 ++site_event_iterator_;
             } else {
                 int skip = 0;
@@ -224,26 +222,28 @@
 
                 if (skip == 1) {
                     // Init the beach line with the two first sites.
- init_beach_line_default();
+ init_beach_line_default(output);
                 } else {
                     // Init the beach line with the sites situated on the same
                     // vertical line. This could be a set of point and vertical
                     // segment sites.
- init_beach_line_collinear_sites();
+ init_beach_line_collinear_sites(output);
                 }
             }
         }
 
         // Init the beach line with the two first sites.
         // The first site is always a point.
- void init_beach_line_default() {
+ template <typename OUTPUT>
+ void init_beach_line_default(OUTPUT *output) {
             // Get the first and the second site events.
             site_event_iterator_type it_first = site_events_.begin();
             site_event_iterator_type it_second = site_events_.begin();
             ++it_second;
 
             // Update the beach line.
- insert_new_arc(*it_first, *it_first, *it_second, beach_line_.begin());
+ insert_new_arc(*it_first, *it_first, *it_second,
+ beach_line_.begin(), output);
 
             // The second site has been already processed.
             // Move the site's iterator.
@@ -251,7 +251,8 @@
         }
 
         // Insert bisectors for all collinear initial sites.
- void init_beach_line_collinear_sites() {
+ template <typename OUTPUT>
+ void init_beach_line_collinear_sites(OUTPUT *output) {
              site_event_iterator_type it_first = site_events_.begin();
              site_event_iterator_type it_second = site_events_.begin();
              ++it_second;
@@ -260,7 +261,7 @@
                  key_type new_node(*it_first, *it_second);
 
                  // Update the output.
- edge_type *edge = output_->insert_new_edge(*it_first, *it_second);
+ edge_type *edge = output->insert_new_edge(*it_first, *it_second).first;
 
                  // Insert a new bisector into the beach line.
                  beach_line_.insert(
@@ -279,7 +280,8 @@
             }
         }
 
- void process_site_event() {
+ template <typename OUTPUT>
+ void process_site_event(OUTPUT *output) {
             // Get the site event to process.
             site_event_type site_event = *site_event_iterator_;
 
@@ -324,7 +326,7 @@
 
                     // Insert new nodes into the beach line. Update the output.
                     beach_line_iterator new_node_it =
- insert_new_arc(site_arc, site_arc, site_event, it);
+ insert_new_arc(site_arc, site_arc, site_event, it, output);
 
                     // Add a candidate circle to the circle event queue.
                     // There could be only one new circle event formed by
@@ -338,7 +340,7 @@
                     const site_event_type &site_arc = it->first.left_site();
 
                     // Insert new nodes into the beach line. Update the output.
- insert_new_arc(site_arc, site_arc, site_event, it);
+ insert_new_arc(site_arc, site_arc, site_event, it, output);
 
                     // If the site event is a segment, update its direction.
                     if (site_event.is_segment()) {
@@ -364,7 +366,7 @@
 
                     // Insert new nodes into the beach line. Update the output.
                     beach_line_iterator new_node_it =
- insert_new_arc(site_arc1, site_arc2, site_event, it);
+ insert_new_arc(site_arc1, site_arc2, site_event, it, output);
 
                     // Add candidate circles to the circle event queue.
                     // There could be up to two circle events formed by
@@ -393,7 +395,8 @@
         // (B, C) bisector and change (A, B) bisector to the (A, C). That's
         // why we use const_cast there and take all the responsibility that
         // map data structure keeps correct ordering.
- void process_circle_event() {
+ template <typename OUTPUT>
+ void process_circle_event(OUTPUT *output) {
             // Get the topmost circle event.
             const event_type &e = circle_events_.top();
             const circle_event_type &circle_event = e.first;
@@ -422,8 +425,8 @@
             const_cast<key_type &>(it_first->first).right_site(site3);
 
             // Insert the new bisector into the beach line.
- it_first->second.edge(output_->insert_new_edge(site1, site3, circle_event,
- bisector1, bisector2));
+ it_first->second.edge(output->insert_new_edge(site1, site3, circle_event,
+ bisector1, bisector2));
 
             // Remove the (B, C) bisector node from the beach line.
             beach_line_.erase(it_last);
@@ -452,10 +455,12 @@
         }
 
         // Insert new nodes into the beach line. Update the output.
+ template <typename OUTPUT>
         beach_line_iterator insert_new_arc(const site_event_type &site_arc1,
                                            const site_event_type &site_arc2,
                                            const site_event_type &site_event,
- const beach_line_iterator &position) {
+ const beach_line_iterator &position,
+ OUTPUT *output) {
             // Create two new bisectors with opposite directions.
             key_type new_left_node(site_arc1, site_event);
             key_type new_right_node(site_event, site_arc2);
@@ -466,9 +471,10 @@
             }
 
             // Update the output.
- edge_type *edge = output_->insert_new_edge(site_arc2, site_event);
+ std::pair<edge_type*, edge_type*> edges =
+ output->insert_new_edge(site_arc2, site_event);
             beach_line_iterator it = beach_line_.insert(position,
- typename beach_line_type::value_type(new_right_node, value_type(edge->twin())));
+ beach_line_type::value_type(new_right_node, value_type(edges.second)));
 
             if (site_event.is_segment()) {
                 // Update the beach line with temporary bisector, that will
@@ -484,7 +490,7 @@
             }
 
             beach_line_.insert(position,
- typename beach_line_type::value_type(new_left_node, value_type(edge)));
+ typename beach_line_type::value_type(new_left_node, value_type(edges.first)));
             return it;
         }
 
@@ -520,13 +526,14 @@
                              end_point_comparison > end_points_;
         circle_event_queue_type circle_events_;
         beach_line_type beach_line_;
- output_type *output_;
         circle_formation_predicate_type circle_formation_predicate_;
 
         //Disallow copy constructor and operator=
         voronoi_builder(const voronoi_builder&);
         void operator=(const voronoi_builder&);
     };
+
+ typedef voronoi_builder<detail::int32> default_voronoi_builder;
 } // polygon
 } // boost
 

Modified: sandbox/gtl/boost/polygon/voronoi_diagram.hpp
==============================================================================
--- sandbox/gtl/boost/polygon/voronoi_diagram.hpp (original)
+++ sandbox/gtl/boost/polygon/voronoi_diagram.hpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,6 +1,6 @@
 // Boost.Polygon library voronoi_diagram.hpp header file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -846,8 +846,8 @@
         // Takes as input left and right sites that form a new bisector.
         // Returns a pointer to a new half-edge.
         template <typename SEvent>
- voronoi_edge_type *insert_new_edge(const SEvent &site1,
- const SEvent &site2) {
+ std::pair<void*, void*> insert_new_edge(const SEvent &site1,
+ const SEvent &site2) {
             // Get sites' indices.
             int site_index1 = site1.index();
             int site_index2 = site2.index();
@@ -892,7 +892,7 @@
             edge2.twin(&edge1);
 
             // Return a pointer to the new half-edge.
- return &edge1;
+ return std::make_pair(&edge1, &edge2);
         }
 
         // Insert a new half-edge into the output data structure with the
@@ -902,11 +902,14 @@
         // pointers to those half-edges. Half-edges' direction goes out of the
         // new voronoi vertex point. Returns a pointer to the new half-edge.
         template <typename SEvent, typename CEvent>
- voronoi_edge_type *insert_new_edge(const SEvent &site1,
- const SEvent &site3,
- const CEvent &circle,
- voronoi_edge_type *edge12,
- voronoi_edge_type *edge23) {
+ void *insert_new_edge(const SEvent &site1,
+ const SEvent &site3,
+ const CEvent &circle,
+ void *data12,
+ void *data23) {
+ voronoi_edge_type *edge12 = static_cast<voronoi_edge_type*>(data12);
+ voronoi_edge_type *edge23 = static_cast<voronoi_edge_type*>(data23);
+
             // Add a new voronoi vertex.
             vertex_records_.push_back(voronoi_vertex_type(
                 point_type(circle.x(), circle.y()), edge12));

Modified: sandbox/gtl/libs/polygon/test/voronoi_benchmark_test.cpp
==============================================================================
--- sandbox/gtl/libs/polygon/test/voronoi_benchmark_test.cpp (original)
+++ sandbox/gtl/libs/polygon/test/voronoi_benchmark_test.cpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,6 +1,6 @@
 // Boost.Polygon library voronoi_benchmark_test.cpp file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -55,12 +55,13 @@
         timer.restart();
         int num_tests = max_points / num_points;
         for (int cur = 0; cur < num_tests; cur++) {
+ test_output.clear();
             for (int cur_point = 0; cur_point < num_points; cur_point++) {
                 x = static_cast<coordinate_type>(gen());
                 y = static_cast<coordinate_type>(gen());
                 points[cur_point] = point_type(x, y);
             }
- construct_voronoi_points<coordinate_type>(points, test_output);
+ construct_voronoi_points(points, &test_output);
         }
         double elapsed_time = timer.elapsed();
         double time_per_test = elapsed_time / num_tests;
@@ -97,7 +98,7 @@
         for (int i = 0; i < POINT_RUNS; ++i) {
             voronoi_diagram<double> test_output;
             timer.restart();
- construct_voronoi_points<coordinate_type>(points, test_output);
+ construct_voronoi_points(points, &test_output);
             periods.push_back(timer.elapsed());
         }
     }
@@ -137,7 +138,7 @@
         for (int i = 0; i < SEGMENT_RUNS; ++i) {
             voronoi_diagram<double> test_output;
             timer.restart();
- construct_voronoi_segments<coordinate_type>(segments, test_output);
+ construct_voronoi_segments(segments, &test_output);
             periods.push_back(timer.elapsed());
         }
     }

Modified: sandbox/gtl/libs/polygon/voronoi_example/voronoi_visualizer.cpp
==============================================================================
--- sandbox/gtl/libs/polygon/voronoi_example/voronoi_visualizer.cpp (original)
+++ sandbox/gtl/libs/polygon/voronoi_example/voronoi_visualizer.cpp 2012-01-23 17:22:43 EST (Mon, 23 Jan 2012)
@@ -1,6 +1,6 @@
 // Boost.Polygon library voronoi_visualizer.cpp file
 
-// Copyright Andrii Sydorchuk 2010-2011.
+// Copyright Andrii Sydorchuk 2010-2012.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
@@ -57,7 +57,8 @@
         in_stream.flush();
 
         // Build voronoi diagram.
- construct_voronoi<int>(point_sites, segment_sites, vd_);
+ vd_.clear();
+ construct_voronoi(point_sites, segment_sites, &vd_);
         brect_ = voronoi_helper<coordinate_type>::get_view_rectangle(
             vd_.bounding_rectangle());
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk