Boost logo

Boost Users :

Subject: Re: [Boost-users] [units][ublas] how would i use typedef in units?
From: Matthias Schabel (boost_at_[hidden])
Date: 2009-10-14 22:31:39


> ----- calculations.hpp -----------
> //typedefs to get library-free code
>
> #include <complex>
> #include <iostream>
>
> #if USING_BOOST_UNITS
>
>
> #include <boost/typeof/std/complex.hpp>
> #include <boost/units/systems/si/power.hpp>
> //...
> using namespace boost::units;
> using namespace boost::units::si;
> using namespace std;
>
> typedef std::complex<double> complex_type;
>
> typedef quantity<electric_potential,complex_type> tPotencial;
> typedef quantity<current,complex_type> tIntensidad;
> typedef quantity<resistance,complex_type> tResistancia;
>
> //...
> #elif
>
> typedef double tPotencial;
> typedef double tIntensidad;
> typedef double tResistancia;
>
> //...
> #endif
> ------------------------------------------
>
> ----- some_legacy_calculations.cpp ------
>
> #define USING_BOOST_UNITS
> tPotencial tension = complex_type(12.5,0.0)*volts; //ok
> tPotencial tension2 = complex_type(12.5,0.0); //auch!

Here tPotencial is a quantity<electric_potential,complex_type>, so it
must be initialized with a valid quantity. Thus, as expected, the
first case works because volts are the SI unit of electric potential.
The second fails because you are trying to initialize a quantity with
a bare value, which is not dimensionally correct.

> //get Real part from 'tension' and pretend it's a current
> quantity<current, double> phony_tension = tension.value().real *
> amperes;//compiler doesn't complain, but how do I prevent this to
> compile?

As soon as you use the value member function you have stripped out all
unit information. Then, by multiplying by amperes, you are telling the
compiler that this quantity is a current. It's not clear to me what
you are trying to do here...the real part should still have units of
electric potential. You might find reversing the nesting useful :

typedef std::complex<quantity<electric_potential,double> > tPotencial;

etc... Then tension.real() is a quantity<electric_potential,double> as
you probably expect...this will fail in the context you list. Another
option is to write free real() and imag() functions that take
quantities with complex value type and return the corresponding
quantities with real value type.

> #undef USING_BOOST_UNITS
> tPotencial tension = complex_type(12.5,0.0)*volts; //auch!
> tPotencial tension2 = complex_type(12.5,0.0); //ok

Here you have the reverse problem : volts is still a unit of electric
potential, but tPotencial is a bare double, so the first line is
trying to assign a quantity<electric_potential> to a POD double, which
is not dimensionally correct.

> #define USING_BOOST_UNITS
> //use ublas
> ublas::matrix<tAdmitancia, ublas::column_major> admi(2, 2);
> ublas::matrix<tPotencia, ublas::column_major> ind(2, 1);
>
> ind(0, 0) = complex_type (1, 0)*volts;
> ind(1, 0) = complex_type (-1, 0)*volts;
>
> admi(0, 0) = complex_type (0, -2)*siemens;
> admi(0, 1) = complex_type (0, 2)*siemens;
> admi(1, 0) = complex_type (0, 2)*siemens;
> admi(1, 1) = complex_type (0, -2)*siemens;
>
>
> int er = lapack::gesv(admi, ind);//auch!

This question requires more knowledge of ublas than I have. Maybe
someone more familiar with the algorithm can comment. My guess is that
gesv doesn't compute the typeof its return value correctly, but I
don't know for sure. In any case, I would strongly recommend that you
try completely converting a small but non-trivial bit of legacy code
to use boost.units and then test the performance. Quite a bit of work
was done to make the library have zero runtime overhead, and we would
be interested to know if there are cases on modern compilers where
this is not the situation.

Matthias


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