Hi boost::units developers
I am interested in extending the scale system for units. Here I present a
short explanation, my initial hack to get this working, and questions on a
small re-engineering issue that will crop up if this proposal is accepted.
*** WHY ***
Existing boost-units code allows scales which have factors as integral powers
of a base,
b^e, eg. 10^3, 2^10 etc. I'd like to use scales that have factors of the form
a*b^e,
Examples:
(a) electron-Volt (eV) = 1.602*10^{-19} J
(b) bohr = 0.528 Angstroms = 5.28*10^{-11} m
In quantum chemistry, for example, such an "atomic units system" is
typically used.
*** HOW ***
To achieve this using templates (which don't (yet) recognize floating point
constants), I borrowed the idea from the 'dimnum' package. I,
(1) added two more parameters of type long to the scale<> template which are
the numerator and denominator of the rational approximation to a,
(2) added static const value_type factor() member function which returns the
value 'a' evaluated as double,
(3) modified the value() static member to return factor() * b^e instead of
simply b^e
---------------
Code snippet (scale.hpp):
template
struct scale {
// ...
static const double factor() { return
double(FactorNumerator)/double(FactorDenominator); }
static value_type value() { return(factor() *
detail::static_rational_power<Exponent>(static_cast<double>(base))); }
// ...
};
----------------
I modified the defintion of the apply<> template class in the
boost::mpl::plus_impl, boost::mpl::negate_impl classes in unscale.hpp so
that the scale<> return template-type now includes the correct
FactorNumerator and FactorDenominator results based on the operands. This
seems to be the place where arithmetic on scales is being performed for
inter-conversion of quantities. I couldn't modify boost::mpl::times_impl
because I'd have to statically exponentiate the numerator/denominator here
and this doesn't fit cleanly into the existing mechanism.
*** WHAT ***
I do have the following questions/observations - please answer/comment.
1. The current implementation assumes that the scales being multiplied have
the same base and differ only in the exponent? I just see T0::base being
copied as the new base. This can be fixed with the generalized scale approach
where if the bases are different (eg. 2 and 10), the resulting base is a
default (10?) with exponent=static_rational<0,1> and a new factor
f=(2^e1)*(10^e2). Of course, this will work only if there are no overflows.
A conceivable use-case for this feature is when calculating, say,
price-per-GB that is incurred in setting up a data-center. $<--->c
interconversion will require 10^2 scale along the currency dimension while
MB<--->GB<--->TB interconversions will require 2^10 scale along the memory
dimension (assume they can be created). Here, currency interconversion will
necessitate a generalized scale.
2. For simple scales like the existing one, multiplication of scales leads to
addition of the exponents and therefore I can understand the static-overload
of the plus_impl template to allow MPL to add the exponents. But with
generalized scales we will have to switch to a different mechanism. Could you
advise me on what all will need to be changed? I have a fair idea and I could
use your input to cross-check.
3. When I complete this, can I submit the patch? I would like to add the
atomic units system to the existing list of systems
http://en.wikipedia.org/wiki/Atomic_units
thanks,
Manoj