From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,608011466ae2af71 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.68.227.67 with SMTP id ry3mr12833295pbc.8.1341571678796; Fri, 06 Jul 2012 03:47:58 -0700 (PDT) Path: l9ni11004pbj.0!nntp.google.com!news1.google.com!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail From: AdaMagica Newsgroups: comp.lang.ada Subject: Re: GNAT and Dimension Checking Date: Fri, 6 Jul 2012 03:47:58 -0700 (PDT) Organization: http://groups.google.com Message-ID: <8252873c-f2b9-4afd-8373-0658836c34c1@googlegroups.com> References: <2afdc8e6-def0-4a00-8535-4db40165fc92@googlegroups.com> NNTP-Posting-Host: 91.7.69.24 Mime-Version: 1.0 X-Trace: posting.google.com 1341571678 25143 127.0.0.1 (6 Jul 2012 10:47:58 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Fri, 6 Jul 2012 10:47:58 +0000 (UTC) In-Reply-To: <2afdc8e6-def0-4a00-8535-4db40165fc92@googlegroups.com> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=91.7.69.24; posting-account=rmHyLAoAAADSQmMWJF0a_815Fdd96RDf User-Agent: G2/1.0 Content-Type: text/plain; charset=ISO-8859-1 Date: 2012-07-06T03:47:58-07:00 List-Id: 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?