Using BOOST_ASSERT to check numeric_limits<FPT>::epsilon

Can anyone help me insert a compile time check on the validity ( > 0) of std::numeric_limits<FPT>::epsilon(). In this code (in floating_point_comparison.hpp) template<typename FPT> bool operator()(FPT left, FPT right) { // ((left-right)/left) / epsilon) BOOST_STATIC_ASSERT(std::numeric_limits<FPT>::is_specialized); // OK. BOOST_STATIC_ASSERT(numeric_limits<FPT>::is_iec559); // OK BOOST_STATIC_ASSERT((DBL_EPSILON > 0)); // OK too. BOOST_STATIC_ASSERT(DBL_EPSILON); // OK, but I am trying to check for UDT FPT BOOST_STATIC_ASSERT(numeric_limits<FPT>::epsilon()); // Fails to compile BOOST_STATIC_ASSERT(numeric_limits<FPT>::epsilon() > (FPT)0); // as does this. // error C2975: 'x' : invalid template argument for 'boost::STATIC_ASSERTION_FAILURE', expected compile-time constant expression (I could just return false but this would help the user much). return ...; } epsilon should be a constant known at compile time? But is the compile unable to know this? Other suggestions on how to achieve a compile-time warning here? Thanks Paul -- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB Phone and SMS text +44 1539 561830, Mobile and SMS text +44 7714 330204 mailto: pbristow@hetp.u-net.com http://www.hetp.u-net.com/index.html http://www.hetp.u-net.com/Paul%20A%20Bristow%20info.html

epsilon should be a constant known at compile time? But is the compile unable to know this?
Static assertions require an integral-constant expression, and epsilon is basically a runtime constant (at best it's a floating point constant). BTW I don't believe you can portably use DBL_EPSILON etc in a static assertion: you certainly can't use the DBL_* macros in preprocessor directives as I've found to my cost already. A vendor is entitled to implement this as: #define DBL_EPSILON __dbl_eps extern const double __dbl_eps;
Other suggestions on how to achieve a compile-time warning here?
Not really, other than checking for numeric_limits<>::is_specialized. John.

| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock | Sent: 11 February 2006 13:43 | To: boost@lists.boost.org | Subject: Re: [boost] Using BOOST_ASSERT to check | numeric_limits<FPT>::epsilon | | > epsilon should be a constant known at compile time? | > But is the compile unable to know this? | | Static assertions require an integral-constant expression, | and epsilon is | basically a runtime constant (at best it's a floating point constant). | | BTW I don't believe you can portably use DBL_EPSILON etc in a static | assertion: you certainly can't use the DBL_* macros in preprocessor | directives as I've found to my cost already. A vendor is entitled to | implement this as: | | #define DBL_EPSILON __dbl_eps | extern const double __dbl_eps; | | > Other suggestions on how to achieve a compile-time warning here? | | Not really, other than checking for numeric_limits<>::is_specialized. | | John. I feared as much. (In fact worse than I feared - you might like to add these to the static assert docs - I would have dropped into this trap :-(( ) Supplementary question: What impact will it each of the following have on Darwin long double (that I believe you have used) if fp comparisons includes: BOOST_STATIC_ASSERT(numeric_limits<FPT>::is_specialized); and BOOST_STATIC_ASSERT(numeric_limits<FPT>::is_iec559); and if (numeric_limits<FPT>::epsilon() <= (FPT)0) { // numeric_limits not correctly specilized! return false; // Better warning desirable. Throw? } We discussed numeric_limits<FPT>::epsilon() and I think we can produce an intuitively useful (if not exact) value using the normal formula 2^(1-significands) Paul -- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB Phone and SMS text +44 1539 561830, Mobile and SMS text +44 7714 330204 mailto: pbristow@hetp.u-net.com http://www.hetp.u-net.com/index.html http://www.hetp.u-net.com/Paul%20A%20Bristow%20info.html

I feared as much. (In fact worse than I feared - you might like to add these to the static assert docs - I would have dropped into this trap :-(( )
Supplementary question:
What impact will it each of the following have on Darwin long double
(that I believe you have used)
Not really used, just tried to port Boost code to it, and maybe ended up knowing more than I wanted.
if fp comparisons includes: BOOST_STATIC_ASSERT(numeric_limits<FPT>::is_specialized);
and
BOOST_STATIC_ASSERT(numeric_limits<FPT>::is_iec559);
and
if (numeric_limits<FPT>::epsilon() <= (FPT)0) { // numeric_limits not correctly specilized! return false; // Better warning desirable. Throw? }
We discussed numeric_limits<FPT>::epsilon() and I think we can produce an intuitively useful (if not exact) value using the normal formula 2^(1-significands)
Yep. I don't think you'll ever find a value of numeric_limits<>::epsilon() <= 0 BTW, it's a very small positive value very close to zero on Darwin. BTW I added a useful little helper program to Boost.Config (called math_info) that prints out this kind of information - see http://engineering.meta-comm.com/boost-regression/CVS-HEAD/developer/output/... for the Darwin results. As well as checking numeric_limits, it also looks for a couple of other gotchas I've fallen into: like the sqrt of a finite long double being infinity! That one takes a bit of head scratching until you realise that the library in question truncates all long doubles to doubles internally before calculating any math function (and yes the long double overloads are there, they're just not useful). HTH, John.

| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of John Maddock | Sent: 11 February 2006 18:01 | To: boost@lists.boost.org | Subject: Re: [boost] Using BOOST_ASSERT to check | numeric_limits<FPT>::epsilon | | Yep. I don't think you'll ever find a value of | numeric_limits<>::epsilon() <= 0 If not specialized or not done sensibly, it would be 0 (as if NOT specialized), I thought it might be zero on Darwin. | BTW, it's a very small positive value very close to zero on Darwin. epsilon() = 4.94065645841246544176568792868221e-324 == denorm_min() = 4.94065645841246544176568792868221e-324 I don't think that is helpful/useful. It certainly needs a lot of justification and documentation. I think it should be based on bits used in significand. | BTW I added a useful little helper program to Boost.Config (called | math_info) that prints out this kind of information - see | http://engineering.meta-comm.com/boost-regression/CVS-HEAD/dev | eloper/output/dmcgrath-bin-boost-status-math_info-test-gcc-4_0 | -darwin-debug.html | for the Darwin results. Nice - though Firefox would not print it :-(( | As well as checking numeric_limits, it also looks for a | couple of other | gotchas I've fallen into: Hmmm. Not sure I'd rather not have long double at all than have it half done. Thanks. Paul
participants (2)
-
John Maddock
-
Paul A Bristow