diff --git a/include/boost/core/cmath.hpp b/include/boost/core/cmath.hpp index 842766f..0e5fa1f 100644 --- a/include/boost/core/cmath.hpp +++ b/include/boost/core/cmath.hpp @@ -70,12 +70,85 @@ template bool signbit( T x ) return _copysign( 1.0, static_cast( x ) ) < 0.0; } +int const fp_zero = 0; +int const fp_subnormal = 1; +int const fp_normal = 2; +int const fp_infinite = 3; +int const fp_nan = 4; + +inline int fpclassify( float x ) +{ + switch( _fpclass( x ) ) + { + case _FPCLASS_SNAN: + case _FPCLASS_QNAN: + + return fp_nan; + + case _FPCLASS_NINF: + case _FPCLASS_PINF: + + return fp_infinite; + + case _FPCLASS_NZ: + case _FPCLASS_PZ: + + return fp_zero; + + default: + + return boost::core::isnormal( x )? fp_normal: fp_subnormal; + } +} + +inline int fpclassify( double x ) +{ + switch( _fpclass( x ) ) + { + case _FPCLASS_SNAN: + case _FPCLASS_QNAN: + + return fp_nan; + + case _FPCLASS_NINF: + case _FPCLASS_PINF: + + return fp_infinite; + + case _FPCLASS_NZ: + case _FPCLASS_PZ: + + return fp_zero; + + case _FPCLASS_ND: + case _FPCLASS_PD: + + return fp_subnormal; + + default: + + return fp_normal; + } +} + +inline int fpclassify( long double x ) +{ + return boost::core::fpclassify( static_cast( x ) ); +} + #else using std::isfinite; using std::isnan; using std::isinf; using std::isnormal; +using std::fpclassify; + +int const fp_zero = FP_ZERO; +int const fp_subnormal = FP_SUBNORMAL; +int const fp_normal = FP_NORMAL; +int const fp_infinite = FP_INFINITE; +int const fp_nan = FP_NAN; using std::signbit; diff --git a/test/cmath_test.cpp b/test/cmath_test.cpp index 8e2a903..9e419f1 100644 --- a/test/cmath_test.cpp +++ b/test/cmath_test.cpp @@ -16,6 +16,8 @@ template void test_positive_normal( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_normal ); + BOOST_TEST( !boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(+2) ); @@ -29,6 +31,8 @@ template void test_negative_normal( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_normal ); + BOOST_TEST( boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(-2) ); @@ -42,6 +46,8 @@ template void test_positive_zero( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_zero ); + BOOST_TEST( !boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(+2) ); @@ -55,6 +61,8 @@ template void test_negative_zero( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_zero ); + BOOST_TEST( boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(-2) ); @@ -68,6 +76,8 @@ template void test_positive_infinity( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_infinite ); + BOOST_TEST( !boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(+2) ); @@ -81,6 +91,8 @@ template void test_negative_infinity( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_infinite ); + BOOST_TEST( boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(-2) ); @@ -94,6 +106,8 @@ template void test_positive_nan( T x ) BOOST_TEST( boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_nan ); + BOOST_TEST( !boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(+2) ); @@ -107,6 +121,8 @@ template void test_negative_nan( T x ) BOOST_TEST( boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_nan ); + BOOST_TEST( boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(-2) ); @@ -120,6 +136,8 @@ template void test_positive_subnormal( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_subnormal ); + BOOST_TEST( !boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(+2) ); @@ -133,6 +151,8 @@ template void test_negative_subnormal( T x ) BOOST_TEST( !boost::core::isnan( x ) ); BOOST_TEST( !boost::core::isnormal( x ) ); + BOOST_TEST_EQ( boost::core::fpclassify( x ), boost::core::fp_subnormal ); + BOOST_TEST( boost::core::signbit( x ) ); BOOST_TEST_EQ( boost::core::copysign( T(+2), x ), T(-2) );