From: AdaMagica <christ-usch.grein@t-online.de>
Subject: Re: GNAT and Dimension Checking
Date: Fri, 6 Jul 2012 03:47:58 -0700 (PDT)
Date: 2012-07-06T03:47:58-07:00 [thread overview]
Message-ID: <8252873c-f2b9-4afd-8373-0658836c34c1@googlegroups.com> (raw)
In-Reply-To: <2afdc8e6-def0-4a00-8535-4db40165fc92@googlegroups.com>
I would like to invite all of you interested in dimensional algebra to a lively discussion about the findings in packages provided by GNAT.
I played around a bit and here are mine.
GNAT Dimension_System Findings
==================================
Very clever use of the new aspect facilty.
Should be considered for standardisation in next Ada generation.
Currently very poorly documented.
There are a few minor problems and some (in my honest opinion) more severe
ones in output.
The following is based on the (Gaussian) CGS system.
type CGS_Gauss is new Long_Long_Float
with Dimension_System => ((Centimeter, "cm"),
(Gram , 'g'),
(Second , 's'));
package CGS_Gauss_IO is new System.Dim.Float_IO (CGS_Gauss);
use CGS_Gauss_IO;
subtype Length is CGS_Gauss
with Dimension => ("cm",
Centimeter => 1,
others => 0);
subtype Mass is CGS_Gauss
with Dimension => ("g",
Gram => 1,
others => 0);
subtype Time is CGS_Gauss
with Dimension => ("s",
Second => 1,
others => 0);
cm: constant Length := 1.0;
g : constant Mass := 1.0;
s : constant Time := 1.0;
0. The syntax of aspects Dimension_System and Dimension is not documented.
--------------------------------------------------------------------------
It might seem obvious, but documentation is needed nevertheless.
In Dimension_System, up to 7 base dimensions may be defined (more lead to
a compilation error, less are tolerated).
1. How to define objects for dimensions without name?
-----------------------------------------------------
Imagine you have some charge, but not defined a subtype Charge.
Q: CGS_Gauss := 40.0 * cm**(3/2)*g**(1/2)/s; -- ???
This fails with
dimensions mismatch in object declaration
object type is dimensionless
object expression has dimensions (3/2, 1/2, -1)
It's no problem to define the subtype
subtype Charge is CGS_Gauss
with Dimension => ("esu",
Centimeter => 3/2,
Gram => 1/2,
Second => -1);
and then write
Q: Charge := 40.0 * cm**(3/2)*g**(1/2)/s;
but it is often the case that some intermediate value has to be stored
with an unnamed dimension. Very inconvenient if you have to locally
define a subtype for this.
** Dimension should be taken from the initial expression! **
2. Obviously GNAT can handle fractional dimensions.
---------------------------------------------------
This is very comfortable.
Q: Charge := 40.0 * cm**(3/2)*g**(1/2)/s;
R: Length := 10.0 * cm;
Put (Q**2/R**2 , Aft => 2, Exp => 0); New_Line;
Put (Q**2/R**2 , Aft => 2, Exp => 0, Symbols => "dyn"); New_Line;
Put ((Q/R)**(5/7), Aft => 2, Exp => 0); New_Line;
16.00 cm.g.s**(-2)
2.69 cm**(5/14).g**(5/14).s**(-5/7)
However, I cannot find where
function (Left: Dim_Type; Right: Rational) return Dim_Type;
is defined, let alone the type Rational.
The definition of Rational is flawed.
Don't write
(8.0*cm)**(1/3+2/3)
this has the value 1. This, howver, is correct:
(8.0*cm)**((1+2)/(5-2)) = 8.0*cm
(Admittedly, who would write such nonsense? Dimension checking is only done
for static expressions.)
Ahem - be careful:
8.0**(1/3) = 1
8.0**(1/3)*cm = 2.0*cm
(8.0*cm)**(1/3) = 2.0*cm**(1/3)
You need a dimensioned value to give the correct result:
One: constant CGS_Gauss := 1.0; -- dimension 1, i.e. "dimensionless"
8.0**(1/3)*One = 2.0
(In SI, results never have fractional dimensions, but intermediate values
may. So this is important also for SI.)
3. System.Dim.Float_IO is only output.
--------------------------------------
Values are correctly output with their dimension, very nice.
However, the name Float_IO is a lie, there is no dimensional input.
Input would be hard to achieve with the output syntax as produced now because
how to determine whether a dimension to read follows a number or not since
there is a separating space. We would need a multiplication sign instead.
Put (Q**2/R**2, Aft => 2, Exp => 0);
results in
16.00 cm.g.s**(-2) <=== How to read this back in?
Also the exponent in an output like 1.0 m**2.s could be taken as the
floating point number 2.0 when trying to read it in again (in input, missing
fore or aft is allowed).
Compare with
16.00*cm.g.s**(-2) <=== This is dimensioned.
So checking the input for syntactic and semantic correctness is not easy.
Adding a symbol for the output is not checked! You can write any nonsense.
Put (Q**2/R**2, Aft => 2, Exp => 0, Symbols => "dyn"); New_Line;
Put (Q**2/R**2, Aft => 2, Exp => 0, Symbols => "m/s"); New_Line;
16.00dyn <=== space missing (dyn undefined)!
16.00m/s <=== nonsense!
R: Length := 10.0 * cm;
Put (R, Aft => 2, Exp => 0); New_Line;
Put (R, Aft => 2, Exp => 0, Symbols => "km"); New_Line;
10.00 cm <=== OK
10.00km <=== Surprise, surprise!
This behaviour is apt to lead to confusion and program bugs!
4. Mathematics is included!
===========================
package Math is new Ada.Numerics.Generic_Elementary_Functions (CGS_Gauss);
use Math;
Any function requires dimensionless parameters and returns a dimensionless
result, except Sqrt, which correcly calculates the root of the dimension.
However:
function Sin (X, Cycle : Float_Type'Base) return Float_Type'Base;
(Cos, Tan, Cot) should allow dimensioned parameters when both have the same
dimension.
function Arcsin (X, Cycle : Float_Type'Base) return Float_Type'Base;
(Arccos) should request X dimensionless and the return value should be
dimensioned like Cycle.
function Arctan (Y: Float_Type'Base;
X: Float_Type'Base := 1.0[;
Cycle : Float_Type'Base]) return Float_Type'Base;
(Arccot) should allow X and Y with the same dimension [and be dimensioned
like Cycle].
------------------------------------------
Any thoughts, other nice features or awkward shortcomings?
next prev parent reply other threads:[~2012-07-06 10:47 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-01 5:53 GNAT and Dimension Checking AdaMagica
2012-07-01 6:25 ` Nasser M. Abbasi
2012-07-01 10:44 ` yogeshwarsing
2012-07-02 20:42 ` Anh Vo
2012-07-02 20:58 ` Adam Beneschan
2012-07-02 21:51 ` Anh Vo
2012-07-01 15:18 ` AdaMagica
2012-07-01 15:47 ` yogeshwarsing
2012-07-06 10:47 ` AdaMagica [this message]
2012-07-08 1:50 ` Robert A Duff
2012-07-08 10:33 ` AdaMagica
2012-07-08 11:37 ` Dmitry A. Kazakov
2012-07-08 14:13 ` AdaMagica
2012-07-08 18:47 ` Jacob Sparre Andersen
2012-07-09 11:06 ` AdaMagica
2012-07-09 8:20 ` Martin
2012-07-09 11:19 ` AdaMagica
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox