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