adatrain@trwspp.UUCP (09/30/84)
-------------------------------------------------- -- Rules -- -------------------------------------------------- 1. All rules apply equally to all vendors participating. Every effort will be made to assure fairness in the treatment of the vendors. 2. All vendors must perform the tests in accordance with these rules. Each vendor is responsible for complying with them and for accurately reporting the results of all the tests which were submitted, including any tests not performed. 3. If more than one Ada toolset or host/target environment is used, the vendor should make a complete, independent report of the test results for each distinct combination of tools, host, and target. 4. All tests must be performed using the source code in its original, official format, without alteration of any kind, except as directed. Where implementation differences may effect the source code, directions for alteration may be supplied to the vendors in written form, embedded in the source code as comments, or orally by the Technical Chair or his authorized representative. Any alterations made to a test in the absence of such directions or which violate the clear intent of the directions given are grounds for disqualification of the vendor on that test. 5. The test source files must be submitted as single compilations, regardless of the number of compilation units they contain, unless specific directions to the contrary are given. All pragmas which an implementation can obey must be obeyed. In particular, range checking must not be suppressed except where directed by pragmas in the source code. A compilation listing file must be generated by each compilation. Unless specifically requested, no linker or loader outputs are required. Execution outputs must be those produced by the Ada program and its run-time environment, without alteration of any kind. The information submitted as official test results must represent a complete, continuous, and self-consistent sequence of operations in which the unaltered output of each operation is the input of the next. The image which is executed must be precisely that which is directly produced by the sequence described above. The intent of this rule is to avoid any inconsistency between the options used in different parts of the test sequence and to make sure that timing and performance data are measured for that specific sequence only. Additional information which was not produced in that sequence may not be included in the official test results, but may be submitted as a supplement as described below. 6. All timing information which is requested (other than that obtained directly by the program using the Calendar package) shall be given in terms of differences in the actual time of day ("wall clock" time), accurate to the nearest second (or tenth of a second, if possible). Compilation, link or binding, and load times must include the time required to load and initialize the programs which perform these processes. Compilation times include all intermediate translations performed (e.g., from assembly code to native object code), and specifically must include those not performed by the Ada compiler itself. The sum of the times given for each phase (compilation, linking, etc.) must be equal to the actual elapsed time for the entire sequence, starting with initiation of compilation and ending with completion of execution. 7. Size information shall be given in bytes, accurate to the nearest byte if possible. Module object code size does not include predefined packages such as Text_IO and Calendar which were "with"ed or the run-time support library or the underlying operating system if any. 8. In the event that a test is found to be defective for any reason, including (but not restricted to) invalid Ada code, functional errors, or unclear directions for its execution, it will be dropped from the test suite and will not be considered further unless it can be corrected easily and all participating vendors can be given timely notification of the corrections. 9. Any test may be challenged by any vendor stating their belief that it is defective and why they feel that it is. (Suggestions for fixing the defects will be gratefully received.) Such challenges will be taken under advisement by the Technical Chair and his appointed representatives and will be considered and accepted or rejected as expeditiously as possible. Only those challenges made before the date of the fair will be considered unless there is unanimous agreement between all vendors and the Technical Chair that a test is defective, in which case a challenge may be accepted on the spot. In the case of a rejected challenge, vendors may include their objections with their results. 10. In case of ambiguities or contradictions in these rules, the interpretation of the Technical Chair shall prevail. Suggestions for future changes to these rules which would improve them in any way, particularly in their fairness, clarity of interpretation, and usefulness to the Ada community are always welcome. 11. Several copies of these rules will be made available for public inspection and reference at the Fair. 12. Vendors are requested to present two copies of a written summary of their results and two copies of the compilation listing of each test program to the Technical Chair at least 30 minutes prior to the opening of the demonstration period (scheduled for 10:00am on 30 June, 1984). Additional documentation which may be specifically required for each test and supplemental information which the vendor desires to supply for each test should be submitted at the same time. In particular, cross reference listings, set/use listings, assembly listings, linkage and load maps, etc., which were not generated in the official test sequence, may be included. The summary of results shall categorize the results in accordance with the program outlined below: with Text_IO; use Text_IO; procedure Summarize is type Vendor_Name is (<List of participating vendors>, None); Vendor : Vendor_Name := None; Columns : constant := 80; subtype Comment is String (1 .. Columns); Blank_Comment : constant Comment := (1 .. Columns => ' '); type Note is array (1 .. 5) of String (1 .. Columns); Blank_Note : constant Note := (1 .. 5 => (1 .. Columns => ' ')); Compilation_Environment : Note := Blank_Note; Execution_Environment : Note := Blank_Note; type Test_Result is (Passed, Failed, Uncertain, Unable_To_Run, Not_Attempted, Disqualified, Test_Has_Been_Dropped); Seconds : constant Integer := 1; type Size is digits 6; Kilo_Bytes : constant Size := 1.0; -- represents 1024 bytes type Result_Record is record Class : Test_Result := Not_Attempted; Class_Comment : Comment := Blank_Comment; Challenged_By_Vendor : Boolean := False; Challenge_Comment : Comment := Blank_Comment; -- Officially requested results go here: Performance_Data : Note := Blank_Note; Performance_Comment : Comment := Blank_Comment; -- Explanations and objections go here: Explanations : Note := Blank_Note; -- This includes any intermediate translations by other -- compilers or assemblers: Compilation_Time : Duration := 0.0 * Seconds; Compilation_Comment : Comment := Blank_Comment; -- A value of zero indicates load- or execution-time binding: Link_Or_Binding_Time : Duration := 0.0 * Seconds; Linkage_Comment : Comment := Blank_Comment; -- A value of zero indicates load time is included in -- execution time (and cannot be reported separately). Load_Time : Duration := 0.0 * Seconds; Loading_Comment : Comment := Blank_Comment; -- This includes Load_Time if it is not reported above: Execution_Time : Duration := 0.0 * Seconds; Execution_Comment : Comment := Blank_Comment; -- This includes only the units whose source is in the -- compilation; -- it excludes predefined packages which they "with": Object_Code_Size : Size := 0.000 * Kilo_Bytes; Object_Code_Comment : Comment := Blank_Comment; -- This includes pure code only; it excludes data and the -- run-time support library: Code_Image_Size : Size := 0.000 * Kilo_Bytes; Code_Image_Comment : Comment := Blank_Comment; -- This includes it all -- code, data, and run-time support: Maximum_Memory_Used : Size := 0.000 * Kilo_Bytes; Memory_Used_Comment : Comment := Blank_Comment; end record; Number_Of_Programs : constant := <Number actually submitted to vendors>; type Number is range 1 .. Number_Of_Programs; type Result_Array is array (Number) of Result_Record; Results : Result_Array; procedure Put (N : Note) is ... end Put; procedure Put (R : Result_Record) is ... end Put; begin Set_Line(To => 10); Set_Column(To => 31); Put_Line("LA AdaTEC Ada* Fair"); Set_Column(To => 33); Put_Line("30 June, 1984"); Set_Column(To => 29); Put_Line("COMPILER TEST RESULTS"); New_Line; Vendor := <This vendor's name>; Set_Column(To => <TBD>); Put(Vendor); New_Line(2); Compilation_Environment := <Description of the host computer and compiler toolset>; Put(Compilation_Environment); New_Line; Execution_Environment := <Description of the target computer and run-time environment>; Put(Execution_Environment); Set_Line(To => 55); Put("* Ada is a registered trademark of the U.S. Government " & "(Ada Joint Program Office)"); Results := <Vendor's actual results>; for N in Number loop New_Page; Put(Results(N)); end loop; end Summarize; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)akerman.ada 2.3 Date: 9/21/84 -- -- Author: Brian A. Wichmann -- National Physical Laboratory -- Teddington, Middlesex TW11 OLW, UK -- -- Modified by LA AdaTEC to conform to ANSI Standard Ada & to test -- for significance of elapsed time. -- -- [Extracts from: "Latest resuts from the procedure calling test, -- Ackermann's function", B. A. Wichamann, NPL Report DITC 3/82, -- ISSN 0143-7348] -- -- Ackermann's function has been used to measure the procedure calling -- overhead in languages which support recursion [Algol-like languages, -- Assembly Languages, & Basic] -- -- Ackermann's function is a small recursive function .... Although of -- no particular interest in itself, the function does perform other -- operations common to much systems programming (testing for zero, -- incrementing and decrementing integers). The function has two -- parameters M and N, the test being for (3, N) with N in the range -- 1 to 6. -- -- [End of Extract] -- -- The object code size of the Ackermann function should be reported in -- 8-bit bytes, as well as, the Average Number of Instructions Executed -- per Call of the Ackermann function. Also, if the stack space is -- exceeded, report the parameter values used as input to the initial -- invocation of the Ackermann function. -- -- The Average Number of Instructions Executed Per Call should preferably -- be determined by examining the object code and calculating the number -- of instructions executed for a significant number of calls of the -- Ackermann function (see below). If that is not possible, -- please make an estimate based the average execution time per machine -- instruction for the target machine and the average time per call for -- a significant number of calls. Clearly indicate whether the Average -- Number of Instructions Executed Per Call is an estimate or not. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. The number of calls is -- significant if the elapsed time for the initial invocation of the -- Ackermann's function is at least 100 times Duration'Small & at least -- 100 times System.Tick). -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Time_Ackermann is type Real_Time is digits Max_Digits; Start_Time : Time; Elapsed_Time : Duration; Average_Time : Real_Time; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; I, J, K, K1, Calls: Integer; function Ackermann (M, N: Natural) return Natural is begin if M = 0 then return N + 1; elsif N = 0 then return Ackermann (M - 1, 1); else return Ackermann (M - 1, Ackermann (M, N -1 )); end if; end Ackermann; begin K := 16; K1 := 1; I := 1; while K1 < Integer'Last / 512 loop Start_Time := Clock; J := Ackermann (3, I); Elapsed_Time := Clock - Start_Time; if J /= K - 3 then Put_line (" *** Wrong Value ***"); end if; Calls := (512*K1 - 15*K + 9*I + 37) / 3; Put ("Number of Calls = "); Put (Calls, Width => 0); new_line; Put ("Elapsed Time = "); Put (Elapsed_Time, Fore => 0); Put (" seconds -- precision is "); if (Elapsed_Time < 100 * Duration'Small or Elapsed_Time < 100 * System.Tick) then Put_line ("Insignificant"); else Put_line ("Significant"); end if; Average_Time := Real_Time (Elapsed_Time / Calls); Put ("Average Time per call = "); Put (Average_Time, Fore => 0); Put_Line (" seconds"); new_line; I := I + 1; K1 := 4 * K1; K := 2 * K; end loop; Put_Line (" End of Ackermann Test"); exception when Storage_Error => New_line; Put ("Stack space exceeded for Ackermann ( 3, " ); Put (I); Put_line ( ")" ); new_line; Put_Line (" End of Ackermann Test"); end Time_Ackermann; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)boolvec.ada 1.3 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for the "and" operation on the -- elements of a boolean vector -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Iterations large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Boolean_Vector_AND_Test is Iterations : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Elapsed_Time : Duration; Average_Time : Real_Time; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; Vector_Size : constant Positive := 25; type vector is array (1..Vector_Size) of Boolean; v1, v2, vector_result: vector; count: integer := integer'first; -- used in timing loop begin -- Initialize Vectors for N in vector'range loop v1(N) := true; v2(N) := boolean'val (N mod 2); end loop; -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Iterations loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Measure the time including the adding of vector elements Start_Time := Clock; for N in 1 .. Iterations loop count := count + 1; -- prevent optimization vector_result := v1 and v2; end loop; Elapsed_Time := Clock - Start_Time; Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Elapsed_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" iterations"); Average_Time := Real_Time(Elapsed_Time - Loop_Time)/Real_Time(Vector_Size); Put("Average time for " & '"' & "and" & '"' & " of 2 arrays (" & Integer'Image (Vector_Size) & " elements) = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Elapsed_Time - Loop_Time < 100 * Duration'Small or Elapsed_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Boolean_Vector_AND_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)bsearch.ada 1.1 Date: 5/30/84 -- -- Authors: Marion Moon and Bryce Bardin -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- This package implements a generic binary search function. -- It was designed to allow the use of an enumeration type for the table -- index (a feature of possibly dubious utility, but included here for -- uniformity with other generic operations on unconstrained arrays). -- generic type Index is (<>); type Item is limited private; type Table is array (Index range <>) of Item; with function "=" (Left, Right : Item) return Boolean is <>; with function ">" (Left, Right : Item) return Boolean is <>; package Searching is function Index_Of (Key : in Item; Within : in Table) return Index; -- Returns the Index of the Item in Within which matches Key -- if there is one, otherwise raises Not_Found. Not_Found : exception; -- Raised if the search fails. end Searching; package body Searching is function Index_Of (Key : in Item; Within : in Table) return Index is Low : Index := Within'First; Mid : Index; Hi : Index := Within'Last; begin loop if Low > Hi then raise Not_Found; end if; -- Calculate the mean Index value, using an expression -- which can never overflow: Mid := Index'Val(Index'Pos(Low)/2 + Index'Pos(Hi)/2 + (Index'Pos(Low) rem 2 + Index'Pos(Hi) rem 2)/2); if Within(Mid) = Key then return Mid; elsif Within(Mid) > Key then -- This can raise Constraint_Error, but in that case -- the search has failed: Hi := Index'Pred(Mid); else -- This can raise Constraint_Error, but in that case -- the search has failed: Low := Index'Succ(Mid); end if; end loop; exception when Constraint_Error => raise Not_Found; end Index_Of; end Searching; -- This procedure tests the binary search package at the extreme limits -- of its index type. with Searching; with System; use System; with Text_IO; use Text_IO; procedure Main is type Big_Integer is range Min_Int .. Max_Int; type Table is array (Big_Integer range <>) of Character; package Table_Search is new Searching (Big_Integer, Character, Table); use Table_Search; T1 : constant Table (Big_Integer'First .. Big_Integer'First + 2) := "XYZ"; T2 : constant Table (Big_Integer'Last - 3 .. Big_Integer'Last) := "ABCD"; Index : Big_Integer; Key : Character; subtype Alpha is Character range 'A' .. 'Z'; package Big_IO is new Integer_IO (Big_Integer); use Big_IO; procedure Put_Match (Index : Big_Integer; Key : Character) is begin Put("The index for the key value of '" & Key & "' is "); Put(Index, Width => 0); Put('.'); New_Line; end Put_Match; begin begin for C in reverse Alpha loop Key := C; Index := Index_Of (Key, Within => T1); Put_Match(Index, Key); end loop; exception when Not_Found => Put("Key '"); Put(Key); Put_Line("' not found."); end; begin for C in Alpha loop Key := C; Index := Index_Of (Key, Within => T2); Put_Match(Index, Key); end loop; exception when Not_Found => Put("Key '"); Put(Key); Put_Line("' not found."); end; end Main; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)cauchfl.ada 1.1 Date: 6/3/84 -- with text_io; use text_io; procedure cauchy is -- -- This test of floating point accuracy based on computing the inverses -- of Cauchy matricies. These are N x N matricies for which the i, jth -- entry is 1 / (i + j - 1). The inverse is computed using determinants. -- As N increases, the determinant rapidly approaches zero. The inverse -- is computed exactly and then checked by multiplying it by the original -- matrix. -- -- Gerry Fisher -- Computer Sciences Corporation -- May 27, 1984 type REAL is digits 6; type MATRIX is array(POSITIVE range <>, POSITIVE range <>) of REAL; trials : constant := 5; FAILED : Boolean := FALSE; function cofactor(A : MATRIX; i, j : POSITIVE) return MATRIX is B : MATRIX(A'FIRST(1) .. A'LAST(1) - 1, A'FIRST(2) .. A'LAST(2) - 1); x : REAL; begin for p in A'RANGE(1) loop for q in A'RANGE(2) loop x := A(p, q); if p < i and then q < j then B(p, q) := x; elsif p < i and then q > j then B(p, q - 1) := x; elsif p > i and then q < j then B(p - 1, q) := x; elsif p > i and then q > j then B(p - 1, q - 1) := x; end if; end loop; end loop; return B; end cofactor; function det(A : MATRIX) return REAL is D : REAL; k : INTEGER; begin if A'LENGTH = 1 then D := A(A'FIRST(1), A'FIRST(2)); else D := 0.0; k := 1; for j in A'RANGE(2) loop D := D + REAL(k) * A(A'FIRST(1), j) * det(cofactor(A, A'FIRST(1), j)); k := - k; end loop; end if; return D; end det; function init(n : positive) return MATRIX is B : MATRIX(1 .. n, 1 .. n); begin for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := 1.0 / REAL(i + j - 1); end loop; end loop; return B; end init; function inverse(A : MATRIX) return MATRIX is B : MATRIX(A'RANGE(1), A'RANGE(2)); D : REAL := det(A); E : REAL; begin if A'LENGTH = 1 then return (1 .. 1 => (1 .. 1 => 1.0 / D)); end if; for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := REAL((-1) ** (i + j)) * (det(cofactor(A, i, j)) / D); end loop; end loop; -- Now check the inverse for i in A'RANGE loop for j in A'RANGE loop E := 0.0; for k in A'RANGE loop E := E + A(i, k) * B(k, j); end loop; if (i = j and then E /= 1.0) or else (i /= j and then E /= 0.0) then raise PROGRAM_ERROR; end if; end loop; end loop; return B; end inverse; begin put_line("*** TEST Inversion of Cauchy Matricies."); for N in 1 .. trials loop begin declare A : constant MATRIX := init(N); B : constant MATRIX := inverse(A); begin put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " successfully inverted."); end; exception when PROGRAM_ERROR => put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " not successfully inverted."); when NUMERIC_ERROR => put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " appears singular."); when others => put_line("*** REMARK: Unexpected exception raised."); raise; end; end loop; put_line("*** FINISHED Matrix Inversion Test."); end cauchy; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)cauchfx.ada 1.1 Date: 6/3/84 -- with text_io; use text_io; procedure cauchy is -- -- This test of fixed point accuracy based on computing the inverses -- of Cauchy matricies. These are N x N matricies for which the i, jth -- entry is 1 / (i + j - 1). The inverse is computed using determinants. -- As N increases, the determinant rapidly approaches zero. The inverse -- is computed exactly and then checked by multiplying it by the original -- matrix. -- -- Gerry Fisher -- Computer Sciences Corporation -- May 27, 1984 type FIXED is delta 2.0**(-16) range -1000.0 .. +1000.00; type MATRIX is array(POSITIVE range <>, POSITIVE range <>) of FIXED; trials : constant := 5; FAILED : Boolean := FALSE; function cofactor(A : MATRIX; i, j : POSITIVE) return MATRIX is B : MATRIX(A'FIRST(1) .. A'LAST(1) - 1, A'FIRST(2) .. A'LAST(2) - 1); x : FIXED; begin for p in A'RANGE(1) loop for q in A'RANGE(2) loop x := A(p, q); if p < i and then q < j then B(p, q) := x; elsif p < i and then q > j then B(p, q - 1) := x; elsif p > i and then q < j then B(p - 1, q) := x; elsif p > i and then q > j then B(p - 1, q - 1) := x; end if; end loop; end loop; return B; end cofactor; function det(A : MATRIX) return FIXED is D : FIXED; k : INTEGER; begin if A'LENGTH = 1 then D := A(A'FIRST(1), A'FIRST(2)); else D := 0.0; k := 1; for j in A'RANGE(2) loop D := D + k * FIXED(A(A'FIRST(1), j) * det(cofactor(A, A'FIRST(1), j))); k := - k; end loop; end if; return D; end det; function init(n : positive) return MATRIX is B : MATRIX(1 .. n, 1 .. n); begin for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := 1.0 / (i + j - 1); end loop; end loop; return B; end init; function inverse(A : MATRIX) return MATRIX is B : MATRIX(A'RANGE(1), A'RANGE(2)); D : FIXED := det(A); E : FIXED; begin if A'LENGTH = 1 then return (1 .. 1 => (1 .. 1 => FIXED(FIXED(1.0) / D))); end if; for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := ((-1) ** (i + j)) * FIXED(det(cofactor(A, i, j)) / D); end loop; end loop; -- Now check the inverse for i in A'RANGE loop for j in A'RANGE loop E := 0.0; for k in A'RANGE loop E := E + FIXED(A(i, k) * B(k, j)); end loop; if (i = j and then E /= 1.0) or else (i /= j and then E /= 0.0) then raise PROGRAM_ERROR; end if; end loop; end loop; return B; end inverse; begin put_line("*** TEST Inversion of Cauchy Matricies."); for N in 1 .. trials loop begin declare A : constant MATRIX := init(N); B : constant MATRIX := inverse(A); begin put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " successfully inverted."); end; exception when PROGRAM_ERROR => put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " not successfully inverted."); when NUMERIC_ERROR => put_line("*** REMARK: The Cauchy Matrix of size" & integer'image(N) & " appears singular."); when others => put_line("*** REMARK: Unexpected exception raised."); raise; end; end loop; put_line("*** FINISHED Matrix Inversion Test."); end cauchy; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)cauchun.ada 1.1 Date: 6/3/84 -- with universal_integer_arithmetic; use universal_integer_arithmetic; with universal_real_arithmetic; use universal_real_arithmetic; with text_io; use text_io; procedure cauchy is -- -- This test of the Universal Arithmetic Packages computes the inverses -- of Cauchy matricies. These are N x N matricies for which the i, jth -- entry is 1 / (i + j - 1). The inverse is computed using determinants. -- As N increases, the determinant rapidly approaches zero. The inverse -- is computed exactly and then checked by multiplying it by the original -- matrix. -- -- Gerry Fisher -- Computer Sciences Corporation -- May 27, 1984 type MATRIX is array(POSITIVE range <>, POSITIVE range <>) of Universal_real; one : Universal_integer := UI(1); r_one : Universal_real := UR(one, one); r_zero : Universal_real := UR(UI(0), one); trials : constant := 10; FAILED : Boolean := FALSE; function cofactor(A : MATRIX; i, j : POSITIVE) return MATRIX is B : MATRIX(A'FIRST(1) .. A'LAST(1) - 1, A'FIRST(2) .. A'LAST(2) - 1); x : Universal_real; begin for p in A'RANGE(1) loop for q in A'RANGE(2) loop x := A(p, q); if p < i and then q < j then B(p, q) := x; elsif p < i and then q > j then B(p, q - 1) := x; elsif p > i and then q < j then B(p - 1, q) := x; elsif p > i and then q > j then B(p - 1, q - 1) := x; end if; end loop; end loop; return B; end cofactor; function det(A : MATRIX) return Universal_real is D : Universal_real; k : INTEGER; begin if A'LENGTH = 1 then D := A(A'FIRST(1), A'FIRST(2)); else D := r_zero; k := 1; for j in A'RANGE(2) loop D := D + UI(k) * A(A'FIRST(1), j) * det(cofactor(A, A'FIRST(1), j)); k := - k; end loop; end if; return D; end det; function init(n : positive) return MATRIX is B : MATRIX(1 .. n, 1 .. n); begin for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := UR(one, UI(i + j - 1)); end loop; end loop; return B; end init; function inverse(A : MATRIX) return MATRIX is B : MATRIX(A'RANGE(1), A'RANGE(2)); D : Universal_real := det(A); E : Universal_real; begin if A'LENGTH = 1 then return (1 .. 1 => (1 .. 1 => r_one / D)); end if; for i in B'RANGE(1) loop for j in B'RANGE(2) loop B(i, j) := UI((-1) ** (i + j)) * det(cofactor(A, i, j)) / D; end loop; end loop; -- Now check the inverse for i in A'RANGE loop for j in A'RANGE loop E := r_zero; for k in A'RANGE loop E := E + A(i, k) * B(k, j); end loop; if (i = j and then not eql(E, r_one)) or else (i /= j and then not eql(E, r_zero)) then raise PROGRAM_ERROR; end if; end loop; end loop; return B; end inverse; begin put_line("*** TEST Inversion of Cauchy Matricies."); for N in 1 .. trials loop begin declare A : constant MATRIX := init(N); B : constant MATRIX := inverse(A); begin put_line("*** REMARK: The Cauchy Matrix of size " & integer'image(N) & " successfully inverted."); end; exception when PROGRAM_ERROR => put_line("*** FAILED: Matrix of size " & integer'image(N) & " not successfully inverted."); FAILED := True; exit; end; end loop; if not FAILED then put_line("*** PASSED Matrix Inversion Test."); end if; end cauchy; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)char_dir.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for doing various file -- operations using the Direct_IO package with Characters. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Direct_IO; with Calendar; use Calendar; with System; use System; procedure Character_Direct_IO_Test is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Average_Time : Real_Time; Create_Time : Duration; Close_Time : Duration; Open_Time : Duration; Delete_Time : Duration; Read_Time : Duration; Write_Time : Duration; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; package Char_IO is new Direct_IO (Character); use Char_IO; file: Char_IO.file_type; value: character := 'A'; count: integer := integer'first; -- used in timing loop begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Create a file Start_Time := Clock; Char_IO.Create (file, mode => out_file, name => "test_file"); Create_Time := Clock - Start_Time; -- Measure the time of Writing of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Char_IO.write (file, value); end loop; Write_Time := Clock - Start_Time; -- Close a file Start_Time := Clock; Char_IO.Close (file); Close_Time := Clock - Start_Time; -- Open a file Start_Time := Clock; Char_IO.Open (file, mode => in_file, name => "test_file"); Open_Time := Clock - Start_Time; -- Measure the time of Reading of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Char_IO.read (file, value); end loop; Read_Time := Clock - Start_Time; -- Delete a file Start_Time := Clock; Char_IO.Delete (file); Delete_Time := Clock - Start_Time; Put ("Create File Time = "); Put (Create_Time, Fore => 0); put_line (" seconds "); Put ("Close File Time = "); Put (Close_Time, Fore => 0); put_line (" seconds "); Put ("Open File Time = "); Put (Open_Time, Fore => 0); put_line (" seconds "); Put ("Delete File Time = "); Put (Delete_Time, Fore => 0); put_line (" seconds "); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Write_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Writes"); Average_Time := Real_Time(Write_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Write = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; Put("Elapsed time = "); Put(Read_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Reads"); Average_Time := Real_Time(Read_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Read = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Read_Time - Loop_Time < 100 * Duration'Small) or (Read_Time - Loop_Time < 100 * System.Tick) or (Write_Time - Loop_Time < 100 * Duration'Small) or (Write_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Character_Direct_IO_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)char_enm.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for doing various file -- operations using the Text_IO package & the Enumeration_IO subpackage -- with Characters. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Character_Enumeration_IO_Test is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Average_Time : Real_Time; Create_Time : Duration; Close_Time : Duration; Open_Time : Duration; Delete_Time : Duration; Read_Time : Duration; Write_Time : Duration; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; package Char_IO is new Enumeration_IO (Character); file: Text_IO.file_type; value: character := 'A'; count: integer := integer'first; -- used in timing loop begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Create a file Start_Time := Clock; Text_IO.Create (file, mode => out_file, name => "test_file"); Create_Time := Clock - Start_Time; -- Measure the time of Writing of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Char_IO.put (file, value); end loop; Write_Time := Clock - Start_Time; -- Close a file Start_Time := Clock; Text_IO.Close (file); Close_Time := Clock - Start_Time; -- Open a file Start_Time := Clock; Text_IO.Open (file, mode => in_file, name => "test_file"); Open_Time := Clock - Start_Time; -- Measure the time of Reading of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Char_IO.get (file, value); end loop; Read_Time := Clock - Start_Time; -- Delete a file Start_Time := Clock; Text_IO.Delete (file); Delete_Time := Clock - Start_Time; Put ("Create File Time = "); Put (Create_Time, Fore => 0); put_line (" seconds "); Put ("Close File Time = "); Put (Close_Time, Fore => 0); put_line (" seconds "); Put ("Open File Time = "); Put (Open_Time, Fore => 0); put_line (" seconds "); Put ("Delete File Time = "); Put (Delete_Time, Fore => 0); put_line (" seconds "); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Write_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Writes"); Average_Time := Real_Time(Write_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Write = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; Put("Elapsed time = "); Put(Read_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Reads"); Average_Time := Real_Time(Read_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Read = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Read_Time - Loop_Time < 100 * Duration'Small) or (Read_Time - Loop_Time < 100 * System.Tick) or (Write_Time - Loop_Time < 100 * Duration'Small) or (Write_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Character_Enumeration_IO_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)char_txt.ada 1.3 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for doing various file -- operations using the Text_IO package with Characters. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Character_Text_IO_Test is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Average_Time : Real_Time; Create_Time : Duration; Close_Time : Duration; Open_Time : Duration; Delete_Time : Duration; Read_Time : Duration; Write_Time : Duration; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; file: Text_IO.file_type; value: character := 'A'; count: integer := integer'first; -- used in timing loop begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Create a file Start_Time := Clock; Text_IO.Create (file, mode => out_file, name => "test_file"); Create_Time := Clock - Start_Time; -- Measure the time of Writing of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Text_IO.put (file, value); end loop; Write_Time := Clock - Start_Time; -- Close a file Start_Time := Clock; Text_IO.Close (file); Close_Time := Clock - Start_Time; -- Open a file Start_Time := Clock; Text_IO.Open (file, mode => in_file, name => "test_file"); Open_Time := Clock - Start_Time; -- Measure the time of Reading of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Text_IO.get (file, value); end loop; Read_Time := Clock - Start_Time; -- Delete a file Start_Time := Clock; Text_IO.Delete (file); Delete_Time := Clock - Start_Time; Put ("Create File Time = "); Put (Create_Time, Fore => 0); put_line (" seconds "); Put ("Close File Time = "); Put (Close_Time, Fore => 0); put_line (" seconds "); Put ("Open File Time = "); Put (Open_Time, Fore => 0); put_line (" seconds "); Put ("Delete File Time = "); Put (Delete_Time, Fore => 0); put_line (" seconds "); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Write_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Writes"); Average_Time := Real_Time(Write_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Write = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; Put("Elapsed time = "); Put(Read_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Reads"); Average_Time := Real_Time(Read_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Read = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Read_Time - Loop_Time < 100 * Duration'Small) or (Read_Time - Loop_Time < 100 * System.Tick) or (Write_Time - Loop_Time < 100 * Duration'Small) or (Write_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Character_Text_IO_Test;
adatrain@trwspp.UUCP (09/30/84)
------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)floatvec.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for the adding of the -- elements of a large floating point vector -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Vector_Size large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Float_Vector_Add_Test is Vector_Size : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Elapsed_Time : Duration; Average_Time : Real_Time; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; type vector is array (1..Vector_Size) of Float; v1, v2, vector_result: vector; count: integer := integer'first; -- used in timing loop begin -- Initialize Vectors for N in vector'range loop v1(N) := float (N); v2(N) := float (vector'last - N + 1); end loop; -- Measure the timing loop overhead. Start_Time := Clock; for N in vector'range loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Measure the time including the adding of vector elements Start_Time := Clock; for N in vector'range loop count := count + 1; -- prevent optimization vector_result (n) := v1(n) + v2(n); end loop; Elapsed_Time := Clock - Start_Time; Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Elapsed_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" iterations (1 iteration/element)"); Average_Time := Real_Time(Elapsed_Time - Loop_Time)/Real_Time(Vector_Size); Put("Average time for adding each element = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Elapsed_Time - Loop_Time < 100 * Duration'Small or Elapsed_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Float_Vector_Add_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)friend.ada 1.1 Date: 5/30/84 -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- The purpose of this program is to determine how "friendly" the Ada -- compiler is with regard to warning about the use of uninitialized -- objects, exceptions which will always be raised, and both warning -- about and removal of code that will never be executed. -- Compilers may be graded by the number of instances they catch in each -- of the three categories: set/use errors, 'hard' exceptions, and -- 'dead' code removal. A perfect score is: 12, 3, and 4, respectively. -- Detection of set/use errors encountered during execution will not be -- counted in the score even though it may be a useful feature to have. -- Appropriate supporting evidence, such as an assembly listing, must be -- supplied if dead code removal is claimed. -- N.B.: It is not expected that any compiler will get a perfect score! -- package Global is G : Integer; -- uninitialized end Global; with Global; package Renamed is R : Integer renames Global.G; -- "A rose by any other name ..." end Renamed; with Text_IO; use Text_IO; procedure Do_It is begin Put_Line("Should do it."); end Do_It; with Text_IO; use Text_IO; procedure Dont_Do_It is begin Put_Line("Shouldn't have done it."); end Dont_Do_It; procedure Raise_It is begin raise Program_Error; end Raise_It; with Global; use Global; with Renamed; use Renamed; with Do_It; with Dont_Do_It; with Raise_It; procedure Friendly is L : Integer; -- uninitialized Use_1 : Integer := L; -- use before set 1 Use_2 : Integer := G; -- use before set 2 Use_3 : Integer := R; -- use before set 3 Use_4 : Integer; Use_5 : Integer; Use_6 : Integer; Static : constant Integer := 8; Named : constant := 8; procedure Embedded (Data : Integer) is separate; begin Use_4 := L; -- use before set 4 Use_5 := G; -- use before set 5 Use_6 := R; -- use before set 6 Embedded(L); -- use before set 7 Embedded(G); -- use before set 8 Embedded(R); -- use before set 9 if Static = 8 then Do_It; else Dont_Do_It; -- never executed 1 end if; if Static - 4 /= 2**2 then Dont_Do_It; -- never executed 2 else Do_It; end if; if Named mod 4 = 0 then Do_It; else Dont_Do_It; -- never executed 3 end if; if Named/2 + 2 /= 6 then Dont_Do_It; -- never executed 4 else Do_It; end if; Raise_It; -- always raised 1 end Friendly; separate (Friendly) procedure Embedded (Data : Integer) is Use_1 : Integer := L; -- use before set 10 Use_2 : Integer := G; -- use before set 11 Use_3 : Integer := R; -- use before set 12 begin Use_4 := Data; -- (if Data is uninitialized, causes a use before set) raise Program_Error; -- always raised 2 Raise_It; -- always raised 3 end Embedded; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)int_dir.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for doing various file -- operations using the Direct_IO package with Integer. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Direct_IO; with Calendar; use Calendar; with System; use System; procedure Integer_Direct_IO_Test is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Average_Time : Real_Time; Create_Time : Duration; Close_Time : Duration; Open_Time : Duration; Delete_Time : Duration; Read_Time : Duration; Write_Time : Duration; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; package Int_Direct_IO is new Direct_IO (Integer); use Int_Direct_IO; file: Int_Direct_IO.file_type; value: Integer := 5; count: Integer := Integer'first; -- used in timing loop begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Create a file Start_Time := Clock; Int_Direct_IO.Create (file, mode => out_file, name => "test_file"); Create_Time := Clock - Start_Time; -- Measure the time of Writing of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Int_Direct_IO.write (file, value); end loop; Write_Time := Clock - Start_Time; -- Close a file Start_Time := Clock; Int_Direct_IO.Close (file); Close_Time := Clock - Start_Time; -- Open a file Start_Time := Clock; Int_Direct_IO.Open (file, mode => in_file, name => "test_file"); Open_Time := Clock - Start_Time; -- Measure the time of Reading of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Int_Direct_IO.read (file, value); end loop; Read_Time := Clock - Start_Time; -- Delete a file Start_Time := Clock; Int_Direct_IO.Delete (file); Delete_Time := Clock - Start_Time; Put ("Create File Time = "); Put (Create_Time, Fore => 0); put_line (" seconds "); Put ("Close File Time = "); Put (Close_Time, Fore => 0); put_line (" seconds "); Put ("Open File Time = "); Put (Open_Time, Fore => 0); put_line (" seconds "); Put ("Delete File Time = "); Put (Delete_Time, Fore => 0); put_line (" seconds "); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Write_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Writes"); Average_Time := Real_Time(Write_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Write = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; Put("Elapsed time = "); Put(Read_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Reads"); Average_Time := Real_Time(Read_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Read = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Read_Time - Loop_Time < 100 * Duration'Small) or (Read_Time - Loop_Time < 100 * System.Tick) or (Write_Time - Loop_Time < 100 * Duration'Small) or (Write_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Integer_Direct_IO_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)int_text.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for doing various file -- operations using the Text_IO package with Integers. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Integer_Text_IO_Test is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Average_Time : Real_Time; Create_Time : Duration; Close_Time : Duration; Open_Time : Duration; Delete_Time : Duration; Read_Time : Duration; Write_Time : Duration; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; file: Text_IO.file_type; value: Integer := 5; count: Integer := Integer'first; -- used in timing loop begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Create a file Start_Time := Clock; Text_IO.Create (file, mode => out_file, name => "test_file"); Create_Time := Clock - Start_Time; -- Measure the time of Writing of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Int_IO.put (file, value); end loop; Write_Time := Clock - Start_Time; -- Close a file Start_Time := Clock; Text_IO.Close (file); Close_Time := Clock - Start_Time; -- Open a file Start_Time := Clock; Text_IO.Open (file, mode => in_file, name => "test_file"); Open_Time := Clock - Start_Time; -- Measure the time of Reading of value Start_Time := Clock; for N in 1 .. Times loop count := count + 1; Int_IO.get (file, value); end loop; Read_Time := Clock - Start_Time; -- Delete a file Start_Time := Clock; Text_IO.Delete (file); Delete_Time := Clock - Start_Time; Put ("Create File Time = "); Put (Create_Time, Fore => 0); put_line (" seconds "); Put ("Close File Time = "); Put (Close_Time, Fore => 0); put_line (" seconds "); Put ("Open File Time = "); Put (Open_Time, Fore => 0); put_line (" seconds "); Put ("Delete File Time = "); Put (Delete_Time, Fore => 0); put_line (" seconds "); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Write_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Writes"); Average_Time := Real_Time(Write_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Write = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; Put("Elapsed time = "); Put(Read_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" Reads"); Average_Time := Real_Time(Read_Time - Loop_Time)/Real_Time(Times); Put("Average time for a Read = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Read_Time - Loop_Time < 100 * Duration'Small) or (Read_Time - Loop_Time < 100 * System.Tick) or (Write_Time - Loop_Time < 100 * Duration'Small) or (Write_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Integer_Text_IO_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)intvec.ada 1.2 Date: 9/21/84 -- -- Author: Edward Colbert -- Ada Technology Group -- Information Software Systems Lab -- Defense Systems Group -- TRW -- Redondo Beach, CA -- -- This program measures the time required for the adding of the -- elements of a large integer vector -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Vector_Size large enough to provide at least two significant -- digits in the average times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. -- with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Integer_Vector_Add_Test is Vector_Size : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Elapsed_Time : Duration; Average_Time : Real_Time; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; type vector is array (1..Vector_Size) of integer; v1, v2, vector_result: vector; count: integer := integer'first; -- used in timing loop begin -- Initialize Vectors for N in vector'range loop v1(N) := N; v2(N) := vector'last - N + 1; end loop; -- Measure the timing loop overhead. Start_Time := Clock; for N in vector'range loop count := count + 1; -- prevent optimization end loop; Loop_Time := Clock - Start_Time; -- Measure the time including the adding of vector elements Start_Time := Clock; for N in vector'range loop count := count + 1; -- prevent optimization vector_result (n) := v1(n) + v2(n); end loop; Elapsed_Time := Clock - Start_Time; Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Elapsed_Time, Fore => 0); Put(" seconds for "); Put(Vector_Size, Width => 0); Put_Line(" Elements"); Average_Time := Real_Time(Elapsed_Time - Loop_Time)/Real_Time(Vector_Size); Put("Average time for adding each element = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Elapsed_Time - Loop_Time < 100 * Duration'Small or Elapsed_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Integer_Vector_Add_Test; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)lowlev.ada 1.1 Date: 5/30/84 -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- The following program tests length clauses in conjunction with -- unchecked conversion. -- -- Before running the test, No_Of_Bits must be set to the base 2 logarithm -- of the successor of System.Max_Int, i.e., the total number of bits in -- the largest integer type supported. -- Note: The place where this change is to be made is flagged by a -- comment prefixed by "--!". -- -- For a compiler to pass this test, it must obey the length clauses -- and instantiate and use the unchecked conversions correctly. -- The output will consist of Cases sets of three identical values. -- If a conversion fails, the line will be flagged as an error. A summary -- error count and a "pass/fail" message will be output. -- Ideally, an assembly listing should be provided which demonstrates -- the efficiency of the compiled code. -- with Text_IO; use Text_IO; with Unchecked_Conversion; with System; procedure Change_Types is --! Change this to Log2 (System.Max_Int + 1): No_Of_Bits : constant := 32; Cases : constant := 100; type Int is range 0 .. 2**No_Of_Bits - 1; for Int'Size use No_Of_Bits; --! Change this to System.Max_Int/(Cases - 1): Increment : constant Int := System.Max_Int/(Cases - 1); type Bit is (Off, On); for Bit use (Off => 0, On => 1); for Bit'Size use 1; subtype Bits is Positive range 1 .. No_Of_Bits; type Bit_String is array (Bits) of Bit; for Bit_String'Size use No_Of_Bits; I : Int; J : Int; B : Bit_String; Errors : Natural := 0; Column : constant := 16; package Int_IO is new Integer_IO(Int); use Int_IO; package Nat_IO is new Integer_IO(Natural); use Nat_IO; procedure Put (B : Bit_String) is begin Put("2#"); for N in Bits loop if B(N) = On then Put("1"); else Put("0"); end if; end loop; Put("#"); end Put; function To_Bit_String is new Unchecked_Conversion (Int, Bit_String); function To_Int is new Unchecked_Conversion (Bit_String, Int); begin for N in 1 .. Cases loop I := Int(N-1) * Increment; B := To_Bit_String(I); J := To_Int(B); if J /= I then Errors := Errors + 1; Put("*** ERROR ***"); end if; Set_Col(To => Column); Put("I = "); Put(I, Base => 2); Put_Line(","); Set_Col(To => Column); Put("B = "); Put(B); Put_Line(","); Set_Col(To => Column); Put("J = "); Put(J, Base => 2); Put("."); New_Line(2); end loop; New_Line(2); if Errors > 0 then Put_Line("*** TEST FAILED! ***"); if Errors = 1 then Put_Line("There was 1 error."); else Put("There were "); Put(Errors, Width => 0); Put_Line(" errors."); end if; else Put_Line("TEST PASSED!"); Put_Line("There were no errors."); end if; end Change_Types; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)proccal.ada 1.2 Date: 9/21/84 -- -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- This program measures the time required for simple procedure calls -- with scalar parameters. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average calling times, i.e., the differences between -- the elapsed times and the corresponding loop times for each form of -- call should be greater than 100 times Duration'Small & greater than -- 100 times System.Tick. with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Procedure_Call is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Elapsed_Time : Duration; Average_Time : Real_Time; Insufficient_Precision : Boolean := False; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; type Cases is range 1 .. 4; Kind : array (Cases) of String (1 .. 22) := ("No parameter call: ", "In parameter call: ", "Out parameter call: ", "In Out parameter call:"); -- This package is used to prevent elimination of a "null" call -- by a smart compiler. package Prevent is Counter : Natural := 0; procedure Prevent_Optimization; end Prevent; use Prevent; procedure Call is begin Prevent_Optimization; end Call; procedure Call_In (N : in Natural) is begin Counter := N; end Call_In; procedure Call_Out (N : out Natural) is begin N := Counter; end Call_Out; procedure Call_In_Out (N : in out Natural) is begin N := Counter; end Call_In_Out; -- This procedure determines if Times is large enough to assure adequate -- precision in the timings. procedure Check_Precision is begin if (Elapsed_Time - Loop_Time < 100 * Duration'Small or Elapsed_Time - Loop_Time < 100 * System.Tick) then Insufficient_Precision := True; end if; end Check_Precision; package body Prevent is procedure Prevent_Optimization is begin Counter := Counter + 1; end Prevent_Optimization; end Prevent; begin for Case_Number in Cases loop -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop case Case_Number is when 1 => Prevent_Optimization; when 2 => Counter := N; when 3 => Counter := N; when 4 => Counter := N; end case; end loop; Loop_Time := Clock - Start_Time; -- Measure the time including the procedure call. Start_Time := Clock; for N in 1 .. Times loop case Case_Number is when 1 => Call; when 2 => Call_In(Counter); when 3 => Call_Out(Counter); when 4 => Call_In_Out(Counter); end case; end loop; Elapsed_Time := Clock - Start_Time; Check_Precision; -- Calculate timing and output the result Put(Kind(Case_Number)); New_Line(2); Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Put("Elapsed time = "); Put(Elapsed_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Average_Time := Real_Time(Elapsed_Time - Loop_Time)/Real_Time(Times); New_Line; Put("Average time for a call = "); Put(Average_Time); Put_Line(" seconds"); New_Line(3); end loop; if Insufficient_Precision then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("TEST PASSED"); end if; end Procedure_Call; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- ---------------------------------------------------------------------- -- -- QUICK SORT BENCHMARK -- -- Version: @(#)qsortpar.ada 1.1 Date: 6/5/84 -- -- Gerry Fisher -- Computer Sciences Corporation -- -- May 26, 1984 -- -- This benchmark consists of two versions of the familiar quick -- sort algorithm: a parallel version and a sequential version. -- A relatively small vector (length 100) is sorted into ascending -- sequence. The number of comparisons and exchanges is counted. -- In the parallel version separate tasks are created to sort the -- two subvectors created by partitioning the vector. Each task -- invokes the quicksort procedure. The parallel version is -- functionally equivalent to the sequential version and should -- require the same number of comparisions and exchanges. A check -- is made to verify that this is so. Also, the sorted vector is -- checked to verify that the sort has been performed correctly. -- Control is exercised so that no more than fourteen tasks are -- created when sorting the vector. -- -- The sorting is repeated a number of times to obtain a measurable -- amount of execution time. -- -- The important measure for this benchmark is the ratio of the -- execution time of the parallel version to that of the sequential -- version. This will give some indication of task activation and -- scheduling overhead. -- -- One file is used for both versions. The boolean constant "p" -- indicates whether the parallel or serial version of the algorithm -- is to be used. Simply set this constant TRUE for the parallel -- test and FALSE for the sequential test. A difference in code -- size between the two tests may indicate that conditional -- compilation is supported by the compiler. -- ------------------------------------------------------------------------ with text_io; use text_io; procedure main is failed : exception; type vector is array(integer range <>) of integer; type stats is record c, e : integer := 0; end record; p : constant boolean := true; -- true for parallel algorithm n : constant integer := 100; -- size of vector to be sorted m : constant integer := 100; -- number of times to sort vector x : vector(1 .. n); y : stats; procedure Quick_sort(A : in out vector; w : out stats) is lb : constant integer := A'first; ub : constant integer := A'last; k : integer; c, e : integer := 0; u, v : stats; function partition(L, U : integer) return integer is q, r, i, j : integer; begin r := A((U + L)/2); i := L; j := U; while i < j loop while A(i) < r loop c := c + 1; i := i + 1; end loop; while A(j) > r loop c := c + 1; j := j - 1; end loop; c := c + 2; if i <= j then e := e + 1; q := A(i); A(i) := A(j); A(j) := q; i := i + 1; j := j - 1; end if; end loop; if j > L then return j; else return L; end if; end partition; begin if lb < ub then k := partition(lb, ub); if ub > lb + 15 then if p then declare task S1; task body S1 is begin Quick_sort(A(lb .. k), u); end S1; task S2; task body S2 is begin Quick_sort(A(k + 1 .. ub), v); end S2; begin null; end; else Quick_sort(A(lb .. k), u); Quick_sort(A(k + 1 .. ub), v); end if; elsif ub > lb + 1 then Quick_sort(A(lb .. k), u); Quick_sort(A(k + 1 .. ub), v); end if; e := e + u.e + v.e; c := c + u.c + v.c; end if; w := (c, e); end Quick_sort; begin set_line_length(count(50)); if p then put_line("*** Starting Parallel Quick Sort Benchmark"); else put_line("*** Starting Sequential Quick Sort Benchmark"); end if; for k in 1 .. m loop for i in x'range loop x(i) := x'last - i + 1; end loop; Quick_sort(x, y); for i in x'first .. x'last - 1 loop if x(i) > x(i + 1) then raise failed; end if; end loop; put("."); end loop; new_line; if y.c /= 782 or else y.e /= 148 then put_line("*** FAILED Wrong number of comparisons or exchanges"); else put_line("*** PASSED Sorting test"); end if; exception when failed => put_line("*** FAILED Vector not sorted"); end main; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- ---------------------------------------------------------------------- -- -- QUICK SORT BENCHMARK -- -- Version: @(#)qsortseq.ada 1.1 Date: 6/5/84 -- -- Gerry Fisher -- Computer Sciences Corporation -- May 27, 1984 -- -- -- This benchmark consists of two versions of the familiar quick -- sort algorithm: a parallel version and a sequential version. -- A relatively small vector (length 100) is sorted into ascending -- sequence. The number of comparisons and exchanges is counted. -- In the parallel version separate tasks are created to sort the -- two subvectors created by partitioning the vector. Each task -- invokes the quicksort procedure. The parallel version is -- functionally equivalent to the sequential version and should -- require the same number of comparisions and exchanges. A check -- is made to verify that this is so. Also, the sorted vector is -- checked to verify that the sort has been performed correctly. -- Control is exercised so that no more than fourteen tasks are -- created when sorting the vector. -- -- The sorting is repeated a number of times to obtain a measurable -- amount of execution time. -- -- The important measure for this benchmark is the ratio of the -- execution time of the parallel version to that of the sequential -- version. This will give some indication of task activation and -- scheduling overhead. -- -- One file is used for both versions. The boolean constant "p" -- indicates whether the parallel or serial version of the algorithm -- is to be used. Simply set this constant TRUE for the parallel -- test and FALSE for the sequential test. A difference in code -- size between the two tests may indicate that conditional -- compilation is supported by the compiler. -- -------------------------------------------------------------------- with text_io; use text_io; procedure main is failed : exception; type vector is array(integer range <>) of integer; type stats is record c, e : integer := 0; end record; p : constant boolean := false; -- true for parallel algorithm n : constant integer := 100; -- size of vector to be sorted m : constant integer := 100; -- number of times to sort vector x : vector(1 .. n); y : stats; procedure Quick_sort(A : in out vector; w : out stats) is lb : constant integer := A'first; ub : constant integer := A'last; k : integer; c, e : integer := 0; u, v : stats; function partition(L, U : integer) return integer is q, r, i, j : integer; begin r := A((U + L)/2); i := L; j := U; while i < j loop while A(i) < r loop c := c + 1; i := i + 1; end loop; while A(j) > r loop c := c + 1; j := j - 1; end loop; c := c + 2; if i <= j then e := e + 1; q := A(i); A(i) := A(j); A(j) := q; i := i + 1; j := j - 1; end if; end loop; if j > L then return j; else return L; end if; end partition; begin if lb < ub then k := partition(lb, ub); if ub > lb + 15 then if p then declare task S1; task body S1 is begin Quick_sort(A(lb .. k), u); end S1; task S2; task body S2 is begin Quick_sort(A(k + 1 .. ub), v); end S2; begin null; end; else Quick_sort(A(lb .. k), u); Quick_sort(A(k + 1 .. ub), v); end if; elsif ub > lb + 1 then Quick_sort(A(lb .. k), u); Quick_sort(A(k + 1 .. ub), v); end if; e := e + u.e + v.e; c := c + u.c + v.c; end if; w := (c, e); end Quick_sort; begin set_line_length(count(50)); if p then put_line("*** Starting Parallel Quick Sort Benchmark"); else put_line("*** Starting Sequential Quick Sort Benchmark"); end if; for k in 1 .. m loop for i in x'range loop x(i) := x'last - i + 1; end loop; Quick_sort(x, y); for i in x'first .. x'last - 1 loop if x(i) > x(i + 1) then raise failed; end if; end loop; put("."); end loop; new_line; if y.c /= 782 or else y.e /= 148 then put_line("*** FAILED Wrong number of comparisons or exchanges"); else put_line("*** PASSED Sorting test"); end if; exception when failed => put_line("*** FAILED Vector not sorted"); end main; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)rendez.ada 1.2 Date: 9/21/84 -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- This program measures the time required for a simple rendezvous. -- -- Note: In order for the measurement to be meaningful, it must be the -- only program executing while the test is run. -- -- Please set Times large enough to provide at least two significant -- digits in the average rendezvous times, i.e., the difference between -- the elapsed time and the loop time must be at least 100 times -- Duration'Small & at least 100 times System.Tick. with Text_IO; use Text_IO; with Calendar; use Calendar; with System; use System; procedure Rendezvous is Times : constant Positive := 1000; type Real_Time is digits Max_Digits; Start_Time : Time; Loop_Time : Duration; Elapsed_Time : Duration; Average_Time : Real_Time; package Duration_IO is new Fixed_IO (Duration); use Duration_IO; package Real_Time_IO is new Float_IO (Real_Time); use Real_Time_IO; package Int_IO is new Integer_IO (Integer); use Int_IO; task T is entry Call; end T; -- This package is used to prevent elimination of the "null" timing loop -- by a smart compiler. package Prevent is Count : Natural := 0; procedure Prevent_Optimization; end Prevent; use Prevent; task body T is begin loop select accept Call; or terminate; end select; end loop; end T; package body Prevent is procedure Prevent_Optimization is begin Count := Count + 1; end Prevent_Optimization; end Prevent; begin -- Measure the timing loop overhead. Start_Time := Clock; for N in 1 .. Times loop Prevent_Optimization; end loop; Loop_Time := Clock - Start_Time; -- Measure the time including rendezvous. Start_Time := Clock; for N in 1 .. Times loop Prevent_Optimization; T.Call; end loop; Put("Loop time = "); Put(Loop_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Elapsed_Time := Clock - Start_Time; Put("Elapsed time = "); Put(Elapsed_Time, Fore => 0); Put(" seconds for "); Put(Times, Width => 0); Put_Line(" iterations"); Average_Time := Real_Time(Elapsed_Time - Loop_Time)/Real_Time(Times); Put("Average time for no-parameter rendezvous = "); Put(Average_Time, Fore => 0); Put_Line(" seconds"); New_Line; if (Elapsed_Time - Loop_Time < 100 * Duration'Small or Elapsed_Time - Loop_Time < 100 * System.Tick) then Put_Line("** TEST FAILED (due to insufficient precision)! **"); else Put_Line("** TEST PASSED **"); end if; end Rendezvous; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)sets.ada 1.2 Date: 9/20/84 -- -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- This is a highly portable implementation of sets in Ada. -- -- N. B.: Vendors are invited to supply listings which demonstrate -- the quality of the code generated. -- generic type Element is (<>); with function Image (E : Element) return String is Element'Image; package Sets is type Set is private; -- A set of elements. Empty_Set : constant Set; -- The set of no elements. Full_Set : constant Set; -- The set of all elements. function "and" (Left, Right : Set) return Set; -- Returns the conjunction (intersection) of two sets. -- Usage: S1 and S2 function "or" (Left, Right : Set) return Set; -- Returns the inclusive disjunction (union) of two sets. -- Usage: S1 or S2 function "xor" (Left, Right : Set) return Set; -- Returns the exclusive disjunction of two sets. -- Usage: S1 xor S2 function "not" (Right : Set) return Set; -- Returns the negation (complement) of a set, i.e., the set of -- all elements not in Right. -- Usage: not S function "-" (Left, Right : Set) return Set; -- Returns the difference of two sets, i.e., the set of elements -- in Left which are not in Right. -- Usage: S1 - S2 function "+" (Left : Element; Right : Set) return Set; -- Adds an element to a set. -- Returns the union (or) of an element with a set. -- Usage: E + S function "+" (Left : Set; Right : Element) return Set; -- Adds an element to a set. -- Returns the union (or) of an element with a set. -- Usage: S + E function "+" (Right : Element) return Set; -- Makes an element into a Set. -- Returns the union of the element with the Empty_Set. -- Usage: + E function "+" (Left, Right : Element) return Set; -- Combines two elements into a Set. -- Returns the union (or) of two elements with the Empty_Set. -- Usage: E1 + E2 function "-" (Left : Set; Right : Element) return Set; -- Deletes an element from a set, i.e., removes it from the set -- if it is currently a member of the set, otherwise it returns -- the original set. -- Usage: S - E -- This function is predefined: -- function "=" (Left, Right : Set) return Boolean; -- Tests whether Left is identical to Right. -- Usage: S1 = S2 function "<=" (Left, Right : Set) return Boolean; -- Tests whether Left is contained in Right, i.e., whether Left -- is a subset of Right. -- Usage: S1 <= S2 function Is_Member (S : Set; E : Element) return Boolean; -- Tests an element for membership in a set. -- Returns true if an element is in a set. -- Usage: Is_Member (S, E) procedure Put (S : Set); -- Prints a set. -- Usage: Put (S) private type Set is array (Element) of Boolean; -- A set of elements. Empty_Set : constant Set := (Element => False); -- The set of no elements. Full_Set : constant Set := (Element => True); -- The set of all elements. pragma Inline ("and"); pragma Inline ("or"); pragma Inline ("xor"); pragma Inline ("not"); pragma Inline ("-"); pragma Inline ("+"); pragma Inline ("<="); pragma Inline ("Is_Member"); end Sets; with Text_IO; use Text_IO; package body Sets is type Bool is array (Element) of Boolean; function "and" (Left, Right : Set) return Set is begin return Set(Bool(Left) and Bool(Right)); end "and"; function "or" (Left, Right : Set) return Set is begin return Set(Bool(Left) or Bool(Right)); end "or"; function "xor" (Left, Right : Set) return Set is begin return Set(Bool(Left) xor Bool(Right)); end "xor"; function "not" (Right : Set) return Set is begin return Set(not Bool(Right)); end "not"; function "-" (Left, Right : Set) return Set is begin return (Left and not Right); end "-"; function "+" (Left : Element; Right : Set) return Set is Temp : Set := Right; begin Temp(Left) := True; return Temp; end "+"; function "+" (Left : Set; Right : Element) return Set is Temp : Set := Left; begin Temp(Right) := True; return Temp; end "+"; function "+" (Right : Element) return Set is begin return Empty_Set + Right; end "+"; function "+" (Left, Right : Element) return Set is begin return Empty_Set + Left + Right; end "+"; function "-" (Left : Set; Right : Element) return Set is Temp : Set := Left; begin Temp(Right) := False; return Temp; end "-"; function "<=" (Left, Right : Set) return Boolean is begin return ((Left and not Right) = Empty_Set); end "<="; function Is_Member (S : Set; E : Element) return Boolean is begin return (S(E) = True); end Is_Member; procedure Put (S : Set) is Comma_Needed : Boolean := False; begin Text_IO.Put ("{"); for E in Element loop if S(E) then if Comma_Needed then Text_IO.Put (","); end if; Text_IO.Put (Image(E)); Comma_Needed := True; end if; end loop; Text_IO.Put ("}"); New_Line; end Put; end Sets; -- This procedure tests the set package. -- Its output is self-explanatory. with Text_IO; use Text_IO; with Sets; procedure Main is type Color is (Red, Yellow, Green, Blue); package Color_Set is new Sets(Color); use Color_Set; X, Y, Z : Set; procedure Put_Set (Name : String; S : Set) is begin Put (Name); Put (" = "); Put (S); end Put_Set; procedure Compare_Set (S_String : String; S : Set; T_String : String; T : Set) is begin if S = T then Put (S_String); Put (" is identical to "); Put (T_String); New_Line; end if; if S /= T then Put (S_String); Put (" is not identical to "); Put (T_String); New_Line; end if; if S <= T then Put (S_String); Put (" is a subset of "); Put (T_String); New_Line; end if; if T <= S then Put (T_String); Put (" is a subset of "); Put (S_String); New_Line; end if; end Compare_Set; procedure Test_Membership (C : Color; S_String : String; S : Set) is begin Put (Color'Image(C)); if Is_Member(S,C) then Put (" is a member of "); else Put (" is not a member of "); end if; Put (S_String); New_Line; end Test_Membership; begin X := Empty_Set; Put_Line ("X := Empty_Set"); Put_Set ("X",X); Y := Empty_Set; Put_Line ("Y := Empty_Set"); Put_Set ("Y",Y); Compare_Set ("X",X,"Y",Y); Y := Full_Set; Put_Line ("Y := Full_Set"); Put_Set ("Y",Y); Compare_Set ("X",X,"Y",Y); X := not X; Put_Line ("X := not X"); Put_Set ("X",X); Compare_Set ("X",X,"Y",Y); Y := Empty_Set + Blue; Put_Line ("Y := Empty_Set + Blue"); Put_Set ("Y",Y); Y := + Yellow; Put_Line ("Y := + Yellow"); Put_Set ("Y",Y); Y := Blue + Y; Put_Line ("Y := Blue + Y"); Put_Set ("Y",Y); X := Full_Set - Red; Put_Line ("X := Full_Set - Red"); Put_Set ("X",X); Test_Membership (Red,"X",X); Test_Membership (Yellow,"X",X); Compare_Set ("X",X,"Y",Y); Z := X - Y; Put_Line ("Z := X - Y"); Put_Set ("Z",Z); Z := Y - X; Put_Line ("Z := Y - X"); Put_Set ("Z",Z); X := Green + Blue + Yellow + Red; Put_Line ("X := Green + Blue + Yellow + Red"); Put_Set ("X",X); X := Green + Blue; Put_Line ("X := Green + Blue"); Put_Set ("X",X); Z := X or Y; Put_Line ("Z := X or Y"); Put_Set ("Z",Z); Z := X and Y; Put_Line ("Z := X and Y"); Put_Set ("Z",Z); Z := X xor Y; Put_Line ("Z := X xor Y"); Put_Set ("Z",Z); end Main; ------------------------------------------------------------------- --------------------- Next Program ----------------------------- ------------------------------------------------------------------- -- -- Version: @(#)shared.ada 1.1 Date: 5/30/84 -- -- -- Author: Bryce Bardin -- Ada Projects Section -- Software Engineering Division -- Ground Systems Group -- Hughes Aircraft Company -- Fullerton, CA -- -- This program illustrates the use of tasking to provide shared access -- to global variables. N.B.: The values it outputs may vary from run -- to run depending on how tasking is implemented. -- A "FIFO" solution to the READERS/WRITERS problem. -- Authors: Gerald Fisher and Robert Dewar. -- (Modified by Bryce Bardin to terminate gracefully.) -- May be used to provide shared access to objects by an arbitrary number of -- readers and writers which are serviced in order from a single queue. -- Writers are given uninterrupted access for updates and readers are assured -- that updates are indivisible and therefore complete when read access is -- granted. -- -- If C is a task object of type Control and O is an object which is to be -- shared between readers and writers using C, then: -- -- readers should do: -- -- C.Start(Read); -- <read all or part of O> -- C.Stop; -- -- and writers should do: -- -- C.Start(Write); -- <update all or part of O> -- C.Stop; package Readers_Writers is type Service is (Read, Write); task type Control is entry Start (Mode : Service); -- start readers or writers entry Stop; -- stop readers or writers end Control; end Readers_Writers; package body Readers_Writers is task body Control is Read_Count : Natural := 0; begin loop select -- remove the first reader or writer from the queue accept Start (Mode : Service) do if Mode = Read then Read_Count := Read_Count + 1; else -- when writer, wait for readers which have already -- started to finish before allowing the writer to -- perform the update while Read_Count > 0 loop -- when a write is pending, readers stop here accept Stop; Read_Count := Read_Count - 1; end loop; end if; end Start; if Read_Count = 0 then -- when writer, wait for writer to stop before allowing -- other readers or writers to start accept Stop; end if; or -- when no write is pending, readers stop here accept Stop; Read_Count := Read_Count -1; or -- quit when everyone agrees to do so terminate; end select; end loop; end Control; end Readers_Writers; -- This package allows any number of concurrent programs to read and/or -- indivisibly write a particular (possibly composite) variable object -- without interference and in FIFO order. Similar packages can be -- constructed to perform partial reads and writes of composite objects. -- If service cannot be started before the appropriate time limit expires, -- the exception Timed_Out will be raised. (By default, service must be -- started within Duration'Last (24+) hours. Setting the time limits to -- 0.0 will require immediate service.) -- generic type Object_Type is private; Object : in out Object_Type; Read_Time_Limit : in Duration := Duration'Last; Write_Time_Limit : in Duration := Duration'Last; -- for testing only with procedure Read_Put (Item : in Object_Type) is <>; -- for testing only with procedure Write_Put (Item : in Object_Type) is <>; -- for testing only with procedure Copy (From : in Object_Type; To : in out Object_Type); package Shared_Variable is -- for testing only: Item made "in out" instead of "out" procedure Read (Item : in out Object_Type); procedure Write (Item : in Object_Type); Timed_Out : exception; end Shared_Variable; with Readers_Writers; use Readers_Writers; package body Shared_Variable is C : Control; -- for testing only: Item made "in out" instead of "out" procedure Read (Item : in out Object_Type) is begin select C.Start(Read); or delay Read_Time_Limit; raise Timed_Out; end select; -- for testing only; this allows the scheduler to screw up! Copy(From => Object, To => Item); -- temporarily replaces -- Item := Object; -- for testing only Read_Put(Item); C.Stop; end Read; procedure Write (Item : in Object_Type) is begin select C.Start(Write); or delay Write_Time_Limit; raise Timed_Out; end select; -- for testing only; this allows the scheduler to screw up! Copy(From => Item, To => Object); -- temporarily replaces Object := Item; -- for testing only Write_Put(Item); C.Stop; end Write; end Shared_Variable; with Shared_Variable; package Encapsulate is Max : constant := 2; subtype Index is Positive range 1 .. Max; type Composite is array (Index) of Integer; procedure Read (C : out Composite); procedure Write (C : in Composite); -- This is a help function for testing function Set_To (I : Integer) return Composite; -- This is a help function for testing function Value_Of (C : Composite) return Integer; -- This entry is used to serialize debug output to Standard_Output task Msg is entry Put (S : String); end Msg; end Encapsulate; with Text_IO; package body Encapsulate is Shared : Composite; function Set_To (I : Integer) return Composite is Temp : Composite; begin for N in Index loop Temp(N) := I; end loop; return Temp; end Set_To; function Value_Of (C : Composite) return Integer is begin return C(Index'First); end Value_Of; -- for testing only; this allows the scheduler to overlap readers and -- writers and thus screw up if Readers_Writers doesn't do its job. -- it also checks that the copy is consistent. procedure Copy (From : in Composite; To : in out Composite) is begin for I in Index loop To(I) := From(I); -- delay so that another access could be made: delay 0.5; end loop; -- test for consistency: for I in Index range Index'Succ(Index'First) .. Index'Last loop if To(I) /= To(Index'First) then raise Program_Error; end if; end loop; end Copy; procedure Read_Put (Item : Composite) is begin Msg.Put(Integer'Image(Value_Of(Item)) & " read"); end Read_Put; procedure Write_Put (Item : Composite) is begin Msg.Put(Integer'Image(Value_Of(Item)) & " written"); end Write_Put; task body Msg is begin loop select accept Put (S : String) do Text_IO.Put (S); Text_IO.New_Line; end Put; or terminate; end select; end loop; end Msg; package Share is new Shared_Variable (Object_Type => Composite, Object => Shared, Read_Put => Read_Put, Write_Put => Write_Put, Copy => Copy); use Share; procedure Read (C : out Composite) is Temp : Composite; begin Share.Read(Temp); C := Temp; end Read; procedure Write (C : in Composite) is begin Share.Write(C); end Write; begin Shared := Set_To (0); end Encapsulate; with Encapsulate; use Encapsulate; with Text_IO; use Text_IO; procedure Test_Shared is Local : Composite := Set_To (-1); task A; task B; task C; procedure Put(C : Character; I : Integer); task body A is begin Read(Local); Put('A',Value_Of(Local)); Write(Set_To(1)); Read(Local); Put('A',Value_Of(Local)); Write(Set_To(2)); Read(Local); Put('A',Value_Of(Local)); end A; task body B is begin Read(Local); Put('B',Value_Of(Local)); Write(Set_To(3)); Read(Local); Put('B',Value_Of(Local)); end B; task body C is begin Write(Set_To(4)); Read(Local); Put('C',Value_Of(Local)); Write(Set_To(5)); Read(Local); Put('C',Value_Of(Local)); end C; procedure Put(C : Character; I : Integer) is begin Msg.Put("Task " & C & " read the value " & Integer'Image(I)); end Put; begin null; end Test_Shared;