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,WEIRD_QUOTING autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,38fc011071df5a27 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-06-04 21:40:54 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!bloom-beacon.mit.edu!nycmny1-snh1.gtei.net!news.gtei.net!chcgil2-snh1.gtei.net!news.bbnplanet.com!wn12feed!worldnet.att.net!204.127.198.203!attbi_feed3!attbi.com!sccrnsc04.POSTED!not-for-mail Message-ID: <3EDEC9A7.9050602@attbi.com> From: "Robert I. Eachus" User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Ideas for Ada 200X References: <6a90b886.0305262344.1d558079@posting.google.com> <3ED41344.7090105@spam.com> <3ED46D81.FF62C34F@0.0> <3ED46E07.4340CABC@0.0> <3ED4F3FD.A0EF7079@alfred-hilscher.de> <6vWcnTWjF83bD0qjXTWcpA@gbronline.com> <3EDCBDF4.1050900@attbi.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.62.164.137 X-Complaints-To: abuse@attbi.com X-Trace: sccrnsc04 1054788046 24.62.164.137 (Thu, 05 Jun 2003 04:40:46 GMT) NNTP-Posting-Date: Thu, 05 Jun 2003 04:40:46 GMT Organization: AT&T Broadband Date: Thu, 05 Jun 2003 04:40:47 GMT Xref: archiver1.google.com comp.lang.ada:38655 Date: 2003-06-05T04:40:47+00:00 List-Id: Russ wrote: > In any case, the performance hit taken to keep A unchanged when a > Constraint_Error is raised seems rather expensive to me. If it were up > to me, I would take the factor of four better efficiency over > preserving A in the rare case of an overflow. And I'll bet most > programmers doing heavy-duty number crunching for simulation would > too. You are mixing up two things here that should be kept separate. There are Ada rule for predefined "+" operators which make a lot of sense in those cases. The effect of other Ada rules is that compilers can't go behind the programmers back and change a user defined "+" function to break what the programmer has written and expects. However it is actually easier to define a two parameter Add procedure and use it to add in place--if that is what you want to do. Appended is an Ada program that runs eight test cases Integer vs. Float, "+" vs. Add, and constraint checking on vs. all checks suppressed. As you can see, in this particular case, suppressing checks is a win for Integer, a lose for Float. This is fairly typical. (If you compile with GNAT remember to invoke gnatmake with -gnato, to enable integer constraint checking. Of course, the program should let you know if you forgot.) E:\Ada\Test\New Folder>test_matrix_add test_matrix_add Initialize Generators. Initialize Integer Matricies. Initialize Float Matrices. Initialization Completed. Integer "+" operator, checks on, required 320.349 milliseconds. Integer Add operator, checks on, required 221.992 milliseconds. Integer "+" operator, checks off, required 262.464 milliseconds. Integer Add operator, checks off, required 170.612 milliseconds. Float "+" operator, checks on, required 222.519 milliseconds. Float Add operator, checks on, required 150.401 milliseconds. Float "+" operator, checks off, required 222.297 milliseconds. Float Add operator, checks off, required 171.129 milliseconds. All Done. > I know that Ada is preferable for safety-critical applications, but > based on what you are telling me, it sure seems to be a poor choice > for non-safety-critical simulation with heavy number crunching. Thanks > for clarifying that. I guess C++ is good for something after all, eh? No, what we are telling you is that in Ada, you have a choice. If you choose safety, the rules are very carefully designed so you get it. If you want to trade safety for speed, Ada lets you do that. Most of the Ada safety you get "for free." There are some areas where you have to intelligently decide whether or not you are willing to pay for it. And remember the case here where Float is faster with checks on. That is not all that uncommon. This is why, if you are going to Suppress checks, you should always test to see if there is a benefit. Cut at line and compile. One source file. ---------------------------------------------------------------------------- with Ada.Text_IO; use Ada.Text_IO; with Ada.Calendar; use Ada.Calendar; with Ada.Numerics.Discrete_Random; with Ada.Numerics.Float_Random; procedure Test_Matrix_Add is type Matrix is array (1..1000,1..1000) of Integer; type Acc_Matrix is access all Matrix; type Float_Matrix is array (1..1000,1..1000) of Float; type Acc_Float is access all Float_Matrix; A, B, C : Acc_Matrix := new Matrix; D, E, F : Acc_Float := new Float_Matrix; subtype Int is Integer range -100_000_000..100_000_000; package Int_Random is new Ada.Numerics.Discrete_Random(Int); Int_Gen: Int_Random.Generator; package Float_Random renames Ada.Numerics.Float_Random; Float_Gen: Float_Random.Generator; package Clock_IO is new Ada.Text_IO.Fixed_IO(Duration); Start, Stop: Ada.Calendar.Time; procedure Init_Matrix(M: in out Matrix) is begin for I in M'Range(1) loop for J in M'Range(2) loop M(I,J) := Int_Random.Random(Int_Gen); end loop; end loop; end Init_Matrix; procedure Init_Float(M: in out Float_Matrix) is begin for I in M'Range(1) loop for J in M'Range(2) loop M(I,J) := Float_Random.Random(Float_Gen); end loop; end loop; end Init_Float; begin Put_Line(" Initialize Generators."); Int_Random.Reset(Int_Gen); Float_Random.Reset(Float_Gen); Put_Line(" Initialize Integer Matricies."); Init_Matrix(A.all); Init_Matrix(B.all); C.all := A.all; Put_Line(" Initialize Float Matrices."); Init_Float(D.all); Init_Float(E.all); F.all := D.all; Put_Line(" Initialization Completed."); declare function "+" (Left, Right: Matrix) return Matrix is Temp: Matrix := Left; begin for I in Temp'Range(1) loop for J in Temp'Range(2) loop Temp(I,J) := Temp(I,J) + Right(I,J); end loop; end loop; return Temp; end "+"; procedure Add (Left: in out Matrix; Right: Matrix) is begin for I in Left'Range(1) loop for J in Left'Range(2) loop Left(I,J) := Left(I,J) + Right(I,J); end loop; end loop; return; end Add; begin Start := Clock; A.all := A.all + B.all; Stop := Clock; Put(" Integer ""+"" operator, checks on, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Start := Clock; Add(C.all,B.all); Stop := Clock; Put(" Integer Add operator, checks on, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Int_Check: for K in A'Range(1) loop for L in A'Range(2) loop if A(K,L) /= C(K,L) then Put_Line(" Integer results do not match."); exit Int_Check; end if; end loop; end loop Int_Check; end; -- declare Block Integer Checks on declare function "+" (Left, Right: Matrix) return Matrix is pragma Suppress(All_Checks); Temp: Matrix := Left; begin for I in Temp'Range(1) loop for J in Temp'Range(2) loop Temp(I,J) := Temp(I,J) + Right(I,J); end loop; end loop; return Temp; end "+"; procedure Add (Left: in out Matrix; Right: Matrix) is pragma Suppress(All_Checks); begin for I in Left'Range(1) loop for J in Left'Range(2) loop Left(I,J) := Left(I,J) + Right(I,J); end loop; end loop; return; end Add; begin Start := Clock; A.all := A.all + B.all; Stop := Clock; Put(" Integer ""+"" operator, checks off, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Start := Clock; Add(C.all,B.all); Stop := Clock; Put(" Integer Add operator, checks off, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Int_Check2: for K in A'Range(1) loop for L in A'Range(2) loop if A(K,L) /= C(K,L) then Put_Line(" Integer results do not match."); exit Int_Check2; end if; end loop; end loop Int_Check2; end; -- declare block integer, checks off declare function "+" (Left, Right: Float_Matrix) return Float_Matrix is Temp: Float_Matrix := Left; begin for I in Temp'Range(1) loop for J in Temp'Range(2) loop Temp(I,J) := Temp(I,J) + Right(I,J); end loop; end loop; return Temp; end "+"; procedure Add (Left: in out Float_Matrix; Right: Float_Matrix) is begin for I in Left'Range(1) loop for J in Left'Range(2) loop Left(I,J) := Left(I,J) + Right(I,J); end loop; end loop; return; end Add; begin Start := Clock; D.all := D.all + E.all; Stop := Clock; Put(" Float ""+"" operator, checks on, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Start := Clock; Add(F.all,E.all); Stop := Clock; Put(" Float Add operator, checks on, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Float_Check: for K in D'Range(1) loop for L in D'Range(2) loop if abs(D(K,L)-F(K,L)) > Float'Epsilon then Put_Line("Float result differences greater than Float'Epsilon."); exit Float_Check; end if; end loop; end loop Float_Check; end; -- declare block, Float, checks on declare function "+" (Left, Right: Float_Matrix) return Float_Matrix is pragma Suppress(All_Checks); Temp: Float_Matrix := Left; begin for I in Temp'Range(1) loop for J in Temp'Range(2) loop Temp(I,J) := Temp(I,J) + Right(I,J); end loop; end loop; return Temp; end "+"; procedure Add (Left: in out Float_Matrix; Right: Float_Matrix) is pragma Suppress(All_Checks); begin for I in Left'Range(1) loop for J in Left'Range(2) loop Left(I,J) := Left(I,J) + Right(I,J); end loop; end loop; return; end Add; begin Start := Clock; D.all := D.all + E.all; Stop := Clock; Put(" Float ""+"" operator, checks off, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Start := Clock; Add(F.all,E.all); Stop := Clock; Put(" Float Add operator, checks off, required "); Clock_IO.Put(1000*(Stop-Start), 2, 3); -- overflow to get natural alignment. Put_Line(" milliseconds."); Float_Check2: for K in D'Range(1) loop for L in D'Range(2) loop if abs(D(K,L)-F(K,L)) > Float'Epsilon then Put_Line("Float result differences greater than Float'Epsilon."); exit Float_Check2; end if; end loop; end loop Float_Check2; end; -- declare block; Float checks off. Put_Line(" All Done."); end Test_Matrix_Add;