diff --git a/LCS/Common/include/Common/Numeric.h b/LCS/Common/include/Common/Numeric.h index 3d82558ccf3f878955c554041ff4e0195c6c05b0..5746ecc413d36086ec91345eab822480a7a77c1b 100644 --- a/LCS/Common/include/Common/Numeric.h +++ b/LCS/Common/include/Common/Numeric.h @@ -23,6 +23,8 @@ #ifndef LOFAR_COMMON_NUMERIC_H #define LOFAR_COMMON_NUMERIC_H +#include <Common/LofarTypes.h> + //# Never #include <config.h> or #include <lofar_config.h> in a header file! // \file @@ -65,9 +67,9 @@ namespace LOFAR public: // Mask type used for floats is a (32-bit) int. - typedef int floatMask_t; + typedef uint32 floatMask_t; // Mask type used for doubles is a (64-bit) long long. - typedef long long doubleMask_t; + typedef uint64 doubleMask_t; // @{ // Classes to overlap floating point numbers with masks in a type-safe way @@ -110,13 +112,13 @@ namespace LOFAR // @{ // These constants are for IEEE754 floating point numbers. - static const floatMask_t floatNegativeMask = 0x80000000L; - static const floatMask_t floatExponentMask = 0x7F800000L; - static const floatMask_t floatMantissaMask = 0x007FFFFFL; + static const floatMask_t floatNegativeMask = 0x80000000UL; + static const floatMask_t floatExponentMask = 0x7F800000UL; + static const floatMask_t floatMantissaMask = 0x007FFFFFUL; - static const doubleMask_t doubleNegativeMask = 0x8000000000000000LL; - static const doubleMask_t doubleExponentMask = 0x7FF0000000000000LL; - static const doubleMask_t doubleMantissaMask = 0x000FFFFFFFFFFFFFLL; + static const doubleMask_t doubleNegativeMask = 0x8000000000000000ULL; + static const doubleMask_t doubleExponentMask = 0x7FF0000000000000ULL; + static const doubleMask_t doubleMantissaMask = 0x000FFFFFFFFFFFFFULL; // @} }; diff --git a/LCS/Common/src/Numeric.cc b/LCS/Common/src/Numeric.cc index 4fc15aa3269c3a6bd323917acb351398da7f25e4..2ebcbc5732c0975c23714a8544181cb26dc40a97 100644 --- a/LCS/Common/src/Numeric.cc +++ b/LCS/Common/src/Numeric.cc @@ -33,49 +33,49 @@ namespace LOFAR bool Numeric::isFinite(float f) { floatUnion_t mask = { f }; - return mask.mask & floatExponentMask != floatExponentMask; + return (mask.mask & floatExponentMask) != floatExponentMask; } bool Numeric::isFinite(double d) { doubleUnion_t mask = { d }; - return mask.mask & doubleExponentMask != doubleExponentMask; + return (mask.mask & doubleExponentMask) != doubleExponentMask; } bool Numeric::isNegative(float f) { floatUnion_t mask = { f }; - return mask.mask & floatNegativeMask == floatNegativeMask; + return (mask.mask & floatNegativeMask) == floatNegativeMask; } bool Numeric::isNegative(double d) { doubleUnion_t mask = { d }; - return mask.mask & doubleNegativeMask == doubleNegativeMask; + return (mask.mask & doubleNegativeMask) == doubleNegativeMask; } bool Numeric::isInf(float f) { floatUnion_t mask = { f }; - return !isFinite(f) && (mask.mask & floatMantissaMask == 0L); + return !isFinite(f) && (mask.mask & floatMantissaMask) == 0L; } bool Numeric::isInf(double d) { doubleUnion_t mask = { d }; - return !isFinite(d) && (mask.mask & doubleMantissaMask == 0LL); + return !isFinite(d) && (mask.mask & doubleMantissaMask) == 0LL; } bool Numeric::isNan(float f) { floatUnion_t mask = { f }; - return !isFinite(f) && (mask.mask & floatMantissaMask != 0L); + return !isFinite(f) && (mask.mask & floatMantissaMask) != 0L; } bool Numeric::isNan(double d) { doubleUnion_t mask = { d }; - return !isFinite(d) && (mask.mask & doubleMantissaMask != 0LL); + return !isFinite(d) && (mask.mask & doubleMantissaMask) != 0LL; } @@ -108,13 +108,22 @@ namespace LOFAR // Make \a ilhs and \a irhs lexicographically ordered as twos-complement // long. - if (ilhs < 0) ilhs = floatNegativeMask - ilhs; - if (irhs < 0) irhs = floatNegativeMask - irhs; + if (isNegative(lhs)) + ilhs = ~ilhs + 1; + else + ilhs += floatNegativeMask; + + if (isNegative(rhs)) + irhs = ~irhs + 1; + else + irhs += floatNegativeMask; // If \a ilhs and \a irhs are less than \a maxUlps apart, then \a lhs and // \a rhs are considered equal. - return std::abs(ilhs - irhs) <= maxUlps; - + if (ilhs < irhs) + return irhs - ilhs <= maxUlps; + else + return ilhs - irhs <= maxUlps; } @@ -145,17 +154,23 @@ namespace LOFAR doubleMask_t ilhs = mlhs.mask; doubleMask_t irhs = mrhs.mask; - // Make \a ilhs and \a irhs lexicographically ordered as twos-complement - // long. - if (ilhs < 0) ilhs = doubleNegativeMask - ilhs; - if (irhs < 0) irhs = doubleNegativeMask - irhs; + // Make \a ilhs and \a irhs lexicographically ordered + if (isNegative(lhs)) + ilhs = ~ilhs + 1; + else + ilhs += doubleNegativeMask; + + if (isNegative(rhs)) + irhs = ~irhs + 1; + else + irhs += doubleNegativeMask; // If \a ilhs and \a irhs are less than \a maxUlps apart, then \a lhs and // \a rhs are considered equal. - ilhs -= irhs; - if (ilhs < 0) ilhs = -ilhs; - return ilhs <= maxUlps; - + if (ilhs < irhs) + return irhs - ilhs <= maxUlps; + else + return ilhs - irhs <= maxUlps; } diff --git a/LCS/Common/test/tNumeric.cc b/LCS/Common/test/tNumeric.cc index e90725951ce0b1ab88c06e54f60e0fbc23ccffcf..3a69c0d6695f08d70a51d2a5ca70186dd70e70dc 100644 --- a/LCS/Common/test/tNumeric.cc +++ b/LCS/Common/test/tNumeric.cc @@ -38,11 +38,12 @@ using namespace std; LOG_INFO("initNumbers("#T")"); \ typedef Numeric::T##Mask_t mask_t; \ typedef Numeric::T##Union_t union_t; \ + mask_t negmask = mask_t(1) << 8*sizeof(T)-1; \ ASSERT(sizeof(T) == sizeof(mask_t)); \ T zero(0), one(1), two(2); \ /* Create a negative zero */ \ union_t negativeZero_u; \ - negativeZero_u.mask = mask_t(1) << 8*sizeof(T)-1; \ + negativeZero_u.mask = negmask; \ T negativeZero(negativeZero_u.value); \ /* Create an infinity */ \ T inf(one/zero); \ @@ -80,6 +81,9 @@ using namespace std; #define printNumber(os, x) \ { int p(2*sizeof(x)+1); \ union_t u = { x }; \ + /* test output verification requires NaNs to be signed, */ \ + /* even though the sign of NaN is platform dependent. */ \ + if (Numeric::isNan(x)) u.mask |= negmask; \ os << setprecision(p) << left << setw(17) << #x << " = " \ << setw(p+6) << x << " (" << hex << showbase << setw(p+1) \ << u.mask << dec << ")" << endl; \ diff --git a/LCS/Common/test/tNumeric.run b/LCS/Common/test/tNumeric.run deleted file mode 100755 index b7ced8e1ded2c1b876bb8070e14f28e1dac74f37..0000000000000000000000000000000000000000 --- a/LCS/Common/test/tNumeric.run +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# Skip the test until problem with gcc-4 in opt mode is resolved. -exit 3