[units][ublas] how would i use typedef in units?

Hi,
Using units and ublas for new code is great, but how about using both in
legacy code? I’ve got some legacy numerical code using primitive types, i
plan to use units for some reasons, i.e. to check performance using both
primitive types and boost::units types, and to check my code at compile time
which is its whole purpose after all. I spent a day and my code it’s already
broken, specially because of the initializations and ublas, some
self-explanatory code follows:
----- calculations.hpp -----------
//typedefs to get library-free code
#include <complex>
#include <iostream>
#if USING_BOOST_UNITS
#include

----- calculations.hpp ----------- //typedefs to get library-free code
#include <complex> #include <iostream>
#if USING_BOOST_UNITS
#include
#include //... using namespace boost::units; using namespace boost::units::si; using namespace std; typedef std::complex<double> complex_type;
typedef quantity
tPotencial; typedef quantity tIntensidad; typedef quantity 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
//get Real part from 'tension' and pretend it's a current quantity
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
#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
#define USING_BOOST_UNITS //use ublas ublas::matrix
admi(2, 2); ublas::matrix 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

AMDG Matthias Schabel wrote:
//get Real part from 'tension' and pretend it's a current quantity
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
> tPotencial;
I thought that the operators for std:;complex can't deduce the return type correctly for Boost.Units. Anyway "The effect of instantiating the template complex for any type other than float, double or long double is unspecified." (26.2) In Christ, Steven Watanabe

//get Real part from 'tension' and pretend it's a current quantity
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
> tPotencial; I thought that the operators for std:;complex can't deduce the return type correctly for Boost.Units. Anyway "The effect of instantiating the template complex for any type other than float, double or long double is unspecified." (26.2)
Right, as usual... Maybe flesh out the more flexible complex type that we provided in our example or lobby the standards committee to make std::complex less stupid? Is there any good reason to have unspecified behavior for std::complex for UDTs? Matthias

On Wednesday 14 October 2009 23:03:10 Matthias Schabel wrote:
I thought that the operators for std:;complex can't deduce the return type correctly for Boost.Units. Anyway "The effect of instantiating the template complex for any type other than float, double or long double is unspecified." (26.2)
Right, as usual... Maybe flesh out the more flexible complex type that we provided in our example or lobby the standards committee to make std::complex less stupid? Is there any good reason to have unspecified behavior for std::complex for UDTs?
Yes. This is a huge problem with extended-/finite-precision code where the type of a + b is different from the type of a or b. In this case, std::complex<10-bit type> + std::complex<10-bit type> leads to std::complex<11-bit type> and the problem gets much more complicated for multiplication and division. I work around it currently by specializing std::complex(!) in the std namespace (against all guidelines) for my fixed-point types. Any better solution would be greatly welcome. (For the mathematicians here, the problem is that std::complex<fixed-point type> does not form a ring, much less a field.) Regards, Ravi
participants (4)
-
David Carricajo
-
Matthias Schabel
-
Ravi
-
Steven Watanabe