[Units]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Units]

Boost - Users mailing list
I am trying to create a set of units to use in a library, but I having trouble getting IO to work for some of them. Here is a simple example that demonstrates the problem.

============================

#include<iostream>

#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>

using namespace boost::units;

// short hand for meter
namespace t { typedef si::length m; }
namespace i { BOOST_UNITS_STATIC_CONSTANT( m, t::m ); }

// centimeter
namespace t { typedef make_scaled_unit< si::length, scale< 10, static_rational<-2> > >::type cm; }
namespace i { BOOST_UNITS_STATIC_CONSTANT( cm, t::cm ); }

// meter squared
namespace t { typedef multiply_typeof_helper< m, m>::type m_m; }
namespace i { BOOST_UNITS_STATIC_CONSTANT( m_m, t::m_m ); }

// centimeter squared
namespace t { typedef multiply_typeof_helper< cm, cm>::type cm_cm; }
namespace i { BOOST_UNITS_STATIC_CONSTANT( cm_cm, t::cm_cm ); }

// meter centimeter
namespace t { typedef multiply_typeof_helper< m, cm>::type m_cm; }
namespace i { BOOST_UNITS_STATIC_CONSTANT( m_cm, t::m_cm ); }

// override default output, which prints "c(m^2)"
namespace boost { namespace units {
inline std::string name_string(const t::m_cm&)
{ return "meter centimeter"; }
inline std::string symbol_string(const t::m_cm&)
{ return "m cm"; }
} }

// trying to overload output for centimeter squared
namespace boost { namespace units {
inline std::string name_string(const t::cm_cm&)
{ return "centimeter squared"; }
inline std::string symbol_string(const t::cm_cm&)
{ return "cm^2"; }
} }


int main(int argc, char *argv[])
{
  std::cout << i::m << std::endl;
  std::cout << i::cm << std::endl;
  std::cout << i::m_m << std::endl;
  std::cout << i::m_cm << std::endl;
  //std::cout << i::cm_cm << std::endl; // this won't compile
  
  quantity<t::m_m> a1(100*i::cm_cm);
  std::cout << a1<< std::endl; // should be 0.01 m^2

  quantity<t::m_m> a2(100*i::m_cm);
  std::cout << a2<< std::endl; // should be 1 m^2

  return 0;
}

============================

Basically, I am just trying to create a convenient set of short hands. Unit types are put in a 't' namespace and instances are put in a 'i' namespace with the same name.

This works fine for doing calculations and conversions with the units, but I am having trouble with getting output to work for some of them. In the example above I create a centimeter unit by scaling the meter. Then I create three different area units with the product_typeof_helper struct: meter squared, meter centimeter, and centimeter squared. Conversions work for all three of these, but output will not work for the centimeter squared unit.

The program above outputs

m
cm
m^2
m cm
0.01 m^2
1 m^2


If I uncomment the line that tries to print i::cm_cm it won't compile. I get an error that says

'symbol' is not a member of ...

and points at a line that says

str += Begin::item::symbol()

I can't understand why it doesn't work for a product of two scaled units.

cdclark

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units]

Boost - Users mailing list
AMDG

On 10/04/2017 07:58 PM, CD Clark via Boost-users wrote:

> <snip>
> // centimeter
> namespace t { typedef make_scaled_unit< si::length, scale< 10,
> static_rational<-2> > >::type cm; }
> namespace i { BOOST_UNITS_STATIC_CONSTANT( cm, t::cm ); }
>
> <snip>
>
> // centimeter squared
> namespace t { typedef multiply_typeof_helper< cm, cm>::type cm_cm; }
> namespace i { BOOST_UNITS_STATIC_CONSTANT( cm_cm, t::cm_cm ); }
>
> <snip>
>   //std::cout << i::cm_cm << std::endl; // this won't compile
>
> <snip>
> If I uncomment the line that tries to print i::cm_cm it won't compile. I
> get an error that says
>
> 'symbol' is not a member of ...
>
> and points at a line that says
>
> str += Begin::item::symbol()
>
> I can't understand why it doesn't work for a product of two scaled units.
>

  The reason that it fails is that the output code
instantiates the default implementation even if
you override it.  The problem is that there is
no symbol defined for 10^-4.

In Christ,
Steven Watanabe

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units]

Boost - Users mailing list
> The reason that it fails is that the output code
> instantiates the default implementation even if
> you override it.  The problem is that there is
> no symbol defined for 10^-4.

Ah, that explains why it works for millimeter. Multiplying two millimeter units together gives 10^-6, which has a symbol. Does this mean that the IO can't handle units that have base units raised to some power that does not correspond to a symbol, or is this just supposed to be done a different way?

Looking at the libraries definition of farad (which contains seconds to the fourth power), a derived dimension is defined for capacitance, and then an a unit for that dimension is created. Should I be creating the centimeter squared unit from the area dimension directly instead of trying to build it from already defined units?

Thanks you for the help.

cdclark

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units]

Boost - Users mailing list
AMDG

On 10/05/2017 12:44 PM, CD Clark via Boost-users wrote:

>> The reason that it fails is that the output code
>> instantiates the default implementation even if
>> you override it.  The problem is that there is
>> no symbol defined for 10^-4.
>
> Ah, that explains why it works for millimeter. Multiplying two millimeter
> units together gives 10^-6, which has a symbol. Does this mean that the IO
> can't handle units that have base units raised to some power that does not
> correspond to a symbol, or is this just supposed to be done a different way?
>
> Looking at the libraries definition of farad (which contains seconds to the
> fourth power), a derived dimension is defined for capacitance, and then an
> a unit for that dimension is created. Should I be creating the centimeter
> squared unit from the area dimension directly instead of trying to build it
> from already defined units?
>

Based on the way you're using this, I would recommend,
setting up the scaling at the base unit level, instead
of scaling the whole unit:

namespace t {
  using cm = scaled_base_unit<
    si::meter_base_unit,
    scale<10, static_rational<-2> > >::unit_type;
}

This should make the output work the way you
want automatically, as it causes cm*cm to
be represented as (cm)^2 instead of (c^2)(m^2).

In Christ,
Steven Watanabe

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units]

Boost - Users mailing list
That worked. Thank you.

cdclark

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users