Boost logo

Boost Users :

Subject: Re: [Boost-users] [numeric conversation] behavior on std::numeric_limits<double>::max() + eps with numeric_cast
From: Brandon Kohn (blkohn_at_[hidden])
Date: 2014-06-10 12:28:22


On 6/9/2014 14:13 PM, Olaf Peter wrote:
> attached my 'playground', it's basically the UDT example simplified
> extended with math_round capabilities. The range_checker also checks on
> finite values, but I'm not sure if this is really required (I would say
> yes, since operator[<,>} wouldn't work on NaN or Inf). Line 486 doesn't
> compile - vice versa doesn't work for some reasons.

A couple of points:

1) the range checker you've implemented expects that value is always of
type core::intrinsic_type<T> as it calls value.to_builtin(); This fails
when the 'Source' type/argument_type is a different type (like int.)

2) On the other hand, when Target is of type core::intrinsic_type<T> and
Source is a fundamental type, certain comparison operations fail because
the fundamental type doesn't know how to compare with
core::intrinsic_type<T>.

In order to get this compiling I had to split the range checker into two
specializations like so:

//! Define a custom range checker
template<typename Traits, typename OverFlowHandler>
struct range_checker;

//! One for checking intrinsic_type against some other type (fundamental)
template<typename T, typename SourceT, typename OverFlowHandler>
struct range_checker
<
    boost::numeric::conversion_traits<core::intrinsic_type<T>, SourceT>
  , OverFlowHandler
>;

//! And another one for checking other types against intrinsic_type
template<typename T, typename TargetT, typename OverFlowHandler>
struct range_checker
<
    boost::numeric::conversion_traits<TargetT, core::intrinsic_type<T>>
  , OverFlowHandler
>;

In each of these specializations I wrote logic specific to the
conversion direction.

I also had to add the unary minus operator to core::instrinsic_type.

I've attached the file I modified for my tests (which were done in
visual studio 2008.)

I should note that in each of these specializations care must be taken
that bounds are properly checked given the context of the conversion
direction. In my test I essentially converted the fundamental type to an
instance of intrinsic_type (via the template constructor) and then used
that to compare with the bounds of the intrinsic_type<T>. In a real
world example this is possibly nonsense.

> Is there a way to get a stack trace using boost to find the code part
> which triggers the exception in the source? I mean here it would be e.g.
> line 478 if x would be greater MAX_INT.

I would just use whatever debugger you have handy.

>
> Is it usefull to add boost exception infos about the calling args in
> overflow_handler? Is there a clever way since the overflow_handler isn't
> templated so I have no info about the type and value to be converted.
>
> Where is the error for the vise versa cast at line 486?

The overflow handler was designed to communicate positive and negative
overflow. It assumes the range checker is working properly for all
inputs. So I think the the best way to develop these is to simply write
tests for all the types of inputs you expect your range_checker to see
and make sure it gives you the correct outputs. (i.e. I would test these
directly on the range_checker<ConversionTraits,
OverFlowHandler>::out_of_range interface.)

Hope this helps,

Brandon




Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net