| [ < ] | [ > ] | [ << ] | [ 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] | [ ? ] |