www.delorie.com/gnu/docs/kawa/kawa-tour_7.html   search  
 
Buy GNU books!


Kawa: Compiling Scheme to Java

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6 Quantities

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