Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

square root of boost units scaled_unit

Tags:

c++

boost

I use boost::units to handle units in a project.

I have created a scaled unit to store micro meters:

using namespace boost::units;
typedef make_scaled_unit<si::length,
                         scale<10, static_rational<-6> > >::type micro_meter_unit;

Everything works as expected:

quantity<si::length, double> some_meter = 10 * si::meter;
quantity<micro_meter_unit, double> some_mu_meter = 
  static_cast<quantity<micro_meter_unit, double>>(some_meter);

std::cout << "some_meter^2 = " << some_meter * some_meter;  // outputs 100 m^2
std::cout << "some_mu_meter^2 = " << some_mu_meter * some_mu_meter; // outputs 1e+014 p(m^2)

Yet the square root operations is not compiled:

std::cout << "sqrt(some_meter) = " << sqrt(some_meter); // outputs 3.16228 m^(1/2)
std::cout << "sqrt(some_mu_meter) = " << sqrt(some_mu_meter); //error here
// 'value' : is not a member of 'boost::units::scale_dim_tag'
// ...
// see reference to class template instantiation 
// 'boost::units::root_typeof_helper<X,Y>' being compiled
//with
//[
//  X=boost::units::quantity<pds::ssp::micro_meter_unit,double>,
//  Y=boost::units::static_rational<2>
//]

How can I define scaled unit in a proper way to perform square root and other operations?

like image 917
ifnull Avatar asked Nov 11 '22 04:11

ifnull


1 Answers

After looking at it a bit, I think this is a bug.

The documentation suggests the motivation for make_scaled_unit was for the prefixes in system/si/prefixes.hpp

For example:

BOOST_UNITS_METRIC_PREFIX(-9, nano);
BOOST_UNITS_METRIC_PREFIX(-6, micro);
BOOST_UNITS_METRIC_PREFIX(-3, milli);

//! The define uses a dimensionless unit to make a scale unit
#define BOOST_UNITS_METRIC_PREFIX(exponent, name)                                                       \
typedef make_scaled_unit<dimensionless, scale<10, static_rational<exponent> > >::type name ## _type;\
BOOST_UNITS_STATIC_CONSTANT(name, name ## _type)

These are then used like so:

quantity<si::length, double> mu_meter( 1.0 * si::micro * si::meter );

The idea is that you convert the input into the length type of the underlying system, and then work with those quantities and only worry about conversion when you need to output.

It seems probable that using such scaled units in other ways might have been missed in the library's test coverage. You should post this to the boost trac:

https://svn.boost.org/trac/boost/

like image 133
Brandon Kohn Avatar answered Nov 15 '22 07:11

Brandon Kohn