Boost logo

Boost Users :

Subject: Re: [Boost-users] [units] Proposal for generalizing scales
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2009-09-17 11:02:47


AMDG

Manoj Rajagopalan wrote:
> 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.
>

In this case it's probably easier to define a new
base unit and use the conversion macros, which
can accept a double. (Warning untested)

struct electron_volt_base_unit : base_unit<electron_volt_base_unit,
energy_dimension, 43289> {
    static const char* name() { return "electron-Volt"; }
    static const char* symbol() { return "eV"; }
};

BOOST_UNITS_DEFINE_CONVERSION_FACTOR(electron_volt_base_unit,
si::energy, double, 1.602e-19);
BOOST_UNITS_DEFAULT_CONVERSION(electron_volt_base_unit, si::energy);

> 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<long Base, class Exponent,
> long FactorNumerator=1L,
> long FactorDenominator=1L>
> 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.
>

You can do something like this by chaining scales together.

For example:
typedef scaled_base_unit<second_base_unit, scale<60, static_rational<2>
> > hour_base_unit;
typedef scaled_base_unit<hour_base_unit, scale<24, static_rational<1> >
> day_base_unit;
typedef scaled_base_unit<day_base_unit, scale<7, static_rational<1> > >
week_base_unit;

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

The current implementation never multiplies scales that have different
bases.
In the implementation of conversions, scales are collected in a list
sorted by base.

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

In Christ,
Steven Watanabe


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