|
Boost : |
From: Reece Dunn (msclrhd_at_[hidden])
Date: 2006-06-08 15:59:36
David Greene wrote:
> Andy Little wrote:
>
> > If kilograms played by the rules its exponent would be 3 , but for whatever
> > historical reasons its 0.
> >
> > Without the prefix_offset, because kilograms has an exponent of 0, then its
> > unit output would be worked out as 'g', which is plainly wrong.
> >
> > Does this help?
>
> Why not just give kg anb exponent of "3" like everywhere else and then
> adjust the other mass exponents accordingly. Why special-case this?
I have been playing around with implementing a unit system. What I have
for SI units is something like:
namespace boost { namespace unit { namespace si
{
struct si_tag{};
namespace prefix
{
typedef power< 10, 6 > mega;
typedef power< 10, 3 > kilo;
typedef power< 10, 0 > base;
typedef power< 10, -3 > milli;
typedef kilo k;
typedef milli m;
}
struct length_tag{};
struct mass_tag{};
struct time_tag{};
typedef base_unit_type< length_tag, 0 >
length;
typedef base_unit_type< mass_tag, 1 >
mass;
typedef base_unit_type< time_tag, 2 >
time;
/** @brief length */
typedef base_unit< si_tag, length, prefix::base > meter;
typedef scaled_unit< meter, prefix::kilo > km;
typedef scaled_unit< meter, prefix::base > m;
typedef scaled_unit< meter, prefix::milli > mm;
/** @brief mass */
typedef base_unit< si_tag, mass, prefix::kilo > kilogram;
typedef scaled_unit< kilogram, prefix::kilo > kg;
typedef scaled_unit< kilogram, prefix::base > g;
typedef scaled_unit< kilogram, prefix::milli > mg;
/** @brief time */
typedef base_unit< si_tag, time, prefix::base > second;
typedef scaled_unit< second, prefix::kilo > ks;
typedef scaled_unit< second, prefix::base > s;
typedef scaled_unit< second, prefix::milli > ms;
/** @brief force */
typedef derived_unit< kilogram, meter, per< second >, per< second > >
newton; // N = m.kg.s-2
typedef scaled_unit< newton, prefix::kilo > kN;
typedef scaled_unit< newton, prefix::base > N;
typedef scaled_unit< newton, prefix::milli > mN;
}}}
With the following unit concepts:
namespace boost { namespace unit
{
template< int Base, int Exponent >
struct power{};
/** @brief A single unit in a given unit system.
*/
template< typename System, typename Dimension, typename Scale, int Exponent = 1 >
struct unit{};
/** @brief A fundamental unit type within a unit system.
*/
template< typename Tag, int Index >
struct base_unit_type
{
};
/** @brief A fundamental unit within a unit system.
*/
template< typename System, typename Dimension, typename Scale >
struct base_unit
{
};
/** @brief A unit scaled up or down by a given magnitude.
*/
template< typename Unit, typename Scale >
struct scaled_unit{};
/** @brief The inverse (reciprocal) of a unit.
*/
template< typename Unit >
struct per{};
/** @brief A composite unit type.
*/
template< typename Unit1, typename Unit2 >
struct composite_unit{};
struct none{};
/** @brief A unit derived from a series of other units.
*/
template< typename Unit1, typename Unit2 = none,
typename Unit3 = none, typename Unit4 = none,
typename Unit5 = none, typename Unit6 = none,
typename Unit7 = none, typename Unit8 = none,
typename Unit9 = none, typename Unit10 = none
>
struct derived_unit{};
}}
I also have simple type manipulation inside these concepts that
can reduce units of the same type, Allowing:
namespace si = boost::unit::si;
template< typename Unit >
void print( const Unit & )
{
std::cout << typeid(Unit::type).name() << std::endl << std::endl;
}
print(si::mm());
print(si::kg());
print(si::hertz());
print(si::tesla());
std::cout << typeid(si::mm() * si::mm()).name() << std::endl << std::endl;
print(si::mm() * si::mm() * si::mm());
The last two giving:
struct boost::unit::composite_unit<struct boost::unit::unit<struct boost::unit::
si::si_tag,struct boost::unit::base_unit_type<struct boost::unit::si::length_tag
,0>,struct boost::unit::power<10,-3>,1>,struct boost::unit::unit<struct boost::u
nit::si::si_tag,struct boost::unit::base_unit_type<struct boost::unit::si::lengt
h_tag,0>,struct boost::unit::power<10,-3>,1> >
struct boost::unit::unit<struct boost::unit::si::si_tag,struct boost::unit::base
_unit_type<struct boost::unit::si::length_tag,0>,struct boost::unit::power<10,-3
>,3>
Currently tested on VC8 and will only reduce adjacent similar types. The idea is
to support values like this:
template< typename ValueUnit, typename ValueType = float >
class boost::unit::value;
//...
boost::unit::value< si::mm > dist( 1.5 );
boost::unit::value< typeof(si::mm() * si::mm()) > dist( dist * dist );
If there is interest, I'd be willing to persue this, especially with Andy's
expertise in this area :). At the moment it is just a toy example. I can
upload the full code as well.
NOTE: It will require a conformant compiler!
- Reece
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk