-- $Id: moments.gnat,v 1.0 2003/06/11 12:08: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.Numerics.Generic_Elementary_Functions; with Ada.Unchecked_Deallocation, Ada.Text_IO; procedure Moments is type Real is digits Positive'Max (15, System.Max_Digits); package AF is new Ada.Numerics.Generic_Elementary_Functions (Float_Type => Real); package Io renames Ada.Text_IO; package Rio is new Ada.Text_IO.Float_IO (Num => Real); procedure Put (Item : Real; Fore : Io.Field := 0; Aft : Io.Field := 6; Exp : Io.Field := 0) renames Rio.Put; generic type Item_Type is private; -- Component type of array to be sorted with function "<=" (X, Y : Item_Type) return Boolean; type Sequence is array (Integer range <>) of Item_Type; package Sort_Pkg is procedure Quick_Sort (S : in out Sequence); end Sort_Pkg; -- Copied from Southampton Ada MPICH supercomputer bindings package body Sort_Pkg is procedure Quick_Sort (S : in out Sequence) is procedure Sort_Recursive (Lwb, Upb : Integer) is Pivot : Item_Type := S (Upb); Front : Integer := Lwb; Back : Integer := Upb; Temp : Item_Type; begin if Lwb < Upb then while (Front <= Back) loop while not (Pivot <= S (Front)) loop Front := Front + 1; end loop; while not (S (Back) <= Pivot) loop Back := Back - 1; end loop; if Front <= Back then Temp := S (Front); S (Front) := S (Back); S (Back) := Temp; Front := Front + 1; Back := Back - 1; end if; end loop; Sort_Recursive (Lwb, Back); Sort_Recursive (Front, Upb); end if; end Sort_Recursive; begin Sort_Recursive (S'First, S'Last); end Quick_Sort; end Sort_Pkg; type Real_Array is array (Integer range <>) of Real; type Real_Array_Ptr is access Real_Array; procedure Deallocate_Real_Array is new Ada.Unchecked_Deallocation ( Object => Real_Array, Name => Real_Array_Ptr); package Sort is new Sort_Pkg (Real, "<=" => "<=", Sequence => Real_Array); Data : Real_Array_Ptr := new Real_Array (1 .. 0); Temp_Array : Real_Array_Ptr; Dev, D_2, Mean, Median : Real; Standard_Deviation : Real; Sum, Avg_Abs_Deviation : Real := 0.0; Variance, Skew, Kurtosis : Real := 0.0; M : Natural := 0; begin while not Io.End_Of_File loop M := M + 1; if M > Data'Last then -- Lengthen array of strings Temp_Array := new Real_Array ( 1 .. 4 + Positive (Real'Ceiling (1.70 * Real (M)))); Temp_Array (Data'Range) := Data.all; Deallocate_Real_Array (Data); Data := Temp_Array; -- Replace the old array with the new one end if; Rio.Get (Item => Data (M)); -- Read numbers between whitespace Sum := Sum + Data (M); end loop; Mean := Sum / Real (M); for K in 1 .. M loop Dev := Data (K) - Mean; Avg_Abs_Deviation := Avg_Abs_Deviation + abs Dev; D_2 := Dev * Dev; Variance := Variance + D_2; Skew := Skew + (D_2 * Dev); Kurtosis := Kurtosis + (D_2 * D_2); end loop; Avg_Abs_Deviation := Avg_Abs_Deviation / Real (M); Variance := Variance / Real (M - 1); Standard_Deviation := AF.Sqrt (Variance); if Variance < 10.0 * Real'Model_Epsilon then Io.Put_Line ("> Reduced accuracy results: 0 = ((Variance/10 + 1) - 1)"); else Skew := Skew / (Real (M) * Variance * Standard_Deviation); Kurtosis := -3.0 + Kurtosis / (Real (M) * Variance * Variance); end if; Sort.Quick_Sort (S => Data (1 .. M)); if 1 = (M mod 2) then Median := Data ((M + 1) / 2); else Median := (Data (M / 2) + Data (1 + M / 2)) / 2.0; end if; Io.Put_Line ("n: " & Integer'Image (M)); Io.Put ("median: "); Put (Median); Io.New_Line; Io.Put ("mean: "); Put (Mean); Io.New_Line; Io.Put ("average_deviation: "); Put (Avg_Abs_Deviation); Io.New_Line; Io.Put ("standard_deviation: "); Put (Standard_Deviation); Io.New_Line; Io.Put ("variance: "); Put (Variance); Io.New_Line; Io.Put ("skew: "); Put (Skew); Io.New_Line; Io.Put ("kurtosis: "); Put (Kurtosis); Io.New_Line; end Moments;