| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] | 
This feature depends on Ada 2012 aspect specifications, and is available from version 7.0.1 of GNAT onwards. The GNAT-specific aspect Dimension_System allows the user to define a system of units; the aspect Dimension then allows the user to declare dimensioned quantities within a given system.
The major advantage of this model is that it does not require the declaration of multiple operators for all possible combinations of types: it is only necessary to use the proper subtypes in object declarations.
The simplest way to impose dimensionality checking on a computation is to make use of the package System.Dim.Mks, which is part of the GNAT library. This package defines a floating-point type MKS_Type, for which a sequence of dimension names are specified, together with their conventional abbreviations. The following should be read together with the full specification of the package, in file s-dimmks.ads.
   type Mks_Type is new Long_Long_Float
     with
      Dimension_System => (
        (Meter,    'm'),
        (Kilogram, "kg"),
        (Second,   's'),
        (Ampere,   'A'),
        (Kelvin,   'K'),
        (Mole,     "mol"),
        (Candela,  "cd"));
 | 
The package then defines a series of subtypes that correspond to these conventional units. For example:
   subtype Length is Mks_Type
     with
      Dimension => ('m',
        Meter =>  1,
        others => 0);
 | 
The package also defines conventional names for values of each unit, for example:
m : constant Length := 1.0; kg : constant Mass := 1.0; s : constant Time := 1.0; A : constant Electric_Current := 1.0;  | 
as well as useful multiples of these units:
cm : constant Length := 1.0E-02; g : constant Mass := 1.0E-03; min : constant Time := 60.0; day : constant TIme := 60.0 * 24.0 * min; ...  | 
The user can then define a derived unit by providing the aspect that specifies its dimensions within the MKS system, as well as the string to be used for output of a value of that unit:
  subtype Acceleration is Mks_Type
    with Dimension => ("m/sec^2", Meter => 1, Second => -2, others => 0);
 | 
Here is a complete example of use:
with System.Dim.MKS; use System.Dim.Mks;
with System.Dim.Mks_IO; use System.Dim.Mks_IO;
with Text_IO; use Text_IO;
procedure Free_Fall is
  subtype Acceleration is Mks_Type
    with Dimension => ("m/sec^2", 1, 0, -2, others => 0);
  G : constant acceleration := 9.81 * m / (s ** 2);
  T : Time := 10.0*s;
  Distance : Length;
begin
  Put ("Gravitational constant: ");
  Put (G, Aft => 2, Exp => 0); Put_Line ("");
  Distance := 0.5 * G * T ** 2;
  Put ("distance travelled in 10 seconds of free fall ");
  Put (Distance, Aft => 2, Exp => 0);
  Put_Line ("");
end Free_Fall;
 | 
Execution of this program yields:
Gravitational constant: 9.81 m/sec^2 distance travelled in 10 seconds of free fall 490.50 m  | 
However, incorrect assignments such as:
Distance := 5.0; Distance := 5.0 * kg:  | 
are rejected with the following diagnoses:
   Distance := 5.0;
      >>> dimensions mismatch in assignment
      >>> left-hand side has dimensions (1, 0, 0, 0, 0, 0, 0)
      >>> right-hand side is dimensionless
   Distance := 5.0 * kg:
      >>> dimensions mismatch in assignment
      >>> left-hand side has dimensions  (1, 0, 0, 0, 0, 0, 0)
      >>> right-hand side has dimensions (0, 1, 0, 0, 0, 0, 0)
 | 
The dimensions of an expression are properly displayed, even if there is no explicit subtype for it. If we add to the program:
      Put ("Final velocity: ");
      Put (G * T, Aft =>2, Exp =>0);
      Put_Line ("");
 | 
then the output includes:
Final velocity: 98.10 m.s**(-1)  | 
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |