home *** CD-ROM | disk | FTP | other *** search
- ------------------------------------------------------------------------------
- -- --
- -- GNAT RUNTIME COMPONENTS --
- -- --
- -- A D A . N U M E R I C S . R A N D O M --
- -- --
- -- B o d y --
- -- --
- -- $Revision: 1.3 $ --
- -- --
- -- Copyright (c) 1992,1993,1994 NYU, All Rights Reserved --
- -- --
- -- The GNAT library is free software; you can redistribute it and/or modify --
- -- it under terms of the GNU Library General Public License as published by --
- -- the Free Software Foundation; either version 2, or (at your option) any --
- -- later version. The GNAT library is distributed in the hope that it will --
- -- be useful, but WITHOUT ANY WARRANTY; without even the implied warranty --
- -- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
- -- Library General Public License for more details. You should have --
- -- received a copy of the GNU Library General Public License along with --
- -- the GNAT library; see the file COPYING.LIB. If not, write to the Free --
- -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
- -- --
- ------------------------------------------------------------------------------
-
- -- This implementation is derived from LSN 1055 written by Ken Dritz.
-
- with Ada.Calendar;
-
- package body Ada.Numerics.Random is
-
- ------------------------------
- -- Form of the Image String --
- ------------------------------
-
- -- The image string is of the form:
-
- -- nnn,nnn,nnn .... nnn,b
-
- -- There are Larger_Lag nnn components, where each component is a
- -- decimal integer representing the values of the Lagged_Outputs in
- -- the State_Vector, stored as rounded values * 2**24, in reverse order
- -- (i.e. highest indexed value comes first), b is the borrow (0/1)
-
- -----------
- -- Image --
- -----------
-
- function Image (S : State) return String is
- Result : String (1 .. Max_Image_Width);
- Result_Length : Natural;
-
- procedure Encode (Value : Float);
- -- Add encoded float value to result string, using the float value
- -- multiplied by 2**24 as a rounded decimal integer string.
-
- procedure Encode (Value : Float) is
- Img : constant String := Int'Image (Int (2#1.0#E24 * Value));
-
- begin
- for J in 2 .. Img'Length loop
- Result_Length := Result_Length + 1;
- Result (Result_Length) := Img (J);
- end loop;
- end Encode;
-
- -- Start processing for Image
-
- begin
- Result_Length := 0;
-
- for J in Lag_Range loop
- Encode (S.Lagged_Outputs (S.R - J));
- Result_Length := Result_Length + 1;
- Result (Result_Length) := ',';
- end loop;
-
- Encode (S.Borrow);
- return Result (1 .. Result_Length);
- end Image;
-
- ----------------
- -- Make_State --
- ----------------
-
- function Make_State (Starter : Int := 3E+7) return State is
- Bit_Value : Float;
- LCG_State : Float;
-
- Result : State;
-
- function LCG_Random return Uniformly_Distributed;
- -- Needs comments???
-
- function LCG_Random return Uniformly_Distributed is
- LCG_Multiplier : constant := 16_807.0;
- LCG_Modulus : constant := 2_147_483_647.0;
- T : Float;
- J : Int;
-
- begin
- T := LCG_State * LCG_Multiplier;
- J := Int (T / LCG_Modulus);
- LCG_State := T - Float (J) * LCG_Modulus;
-
- if LCG_State < 0.0 then
- LCG_State := LCG_State + LCG_Modulus;
- end if;
-
- return LCG_State / LCG_Modulus;
- end LCG_Random;
-
- -- Start of processing for Make_State
-
- begin
- LCG_State := Float (Starter);
-
- for J in Lag_Range loop
- Result.Lagged_Outputs (J) := 0.0;
- Bit_Value := 1.0;
-
- for K in 1 .. 24 loop
- Bit_Value := Bit_Value * 0.5;
-
- if LCG_Random >= 0.5 then
- Result.Lagged_Outputs (J) :=
- Result.Lagged_Outputs (J) + Bit_Value;
- end if;
- end loop;
- end loop;
-
- Result.Borrow := 0.0;
- Result.R := Larger_Lag - 1;
- Result.S := Smaller_Lag - 1;
- return Result;
- end Make_State;
-
- ------------
- -- Random --
- ------------
-
- procedure Random (S : in out State; U : out Uniformly_Distributed) is
- U1 : Uniformly_Distributed'Base;
- begin
- U1 := S.Lagged_Outputs (S.R) - S.Lagged_Outputs (S.S) - S.Borrow;
-
- if U1 < 0.0 then
- U1 := U1 + 1.0;
- S.Borrow := 2#1.0#e-24;
- else
- S.Borrow := 0.0;
- end if;
-
- U := U1;
- S.Lagged_Outputs (S.R) := U;
- S.R := S.R - 1;
- S.S := S.S - 1;
- end Random;
-
- -----------
- -- Reset --
- -----------
-
- procedure Reset (S : out State; Initiator : in Integer) is
- begin
- S := Make_State (Int (Initiator) mod 2_147_483_646 + 1);
- end Reset;
-
- procedure Reset (S : out State) is
- use Ada.Calendar;
-
- Year : Year_Number;
- Month : Month_Number;
- Day : Day_Number;
- Secs : Day_Duration;
-
- begin
- Split (Clock, Year, Month, Day, Secs);
- S := Make_State (((Int (Year) * 12 +
- Int (Month)) * 32 +
- Int (Day)) * 24 * 60 * 60 +
- Int (Secs));
- end Reset;
-
- -----------
- -- Value --
- -----------
-
- function Value (S : String) return State is
- Result : State;
- Ptr : Natural := S'First;
-
- function Decode_Component (Max : in Nat) return Float;
- -- Decode next component as a floating-point value, by reading an
- -- integer up to a comma or the end of the string, and converting
- -- it to float by dividing by 2**24. Ptr is the initial location for
- -- the scan, and is advanced past the termninator. Max is the maximum
- -- value of the component as an integer (2**24 - 1 for the lagged
- -- components, and 1 for the borrow).
-
- function Decode_Component (Max : in Nat) return Float is
- End_Ptr : Natural;
- Int_Val : Nat;
-
- begin
- -- Not enough components if past end of string
-
- if Ptr > S'Last then
- raise Constraint_Error;
- end if;
-
- End_Ptr := Ptr;
-
- while End_Ptr <= S'Last
- and then S (End_Ptr) /= ','
- loop
- End_Ptr := End_Ptr + 1;
- end loop;
-
- -- Make sure Length is in reasonable bounds (2**24 < 10**8)
-
- if End_Ptr = Ptr or else End_Ptr > Ptr + 8 then
- raise Constraint_Error;
- end if;
-
- Int_Val := Nat'Value (S (Ptr .. End_Ptr - 1));
-
- if Int_Val > Max then
- raise Constraint_Error;
- end if;
-
- Ptr := End_Ptr;
- return Float (Int_Val) * 2#1.0#e-24;
- end Decode_Component;
-
- -- Start of processing for Value
-
- begin
- for J in reverse Lag_Range loop
- Result.Lagged_Outputs (J) := Decode_Component (2**24 - 1);
- end loop;
-
- Result.Borrow := Decode_Component (1);
-
- -- Must be at end of string now!
-
- if Ptr <= S'Last then
- raise Constraint_Error;
- end if;
-
- Result.R := Larger_Lag - 1;
- Result.S := Smaller_Lag - 1;
- return Result;
- end Value;
-
- end Ada.Numerics.Random;
-