Initial commit

This commit is contained in:
Bassem Girgis
2018-12-20 17:34:07 -06:00
parent 7a2d899662
commit 81b4b9e273
34743 changed files with 5940233 additions and 0 deletions

View File

@@ -0,0 +1,583 @@
// fp_traits.hpp
#ifndef BOOST_SPIRIT_MATH_FP_TRAITS_HPP
#define BOOST_SPIRIT_MATH_FP_TRAITS_HPP
// Copyright (c) 2006 Johan Rade
// 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)
#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT
# error The VAX floating point mode on VMS is not supported.
#endif
#if defined(_MSC_VER)
#pragma once
#endif
#include <cstring>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/detail/endian.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_floating_point.hpp>
//------------------------------------------------------------------------------
namespace boost {
namespace spirit {
namespace math {
namespace detail {
//------------------------------------------------------------------------------
/*
Most processors support three different floating point precisions:
single precision (32 bits), double precision (64 bits)
and extended double precision (>64 bits)
Note that the C++ type long double can be implemented
both as double precision and extended double precision.
*/
struct single_precision_tag {};
struct double_precision_tag {};
struct extended_double_precision_tag {};
//------------------------------------------------------------------------------
/*
template<class T, class U> struct fp_traits_impl;
This is traits class that describes the binary structure of floating
point numbers of C++ type T and precision U
Requirements:
T = float, double or long double
U = single_precision_tag, double_precision_tag
or extended_double_precision_tag
Typedef members:
bits -- the target type when copying the leading bytes of a floating
point number. It is a typedef for uint32_t or uint64_t.
coverage -- tells us whether all bytes are copied or not.
It is a typedef for all_bits or not_all_bits.
Static data members:
sign, exponent, flag, mantissa -- bit masks that give the meaning of the bits
in the leading bytes.
Static function members:
init() -- initializes the static data members, if needed.
(Is a no-op in the specialized versions of the template.)
get_bits(), set_bits() -- provide access to the leading bytes.
*/
struct all_bits {};
struct not_all_bits {};
// Generic version -------------------------------------------------------------
// The generic version uses run time initialization to determine the floating
// point format. It is capable of handling most formats,
// but not the Motorola 68K extended double precision format.
// Currently the generic version is used only for extended double precision
// on Itanium. In all other cases there are specializations of the template
// that use compile time initialization.
template<class T> struct uint32_t_coverage
{
typedef not_all_bits type;
};
template<> struct uint32_t_coverage<single_precision_tag>
{
typedef all_bits type;
};
template<class T, class U> struct fp_traits_impl
{
typedef uint32_t bits;
typedef BOOST_DEDUCED_TYPENAME uint32_t_coverage<U>::type coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
static uint32_t exponent;
static uint32_t flag;
static uint32_t mantissa;
static void init()
{
if(is_init_) return;
do_init_();
is_init_ = true;
}
static void get_bits(T x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
}
static void set_bits(T& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
}
private:
static size_t offset_;
static bool is_init_;
static void do_init_();
};
//..............................................................................
template<class T, class U> uint32_t fp_traits_impl<T,U>::exponent;
template<class T, class U> uint32_t fp_traits_impl<T,U>::flag;
template<class T, class U> uint32_t fp_traits_impl<T,U>::mantissa;
template<class T, class U> size_t fp_traits_impl<T,U>::offset_;
template<class T, class U> bool fp_traits_impl<T,U>::is_init_;
// In a single-threaded program, do_init will be called exactly once.
// In a multi-threaded program, do_init may be called simultaneously
// by more then one thread. That should not be a problem.
//..............................................................................
template<class T, class U> void fp_traits_impl<T,U>::do_init_()
{
T x = static_cast<T>(3) / static_cast<T>(4);
// sign bit = 0
// exponent: first and last bit = 0, all other bits = 1
// flag bit (if present) = 1
// mantissa: first bit = 1, all other bits = 0
uint32_t a;
for(size_t k = 0; k <= sizeof(T) - 4; ++k) {
memcpy(&a, reinterpret_cast<unsigned char*>(&x) + k, 4);
switch(a) {
case 0x3f400000: // IEEE single precision format
offset_ = k;
exponent = 0x7f800000;
flag = 0x00000000;
mantissa = 0x007fffff;
return;
case 0x3fe80000: // IEEE double precision format
// and PowerPC extended double precision format
offset_ = k;
exponent = 0x7ff00000;
flag = 0x00000000;
mantissa = 0x000fffff;
return;
case 0x3ffe0000: // Motorola extended double precision format
// Must not get here. Must be handled by specialization.
// To get accurate cutoff between normals and subnormals
// we must use the flag bit that is in the 5th byte.
// Otherwise this cutoff will be off by a factor 2.
// If we do get here, then we have failed to detect the Motorola
// processor at compile time.
BOOST_ASSERT(false &&
"Failed to detect the Motorola processor at compile time");
return;
case 0x3ffe8000: // IEEE extended double precision format
// with 15 exponent bits
offset_ = k;
exponent = 0x7fff0000;
flag = 0x00000000;
mantissa = 0x0000ffff;
return;
case 0x3ffec000: // Intel extended double precision format
offset_ = k;
exponent = 0x7fff0000;
flag = 0x00008000;
mantissa = 0x00007fff;
return;
default:
continue;
}
}
BOOST_ASSERT(false);
// Unknown format.
}
// float (32 bits) -------------------------------------------------------------
template<> struct fp_traits_impl<float, single_precision_tag>
{
typedef uint32_t bits;
typedef all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x007fffff);
static void init() {}
static void get_bits(float x, uint32_t& a) { memcpy(&a, &x, 4); }
static void set_bits(float& x, uint32_t a) { memcpy(&x, &a, 4); }
};
// double (64 bits) ------------------------------------------------------------
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
template<> struct fp_traits_impl<double, double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
static void init() {}
static void get_bits(double x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
}
static void set_bits(double& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
}
private:
#if defined(BOOST_BIG_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 0);
#elif defined(BOOST_LITTLE_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 4);
#else
BOOST_STATIC_ASSERT(false);
#endif
};
//..............................................................................
#else
template<> struct fp_traits_impl<double, double_precision_tag>
{
typedef uint64_t bits;
typedef all_bits coverage;
static const uint64_t sign = (uint64_t)0x80000000 << 32;
static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
static const uint64_t flag = 0;
static const uint64_t mantissa
= ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff;
static void init() {}
static void get_bits(double x, uint64_t& a) { memcpy(&a, &x, 8); }
static void set_bits(double& x, uint64_t a) { memcpy(&x, &a, 8); }
};
#endif
// long double (64 bits) -------------------------------------------------------
#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
template<> struct fp_traits_impl<long double, double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
static void init() {}
static void get_bits(long double x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
}
static void set_bits(long double& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
}
private:
#if defined(BOOST_BIG_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 0);
#elif defined(BOOST_LITTLE_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 4);
#else
BOOST_STATIC_ASSERT(false);
#endif
};
//..............................................................................
#else
template<> struct fp_traits_impl<long double, double_precision_tag>
{
typedef uint64_t bits;
typedef all_bits coverage;
static const uint64_t sign = (uint64_t)0x80000000 << 32;
static const uint64_t exponent = (uint64_t)0x7ff00000 << 32;
static const uint64_t flag = 0;
static const uint64_t mantissa
= ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff;
static void init() {}
static void get_bits(long double x, uint64_t& a) { memcpy(&a, &x, 8); }
static void set_bits(long double& x, uint64_t a) { memcpy(&x, &a, 8); }
};
#endif
// long double (>64 bits), x86 and x64 -----------------------------------------
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \
|| defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \
|| defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
// Intel extended double precision format (80 bits)
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff);
static void init() {}
static void get_bits(long double x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4);
}
static void set_bits(long double& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4);
}
};
// long double (>64 bits), Itanium ---------------------------------------------
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
// The floating point format is unknown at compile time
// No template specialization is provided.
// The generic definition is used.
// The Itanium supports both
// the Intel extended double precision format (80 bits) and
// the IEEE extended double precision format with 15 exponent bits (128 bits).
// long double (>64 bits), PowerPC ---------------------------------------------
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \
|| defined(__ppc) || defined(__ppc__) || defined(__PPC__)
// PowerPC extended double precision format (128 bits)
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff);
static void init() {}
static void get_bits(long double x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
}
static void set_bits(long double& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
}
private:
#if defined(BOOST_BIG_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 0);
#elif defined(BOOST_LITTLE_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 12);
#else
BOOST_STATIC_ASSERT(false);
#endif
};
// long double (>64 bits), Motorola 68K ----------------------------------------
#elif defined(__m68k) || defined(__m68k__) \
|| defined(__mc68000) || defined(__mc68000__) \
// Motorola extended double precision format (96 bits)
// It is the same format as the Intel extended double precision format,
// except that 1) it is big-endian, 2) the 3rd and 4th byte are padding, and
// 3) the flag bit is not set for infinity
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff);
static void init() {}
// copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding.
static void get_bits(long double x, uint32_t& a)
{
memcpy(&a, &x, 2);
memcpy(reinterpret_cast<unsigned char*>(&a) + 2,
reinterpret_cast<const unsigned char*>(&x) + 4, 2);
}
static void set_bits(long double& x, uint32_t a)
{
memcpy(&x, &a, 2);
memcpy(reinterpret_cast<unsigned char*>(&x) + 4,
reinterpret_cast<const unsigned char*>(&a) + 2, 2);
}
};
// long double (>64 bits), All other processors --------------------------------
#else
// IEEE extended double precision format with 15 exponent bits (128 bits)
template<> struct fp_traits_impl<long double, extended_double_precision_tag>
{
typedef uint32_t bits;
typedef not_all_bits coverage;
BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000);
BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000);
BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000);
BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x0000ffff);
static void init() {}
static void get_bits(long double x, uint32_t& a)
{
memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4);
}
static void set_bits(long double& x, uint32_t a)
{
memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4);
}
private:
#if defined(BOOST_BIG_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 0);
#elif defined(BOOST_LITTLE_ENDIAN)
BOOST_STATIC_CONSTANT(int, offset_ = 12);
#else
BOOST_STATIC_ASSERT(false);
#endif
};
#endif
//------------------------------------------------------------------------------
// size_to_precision is a type switch for converting a C++ floating point type
// to the corresponding precision type.
template<int n> struct size_to_precision;
template<> struct size_to_precision<4>
{
typedef single_precision_tag type;
};
template<> struct size_to_precision<8>
{
typedef double_precision_tag type;
};
template<> struct size_to_precision<10>
{
typedef extended_double_precision_tag type;
};
template<> struct size_to_precision<12>
{
typedef extended_double_precision_tag type;
};
template<> struct size_to_precision<16>
{
typedef extended_double_precision_tag type;
};
// fp_traits is a type switch that selects the right fp_traits_impl
template<class T> struct fp_traits
{
BOOST_STATIC_ASSERT(boost::is_floating_point<T>::value);
typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T)>::type precision;
typedef fp_traits_impl<T, precision> type;
};
//------------------------------------------------------------------------------
} // namespace detail
} // namespace math
} // namespace spirit
} // namespace boost
#endif

View File

@@ -0,0 +1,235 @@
// fpclassify.hpp
#ifndef BOOST_SPIRIT_MATH_FPCLASSIFY_HPP
#define BOOST_SPIRIT_MATH_FPCLASSIFY_HPP
// Copyright (c) 2006 Johan Rade
// 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)
/*
The following algorithm is used:
If all exponent bits, the flag bit (if there is one),
and all mantissa bits are 0, then the number is zero.
If all exponent bits and the flag bit (if there is one) are 0,
and at least one mantissa bit is 1, then the number is subnormal.
If all exponent bits are 1 and all mantissa bits are 0,
then the number is infinity.
If all exponent bits are 1 and at least one mantissa bit is 1,
then the number is a not-a-number.
Otherwise the number is normal.
(Note that the binary representation of infinity
has flag bit 0 for Motorola 68K extended double precision,
and flag bit 1 for Intel extended double precision.)
To get the bits, the four or eight most significant bytes are copied
into an uint32_t or uint64_t and bit masks are applied.
This covers all the exponent bits and the flag bit (if there is one),
but not always all the mantissa bits.
Some of the functions below have two implementations,
depending on whether all the mantissa bits are copied or not.
*/
#if defined(_MSC_VER)
#pragma once
#endif
#include <cmath>
#ifndef FP_INFINITE
# define FP_INFINITE 0
# define FP_NAN 1
# define FP_NORMAL 2
# define FP_SUBNORMAL 3
# define FP_ZERO 4
#endif
#include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp>
namespace boost {
namespace spirit {
namespace math {
//------------------------------------------------------------------------------
template<class T> bool (isfinite)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent;
return a != traits::exponent;
}
//------------------------------------------------------------------------------
template<class T> bool (isnormal)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::flag;
return (a != 0) && (a < traits::exponent);
}
//------------------------------------------------------------------------------
namespace detail {
template<class T> bool isinf_impl(T x, all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::mantissa;
return a == traits::exponent;
}
template<class T> bool isinf_impl(T x, not_all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::mantissa;
if(a != traits::exponent)
return false;
traits::set_bits(x,0);
return x == 0;
}
} // namespace detail
template<class T> bool (isinf)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
return detail::isinf_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
}
//------------------------------------------------------------------------------
namespace detail {
template<class T> bool isnan_impl(T x, all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::mantissa;
return a > traits::exponent;
}
template<class T> bool isnan_impl(T x, not_all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::mantissa;
if(a < traits::exponent)
return false;
a &= traits::mantissa;
traits::set_bits(x,a);
return x != 0;
}
} // namespace detail
template<class T> bool (isnan)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
return detail::isnan_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
}
//------------------------------------------------------------------------------
namespace detail {
template<class T> int fpclassify_impl(T x, all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::flag | traits::mantissa;
if(a <= traits::mantissa) {
if(a == 0)
return FP_ZERO;
else
return FP_SUBNORMAL;
}
if(a < traits::exponent)
return FP_NORMAL;
a &= traits::mantissa;
if(a == 0)
return FP_INFINITE;
return FP_NAN;
}
template<class T> int fpclassify_impl(T x, not_all_bits)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::exponent | traits::flag | traits::mantissa;
if(a <= traits::mantissa) {
if(x == 0)
return FP_ZERO;
else
return FP_SUBNORMAL;
}
if(a < traits::exponent)
return FP_NORMAL;
a &= traits::mantissa;
traits::set_bits(x,a);
if(x == 0)
return FP_INFINITE;
return FP_NAN;
}
} // namespace detail
template<class T> int (fpclassify)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
return detail::fpclassify_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage());
}
//------------------------------------------------------------------------------
} // namespace math
} // namespace spirit
} // namespace boost
#endif

View File

@@ -0,0 +1,92 @@
// signbit.hpp
#ifndef BOOST_SPIRIT_MATH_SIGNBIT_HPP
#define BOOST_SPIRIT_MATH_SIGNBIT_HPP
// Copyright (c) 2006 Johan Rade
// 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)
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp>
namespace boost {
namespace spirit {
namespace math {
//------------------------------------------------------------------------------
template<class T> bool (signbit)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= traits::sign;
return a != 0;
}
//------------------------------------------------------------------------------
namespace detail {
template<class T> T copysign_impl(T x, T y)
{
typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a &= ~traits::sign;
BOOST_DEDUCED_TYPENAME traits::bits b;
traits::get_bits(y,b);
b &= traits::sign;
traits::set_bits(x,a|b);
return x;
}
}
inline float (copysign)(float x, float y) // magnitude of x and sign of y
{
return detail::copysign_impl(x,y);
}
inline double (copysign)(double x, double y)
{
return detail::copysign_impl(x,y);
}
inline long double (copysign)(long double x, long double y)
{
return detail::copysign_impl(x,y);
}
//------------------------------------------------------------------------------
template<class T> T (changesign)(T x)
{
typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits;
traits::init();
BOOST_DEDUCED_TYPENAME traits::bits a;
traits::get_bits(x,a);
a ^= traits::sign;
traits::set_bits(x,a);
return x;
}
//------------------------------------------------------------------------------
} // namespace math
} // namespace spirit
} // namespace boost
#endif