[units][interval] adapt boost.interval for boost.units

Hi, what is the best way to make boost.units work together with boost.interval. Something naive as 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). A work around is to do a typedef suggest by http://lists.boost.org/boost-users/2009/07/49493.php typedef boost::numeric::interval_lib::change_checking< boost::numeric::interval< quantity<si::length> >, boost::units::interval::checking_base< quantity<si::length> > >::type interval_length_type; interval_length_type ival(3.*si::meter, 4.*si::meter); which compiles. do you think there is a better way?, that could allow for the first syntax at the beginning of this message. Thank you, Alfredo the compile error: /g/g91/correaa/usr/include/boost/numeric/interval/checking.hpp: In static member function 'static T boost::numeric::interval_lib::checking_base<T>::empty_lower() [with T = boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double>]': /g/g91/correaa/usr/include/boost/numeric/interval/checking.hpp:88: instantiated from 'static T boost::numeric::interval_lib::checking_no_empty<T, Checking, Exception>::empty_lower() [with T = boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double>, Checking = boost::numeric::interval_lib::checking_base<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double> >, Exception = boost::numeric::interval_lib::exception_create_empty]' /g/g91/correaa/usr/include/boost/numeric/interval/interval.hpp:269: instantiated from 'void boost::numeric::interval<T, Policies>::set_empty() [with T = boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double>, Policies = boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double> >, boost::numeric::interval_lib::checking_strict<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double> > >]' /g/g91/correaa/usr/include/boost/numeric/interval/interval.hpp:171: instantiated from 'boost::numeric::interval<T, Policies>::interval(const T&, const T&) [with T = boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double>, Policies = boost::numeric::interval_lib::policies<boost::numeric::interval_lib::rounded_math<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double> >, boost::numeric::interval_lib::checking_strict<boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double> > >]' lindhard.cpp:205: instantiated from here /g/g91/correaa/usr/include/boost/numeric/interval/checking.hpp:63: error: no matching function for call to 'boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::atomic::electron_mass_base_unit, boost::units::list<boost::units::atomic::elementary_charge_base_unit, boost::units::list<boost::units::atomic::reduced_planck_constant_base_unit, boost::units::list<boost::units::atomic::coulomb_force_constant_base_unit, boost::units::list<boost::units::atomic::boltzman_constant_base_unit, boost::units::dimensionless_type> > > > > >, void>, double>::quantity(int)' compilation terminated due to -Wfatal-errors.

On May 23, 10:12 pm, alfC <alfredo.cor...@gmail.com> 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 } }; }}}
participants (1)
-
alfC