test_pie/external/exact_ccd/expansion.h

232 lines
4.3 KiB
C++

#ifndef EXPANSION_H
#define EXPANSION_H
// Released into the public-domain by Robert Bridson, 2009.
// Modified by Tyson Brochu, 2011.
// Simple functions for manipulating multiprecision floating-point
// expansions, with simplicity favoured over speed.
#include <vector>
// The basic type is essentially a vector of *increasing* and
// *nonoverlapping* doubles, apart from allowed zeroes anywhere.
namespace CCD
{
class expansion;
void negative(const expansion& input, expansion& output);
int sign( const expansion& a );
bool
is_zero( const expansion& a );
void
add(double a, double b, expansion& sum);
// a and sum may be aliased to the same expansion for in-place addition
void
add(const expansion& a, double b, expansion& sum);
inline void
add(double a, const expansion& b, expansion& sum)
{ add(b, a, sum); }
// aliasing a, b and sum is safe
void
add(const expansion& a, const expansion& b, expansion& sum);
void
subtract( const double& a, const double& b, expansion& difference);
// aliasing a, b and difference is safe
void
subtract(const expansion& a, const expansion& b, expansion& difference);
// aliasing input and output is safe
void
negative(const expansion& input, expansion& output);
void
multiply(double a, double b, expansion& product);
void
multiply(double a, double b, double c, expansion& product);
void
multiply(double a, double b, double c, double d, expansion& product);
void
multiply(const expansion& a, double b, expansion& product);
inline void
multiply(double a, const expansion& b, expansion& product)
{ multiply(b, a, product); }
// Aliasing NOT safe
void
multiply(const expansion& a, const expansion& b, expansion& product);
void compress( const expansion& e, expansion& h );
// Aliasing NOT safe
bool divide( const expansion& x, const expansion& y, expansion& q );
void
remove_zeros(expansion& a);
double
estimate(const expansion& a);
bool equals( const expansion& a, const expansion& b );
void
print_full( const expansion& e );
// ----------------------------------------------------
class expansion
{
public:
std::vector<double> v;
expansion()
: v(0)
{}
explicit expansion( double val )
: v(1, val)
{}
expansion( std::size_t n, double val )
: v(n,val)
{}
virtual ~expansion() {}
expansion& operator+=(const expansion &rhs)
{
add( *this, rhs, *this );
return *this;
}
expansion& operator-=(const expansion &rhs)
{
subtract( *this, rhs, *this );
return *this;
}
expansion& operator*=(const expansion &rhs)
{
expansion p;
multiply( *this, rhs, p );
*this = p;
return *this;
}
inline expansion operator+(const expansion &other) const
{
expansion result = *this;
result += other;
return result;
}
inline expansion operator-(const expansion &other) const
{
expansion result = *this;
result -= other;
return result;
}
inline expansion operator*(const expansion &other) const
{
expansion result = *this;
result *= other;
return result;
}
inline expansion operator-( ) const
{
expansion result;
negative( *this, result );
return result;
}
bool is_certainly_negative() const{
return sign(*this) < 0;
}
bool is_certainly_positive() const{
return sign(*this) > 0;
}
bool is_certainly_zero() const{
return is_zero(*this);
}
bool same_sign(const expansion& b) const{
return sign(*this) == sign(b);
}
inline double estimate() const
{
return CCD::estimate( *this );
}
inline bool indefinite_sign() const
{
return false;
}
static void begin_special_arithmetic()
{}
static void end_special_arithmetic()
{}
inline void clear()
{
v.clear();
}
inline void resize( std::size_t new_size )
{
v.resize(new_size);
}
};
inline void make_expansion( double a, expansion& e )
{
if(a)
{
e = expansion(1, a);
}
else
{
e.clear();
}
}
inline void
make_zero(expansion& e)
{ e.resize(0); }
inline void create_from_double( double a, expansion& out )
{
make_expansion( a, out );
}
inline bool certainly_opposite_sign( const expansion& a, const expansion& b )
{
return ( sign(a) > 0 && sign(b) < 0 ) || ( sign(a) < 0 && sign(b) > 0 );
}
}
#endif