comp.lang.ada
 help / color / mirror / Atom feed
From: Hyman Rosen <hymie@prolifics.com>
Subject: Re: Engineering types hierarchy
Date: 1999/09/08
Date: 1999-09-08T18:41:41+00:00	[thread overview]
Message-ID: <t73dwpckha.fsf@calumny.jyacc.com> (raw)
In-Reply-To: 7r50i7$e893@svlss.lmms.lmco.com

dkristol@see-my.sig (David Kristola) writes:
> I am trying to put together a robust and easily usable
> hierarchy of types packages to support a collection of
> engineering units (kilograms, meters, seconds, etc.)
> in scalar, vector, and matrix forms.
> 
> So far, i have a list of the base types and combined
> types (meters per second and so on) that are going to
> be used on this project.
> 
> There is an explosion of operators that i have to
> implement.  "/" for meters and second returning
> meters per seconds, and on, and on, and on.
> Of course, there is nothing special about these
> operators beyond the typing they do.
> 
> Is there a better way?

Although this is an Ada group, I am moved to demonstrate a C++ solution
which is applicable when all units are known at compile time. It's from
Barton & Nackman's excellant "Scientific and Engineering C++", and is
quite beautiful. Perhaps it can be transformed into Ada by someone who
knows more about the language than I do.

I'll write the code assuming three units - mass, time, distance - but the
technique easily scales to as many as you need. The units are kept track
of by virtue of the type system - the objects themselves carry no data
other than their values. The type system allows multiplication and division
of arbitrary units, while allowing addition and subtraction only of like
units. Type mismatches result in compile-time errors.

The scaffolding is wordy, but the punchline is down in main(), where the
units are used in a very natural way, with the compiler deducing types.

#include <iostream>

template<int M, int T, int D>
struct unit
{
	double value;
	unit(double initial = 0) : value(initial) { }
};

template<int M, int T, int D>
unit<M,T,D> operator+(const unit<M,T,D> &a, const unit<M,T,D> &b)
{ return unit<M,T,D>(a.value + b.value); }

template<int M, int T, int D>
unit<M,T,D> operator-(const unit<M,T,D> &a, const unit<M,T,D> &b)
{ return unit<M,T,D>(a.value - b.value); }

template<int M1, int T1, int D1, int M2, int T2, int D2>
unit<M1+M2, T1+T2, D1+D2>
operator*(const unit<M1,T1,D1> &a, const unit<M2,T2,D2> &b)
{ return unit<M1+M2, T1+T2, D1+D2>(a.value * b.value); }

template<int M1, int T1, int D1, int M2, int T2, int D2>
unit<M1-M2, T1-T2, D1-D2>
operator/(const unit<M1,T1,D1> &a, const unit<M2,T2,D2> &b)
{ return unit<M1-M2, T1-T2, D1-D2>(a.value / b.value); }

template<int M, int T, int D>
ostream &operator<<(ostream &out, const unit<M,T,D> &u)
{
	cout << u.value;
	if (M != 0) { out << " gm";  if (M != 1) out << "^" << M; }
	if (D != 0) { out << " cm";  if (D != 1) out << "^" << D; }
	if (T != 0) { out << " sec"; if (T != 1) out << "^" << T; }
	return out;
}

typedef unit<0,0,0> Scalar;
typedef unit<1,0,0> Mass;
typedef unit<0,1,0> Time;
typedef unit<0,0,1> Distance;
typedef unit<0,-1,1> Herz;
typedef unit<1,-2,2> Energy;
typedef unit<0,-1,1> Velocity;
// etc.

// gram-second-centimeter system
const Mass gram = 1;
const Mass kilogram = 1000;
const Distance centimeter = 1;
const Distance meter = 100;
const Time second = 1;
// etc.

int main()
{
	Distance d = Scalar(3) * meter + Scalar(21) * centimeter;
	Time t = 10;
	Mass m = Scalar(5) * kilogram + Mass(672);
	Energy e = (m * d * d / t / t);
	cout << e << endl;
}




  parent reply	other threads:[~1999-09-08  0:00 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-09-08  0:00 Engineering types hierarchy David Kristola
1999-09-08  0:00 ` Robert Dewar
1999-09-09  0:00   ` David Kristola
1999-09-09  0:00     ` Robert Dewar
1999-09-10  0:00       ` David Kristola
1999-09-09  0:00     ` Robert Dewar
1999-09-08  0:00 ` Marin David Condic
1999-09-09  0:00   ` David Kristola
1999-09-11  0:00     ` Richard D Riehle
1999-09-08  0:00 ` Pat Rogers
1999-09-09  0:00   ` David Kristola
1999-09-08  0:00 ` Matthew Heaney
1999-09-09  0:00   ` David Kristola
1999-09-08  0:00 ` Hyman Rosen [this message]
1999-09-08  0:00   ` Matthew Heaney
1999-09-09  0:00 ` David Botton
1999-09-10  0:00   ` David Kristola
1999-09-10  0:00     ` Ted Dennison
  -- strict thread matches above, loose matches on Subject: below --
1999-09-09  0:00 Matthew Heaney
1999-09-09  0:00 ` Matthew Heaney
1999-09-09  0:00   ` Pat Rogers
1999-09-10  0:00   ` David Kristola
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox