Boost logo

Boost :

From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2006-08-04 15:16:00


"John Maddock" <john_at_[hidden]> wrote in message
news:097901c6b728$a7d1b0b0$6e240d52_at_fuji...
> Gennadiy Rozental wrote:
>> Should be in cvs by now.
>
> Apparently this was not quite as simple as I thought it was, because we
> still need to handle the 0/0 case, the following patch does the trick:
>
> cvs diff: Diffing boost/test
> Index: boost/test/floating_point_comparison.hpp
> ===================================================================
> RCS file: /cvsroot/boost/boost/boost/test/floating_point_comparison.hpp,v
> retrieving revision 1.28
> diff -u -r1.28 floating_point_comparison.hpp
> --- boost/test/floating_point_comparison.hpp 28 Jul 2006
> 15:01:01 -00001.28
> +++ boost/test/floating_point_comparison.hpp 3 Aug 2006 18:08:39 -0000
> @@ -71,6 +71,18 @@
> f2 > static_cast<FPT>(1) && f1 < f2 *
> (std::numeric_limits<FPT>::mi
> n)() )
> return static_cast<FPT>(0);
> }
> + else if(f1 == 0)
> + {
> + // Avoid 0 / 0, since we're calculating relative error
> + // the result really is zero here no matter what the denominator:
> + return 0;
> + }
> + else if(f2 == 0)
> + {
> + // We have an infinite relative error, in practice any
> + // big number returned here will cause our test to fail:
> + return 1000000; // any really big number will do.
> + }
>
> return f1/f2;
> }
>
> Both of the else clauses here only kick in when there is no numeric_limits
> support BTW.
>
> Does this look OK?

I don't really like this. I may consider something like this:

namespace tt_detail {

template<typename FPT>
struct generic_fpt_limits {
    FPT min_value() { return static_cast<FPT>(0); }
    FPT max_value() { return static_cast<FPT>(1000000); }
};

template<typename FPT>
struct numeric_limits {
    FPT min_value() { return (std::numeric_limits<FPT>::min)(); }
    FPT max_value() { return (std::numeric_limits<FPT>::min)(); }
};

template<typename FPT>
struct fpt_limits
:
mpl::if_<std::numeric_limits<FPT>::is_specialized,numeric_fpt_limits,generic_fpt_limits>
{};

template<typename FPT>
inline FPT
safe_fpt_division( FPT f1, FPT f2 )
{
    // Avoid overflow.
    if( f2 < static_cast<FPT>(1) && f1 > f2 *
fpt_limits<FPT>::max_value() )
        return fpt_limits<FPT>::max_value();

    // Avoid underflow.
    if( f1 == static_cast<FPT>(0) ||
        f2 > static_cast<FPT>(1) && f1 < f2 * fpt_limits<FPT>::min_value() )
        return static_cast<FPT>(0);

    return f1/f2;
}

} // namespace tt_detail

Could you try this?

Gennadiy


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk