-- $Id: heapsort.gnat,v 1.0 2003/06/11 12:10:00 dada Exp $ -- http://dada.perl.it/shootout/ -- Ada 95 code by C.C. -- Annotated Ada Reference Manual ISO/IEC 8652:1995: http://www.ada-auth.org/ with System, Ada.Command_Line, Text_IO; procedure Heapsort is type Real is digits Positive'Max (15, System.Max_Digits); package Rio is new Text_IO.Float_IO (Num => Real); package Random_Real is function Gen_Random (Supr : Real) return Real; pragma Inline (Gen_Random); end Random_Real; package body Random_Real is IM : constant Positive := 139968; IA : constant Integer := 3877; IC : constant Integer := 29573; Last : Integer := 42; function Gen_Random (Supr : Real) return Real is pragma Suppress (Overflow_Check); pragma Suppress (Range_Check); begin Last := (Last * IA + IC) mod IM; return Supr * Real (Last) / Real (IM); end Gen_Random; end Random_Real; type Range_Int is new Integer; subtype Offset_Int is Range_Int; type Real_Array is array (Range_Int range <>) of Real; type Real_Array_Ptr is access Real_Array; procedure Heapsort (A : in out Real_Array) is pragma Suppress (Overflow_Check); pragma Suppress (Index_Check); pragma Suppress (Range_Check); subtype Range_Positive is Range_Int; First : constant Range_Int := A'First; -- might be <= -1 IR : Range_Positive; One : constant Offset_Int := 1; Minus_One : constant Offset_Int := -1; First_Minus_1 : constant Range_Int := First + Minus_One; First_Plus_1 : constant Range_Int := First + One; RRA : Real; L : Offset_Int := One + (A'Length / 2); begin if A'Length <= 0 then return; end if; IR := A'Last; loop if L > One then L := L - One; RRA := A (First_Minus_1 + L); else RRA := A (IR); A (IR) := A (First); if IR <= First_Plus_1 then A (First) := RRA; exit; else IR := IR + Minus_One; end if; end if; declare K1 : Range_Positive := First_Minus_1 + L; K2 : Range_Positive := K1 + L; begin while K2 <= IR loop if K2 < IR then if A (K2) < A (K2 + One) then K2 := K2 + One; end if; end if; if RRA < A (K2) then A (K1) := A (K2); K1 := K2; K2 := K1 + (K1 - First_Minus_1); else K2 := IR + One; end if; end loop; A (K1) := RRA; end; end loop; end Heapsort; N : Range_Int; No_Verify : constant Boolean := True; Chk : Real := 0.0; X : Real_Array_Ptr; begin begin N := Range_Int'Max (1, Range_Int'Value (Ada.Command_Line.Argument (1))); exception when Constraint_Error => N := 1; end; X := new Real_Array (0 .. N - 1); -- 3% slower than 'declare' (stack) for Iter in X'Range loop X (Iter) := Random_Real.Gen_Random (Supr => 1.0); end loop; if No_Verify then Heapsort (A => X.all); Rio.Put (X (X'Last), Fore => 0, Aft => 10, Exp => 0); Text_IO.New_Line; else for Iter in X'Range loop Chk := Chk + X (Iter); end loop; Heapsort (A => X.all); for K in X'Range loop pragma Assert (K + 1 = X'Last or else X (K) <= X (K + 1)); Chk := Chk - X (K); end loop; pragma Assert (abs Chk < 50.0 * Real (N) * Real'Model_Epsilon); end if; end Heapsort;