$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [units] - learning to use, more questions :)
From: Matthias Schabel (boost_at_[hidden])
Date: 2011-11-28 17:13:55
> And I've hit a brick wall, because I cannot get those lines to compile:
>
> quantity<reciprocal_area> lambda ( 2.0*m*E / (hbar*hbar) );
> quantity<reciprocal_area> alpha ( m*omega/root<2>(hbar) );
> double lambda_per_alpha ( lambda / alpha );
>
> Even the first one has problems, to my surprise. Maybe I really
> should change my g++ 4.4.5 version to a newer version? I will gladly try
> this if you think it makes sense.
The first line compiles correctly using Boost 1.48; I don't know when the fix was made. The second line there is a bug/missing feature; the constants don't define pow/root operations, although I don't understand exactly why the implicit conversion to the appropriate quantity type is not working. We will fix that in the next release... For the interim, you can use root<2>(hbar.value()), although I recognize that it is somewhat confusing since, in this context, value() returns a quantity, not a value_type.
However, you also have an error in the second line; alpha is not a reciprocal_area : kg * (1/s) / (kg m^2/s)^1/2 = kg^1/2 s^-1/2 m^-1. Of course, this makes the third line incorrect as well; an example of the power of Boost.Units, I guess...
In general, when debugging units, it is often helpful to output to the console. Use of auto for intermediate values is also your friend... For example, here's what I did to figure out your problem:
#include <iostream>
#include <complex>
using namespace std;
//use units
#include <boost/typeof/std/complex.hpp>
#include <boost/units/cmath.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#include <boost/units/systems/si/codata/universal_constants.hpp>
#include <boost/units/io.hpp>
using namespace boost::units;
using namespace boost::units::si;
using namespace boost::units::si::constants::codata;
//use units end
typedef derived_dimension<length_base_dimension,-2>::type reciprocal_area_dimension;
typedef unit<reciprocal_area_dimension,si::system> reciprocal_area;
int main()
{
int n = 5;
quantity<mass> m(1*kilogram);
quantity<frequency> omega(1*hertz);
quantity<energy> E(hbar*omega*(n+0.5));
quantity<reciprocal_area> lambda(2.0*m*E/(hbar*hbar));
std::cout << m << std::endl;
std::cout << omega << std::endl;
std::cout << E << std::endl;
std::cout << lambda << std::endl;
// std::cout << m*omega/root<2>(hbar) << std::endl; // bug - this should work
std::cout << m*omega/root<2>(hbar.value()) << std::endl; // works but shouldn't be necessary and bad choice of syntax
return 0;
}
output :
1 kg
1 s^-1
5.80014e-34 m^2 kg s^-2
1.04308e+35 m^-2
9.73782e+16 m^-1 kg^(1/2) s^(-1/2)
Steven - since you implemented the constants.hpp header, I'm a little reluctant to rummage through it. Could you please consider
1) adding support for the pow<> and root<> operations?
2) deprecating constant.value_type and constant.value() in favor of constant.quantity_type and constant.quantity() or constant.mean_value() or constant.mean() or something?
Also, can you remind me why we have "constant" and "physical_constant" structs? They look identical to me...
Janek,
I have attached headers implementing the various prefixed short cuts for the meter and joule; these two should be sufficient to extend to the rest of the SI unit system. What remains to be done is to replicate scaled_meter.hpp/scaled_length.hpp for the remaining base units in the <boost/units/base_units/si> directory and to replicate scaled_energy.hpp for all the remaining named SI units in the <boost/units/systems/si> directory.
Here's my test program:
#include <iostream>
#include <boost/units/io.hpp>
#include <boost/units/systems/si/length.hpp>
#include <boost/units/systems/si/energy.hpp>
#include "scaled_length.hpp"
#include "scaled_energy.hpp"
using namespace boost::units;
using namespace boost::units::si;
int main()
{
std::cout << 1.0*nm << "\t" << 1.5*mJ << std::endl;
quantity<length> q1(1.0*nm);
quantity<energy> q2(1.5*mJ);
std::cout << q1 << "\t" << q2 << std::endl;
auto q3(1.0*nm);
auto q4(1.5*mJ);
std::cout << q3 << "\t" << q4 << std::endl;
return 0;
}
and output :
1 nm 1.5 mJ
1e-09 m 0.0015 m^2 kg s^-2
1 nm 1.5 mJ
Note: if you assign these scaled quantities to unscaled quantities, the scaling information will be lost (second output line)...
Matthias