| www.delorie.com/gnu/docs/kawa/kawa-tour_7.html | search |
![]() Buy GNU books! | |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The DSSSL language is a dialect of Scheme used
to process SGML documents. DSSSL has "quantities" in addition
to real and integer numbers. Since DSSSL is used to format documents,
it provides length values that are a multiple of a meter
(e.g. 0.2m), as well as derived units like cm and
pt (point).
A DSSSL quantity is a product of a dimension-less number with an integral
power of a length unit (the meter). A (pure) number is a quantity where
the length power is zero.
For Kawa, I wanted to merge the Scheme number types with the DSSSL
number types, and also generalize the DSSSL quantities to support
other dimensions (such as mass and time) and units (such as kg
and seconds). Quantities are implemented by the abstract class Quantity.
A quantity is a product of a Unit and a pure
number. The number can be an arbitrary complex number.
class Quantity extends Number {
public Unit unit ()
{ return Unit.Empty; }
public abstract Complex number ();
...
}
|
class CQuantity extends Quantity {
Complex num;
Unit unt;
public Complex number ()
{ return num; }
public Unit unit ()
{ return unt; }
...
}
|
A CQuantity is a concrete class that implements general
Quantities. But usually we don't need that much generality,
and instead use DQuanity.
class DQuantity extends Quantity {
double factor;
Unit unt;
public final Unit unit ()
{ return unt; }
public final Complex number ()
{ return new DFloNum(factor); }
...
}
|
class Unit extends Quantity {
String name; // Optional.
Dimensions dims;
double factor;
...
}
|
A Unit is a product of a floating-point factor
and one or more primitive units, combined into a Dimensions object.
The Unit name have a name (such as "kg"), which is
used for printing, and when parsing literals.
class BaseUnit extends Unit {
int index;
...
}
|
A BaseUnit is a primitive unit that is not
defined in terms of any other Unit, for example the meter.
Each BaseUnit has a different index, which is used
for identification and comparison purposes. Two BaseUnits
have the same index if and only if they are the same BaseUnit.
class Dimensions {
BaseUnit[] bases;
short[] powers;
...
}
|
A Dimensions object is a product and/or ratio of BaseUnits.
You can think of it as a data structure that maps every BaseUnit
to an integer power. The bases array is a list of the BaseUnits
that have a non-zero power, in order of the index of the BaseUnit.
The powers array gives the power (exponent) of the BaseUnit
that has the same index in the bases array.
Two Dimensions objects are equal if they have the same list of
bases and powers. Dimensions objects are "interned"
(using a global hash table) so that they are equal only if they are
the same object. This makes it easy to implement addition and
subtraction:
public static DQuantity add (DQuantity x, DQuantity y)
{
if (x.unit().dims != y.unit().dims)
throw new ArithmeticException ("units mis-match");
double r = y.unit().factor / x.unit().factor;
double s = x.factor + r * y.factor;
return new DQuantity (s, x.unit());
}
|
The Unit of the result of an addition or subtraction
is the Unit of the first operand. This makes it easy to convert units:
kawa> (+ 0cm 2.5m) 250cm |
Because Kawa represents quantities relative to user-specified units,
instead of representing them relative to primitive base units,
it can automatically print quantities using the user's preferred units.
However, this does make multiplication and division more difficult.
The actual calculation (finding the right Dimensions and
multiplying the constant factors) is straight-forward.
The problem is generating the new compound unit, and
later printing out the result in a human-friendly format.
There is no obvious right way to do this. Kawa creates
a MulUnit to represent a compound unit, but it is not
obvious which simplifications should be done when.
Kawa uses a few heuristics to simplify compound
units, but this is an area that could be improved.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| webmaster donations bookstore | delorie software privacy |
| Copyright © 2003 by The Free Software Foundation | Updated Jun 2003 |