
----- 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