Boost logo

Boost Users :

Subject: Re: [Boost-users] [units][interval] adapt boost.interval for boost.units
From: alfC (alfredo.correa_at_[hidden])
Date: 2010-05-24 14:09:26


On May 23, 10:12 pm, alfC <alfredo.cor..._at_[hidden]> wrote:
>
> boost::numeric::interval<boost::units::quantity<boost::units::si::energy>
>
>    iv(3.*boost::units::si::meter, 4.*boost::units::si::meter);
>
> doesn't compile because of an error in boost/numeric/interval/
> checking.hpp (error attached below).
>

answering to myself... I hope this is useful for someone and for the
Units and Interval maintainers.

Boost Interval has an unfortunate line of code in boost/numeric/
interval/checking.hpp that reads

        static T empty_lower()
        {
                return (std::numeric_limits<T>::has_quiet_NaN ?
                                        std::numeric_limits<T>::quiet_NaN() : static_cast<T>(1) // units
can not be constructed from plain numbers (int or other)
                );
        }
inside the template class 'checking_base'. The trick to make interval
work with units is to specialize the class checking_base to change the
behaviour of this particular function.
Also unfortunate is the fact that the checking_base member functions
are defined inside the class so the whole checking_base class has to
be rewritten during the specialization, including member functions
that remain unchanged. So if you want to declare a units interval as

boost::numeric::interval<boost::units::quantity<boost::units::si::energy>
>

you need to include the code below

(see at end).

The code seems to be as generic as possible, it should work with any
unit.

Now I still have two questions: Whether it is possible to add a
shorter specialization code that only specializes only empty_lower().
The second question is what is the magic that makes units
constructible from integer 0 and not from integer 1 (note that because
of this I can keep empty_upper unchanged).

Thank you,
Alfredo

adaptation of Boost.Interval for Boost.Units:

namespace boost {namespace numeric {namespace interval_lib {
template<class Unit>
struct checking_base<boost::units::quantity<Unit> >{
        typedef boost::units::quantity<Unit> T; //this is to keep most of
the code unchanged
        static T pos_inf(){
                assert(std::numeric_limits<T>::has_infinity);
                return std::numeric_limits<T>::infinity();
        }
        static T neg_inf(){
                assert(std::numeric_limits<T>::has_infinity);
                return -std::numeric_limits<T>::infinity();
        }
        static T nan(){
                assert(std::numeric_limits<T>::has_quiet_NaN);
                return std::numeric_limits<T>::quiet_NaN();
        }
        static bool is_nan(const T& x){
                return std::numeric_limits<T>::has_quiet_NaN && (x != x);
        }
        static T empty_lower(){
                return (std::numeric_limits<T>::has_quiet_NaN ?
                        std::numeric_limits<T>::quiet_NaN() : T::from_value(1) // <--
basically the only change
                );
        }
        static T empty_upper(){
                return (std::numeric_limits<T>::has_quiet_NaN ?
                                        std::numeric_limits<T>::quiet_NaN() : static_cast<T>(0)
                );
        }
        static bool is_empty(const T& l, const T& u){
                return !(l <= u); // safety for partial orders
        }
};
}}}


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