OSDN Git Service

* gcc-interface/ada-tree.h (SET_TYPE_RM_VALUE): Mark the expression
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-nudira.adb
index 298aecc..87abcd8 100644 (file)
@@ -1,30 +1,28 @@
 ------------------------------------------------------------------------------
 --                                                                          --
---                         GNAT RUNTIME COMPONENTS                          --
+--                         GNAT RUN-TIME COMPONENTS                         --
 --                                                                          --
 --         A D A . N U M E R I C S . D I S C R E T E _ R A N D O M          --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-1999 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
--- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
 --                                                                          --
--- As a special exception,  if other files  instantiate  generics from this --
--- unit, or you link  this unit with other files  to produce an executable, --
--- this  unit  does not  by itself cause  the resulting  executable  to  be --
--- covered  by the  GNU  General  Public  License.  This exception does not --
--- however invalidate  any other reasons why  the executable file  might be --
--- covered by the  GNU Public License.                                      --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
@@ -32,6 +30,7 @@
 ------------------------------------------------------------------------------
 
 with Ada.Calendar;
+
 with Interfaces; use Interfaces;
 
 package body Ada.Numerics.Discrete_Random is
@@ -52,7 +51,34 @@ package body Ada.Numerics.Discrete_Random is
 
    type Pointer is access all State;
 
-   Need_64 : constant Boolean := Rst'Pos (Rst'Last) > Int'Last;
+   Fits_In_32_Bits : constant Boolean :=
+                       Rst'Size < 31
+                         or else (Rst'Size = 31
+                                  and then Rst'Pos (Rst'First) < 0);
+   --  This is set True if we do not need more than 32 bits in the result. If
+   --  we need 64-bits, we will only use the meaningful 48 bits of any 64-bit
+   --  number generated, since if more than 48 bits are required, we split the
+   --  computation into two separate parts, since the algorithm does not behave
+   --  above 48 bits.
+
+   --  The way this expression works is that obviously if the size is 31 bits,
+   --  it fits in 32 bits. In the 32-bit case, it fits in 32-bit signed if the
+   --  range has negative values. It is too conservative in the case that the
+   --  programmer has set a size greater than the default, e.g. a size of 33
+   --  for an integer type with a range of 1..10, but an over-conservative
+   --  result is OK. The important thing is that the value is only True if
+   --  we know the result will fit in 32-bits signed. If the value is False
+   --  when it could be True, the behavior will be correct, just a bit less
+   --  efficient than it could have been in some unusual cases.
+   --
+   --  One might assume that we could get a more accurate result by testing
+   --  the lower and upper bounds of the type Rst against the bounds of 32-bit
+   --  Integer. However, there is no easy way to do that. Why? Because in the
+   --  relatively rare case where this expresion has to be evaluated at run
+   --  time rather than compile time (when the bounds are dynamic), we need a
+   --  type to use for the computation. But the possible range of upper bound
+   --  values for Rst (remembering the possibility of 64-bit modular types) is
+   --  from -2**63 to 2**64-1, and no run-time type has a big enough range.
 
    -----------------------
    -- Local Subprograms --
@@ -69,9 +95,9 @@ package body Ada.Numerics.Discrete_Random is
    function Image (Of_State : State) return String is
    begin
       return Int'Image (Of_State.X1) &
-             ','                            &
+             ','                     &
              Int'Image (Of_State.X2) &
-             ','                            &
+             ','                     &
              Int'Image (Of_State.Q);
    end Image;
 
@@ -109,7 +135,7 @@ package body Ada.Numerics.Discrete_Random is
          Temp := Temp + Genp.Q;
       end if;
 
-      TF :=  Offs + (Flt (Temp) * Flt (Genp.P) + Flt (Genp.X1)) * Genp.Scl;
+      TF := Offs + (Flt (Temp) * Flt (Genp.P) + Flt (Genp.X1)) * Genp.Scl;
 
       --  Pathological, but there do exist cases where the rounding implicit
       --  in calculating the scale factor will cause rounding to 'Last + 1.
@@ -118,13 +144,12 @@ package body Ada.Numerics.Discrete_Random is
       if TF >= Flt (Rst'Pos (Rst'Last)) + 0.5 then
          return Rst'First;
 
-      elsif Need_64 then
+      elsif not Fits_In_32_Bits then
          return Rst'Val (Interfaces.Integer_64 (TF));
 
       else
          return Rst'Val (Int (TF));
       end if;
-
    end Random;
 
    -----------
@@ -144,7 +169,7 @@ package body Ada.Numerics.Discrete_Random is
          X2 := Square_Mod_N (X2, K2);
       end loop;
 
-      --  eliminate effects of small Initiators.
+      --  Eliminate effects of small Initiators
 
       Genp.all :=
         (X1  => X1,
@@ -198,7 +223,6 @@ package body Ada.Numerics.Discrete_Random is
 
    procedure Reset (Gen : Generator; From_State : State) is
       Genp : constant Pointer := Gen.Gen_State'Unrestricted_Access;
-
    begin
       Genp.all := From_State;
    end Reset;
@@ -226,30 +250,39 @@ package body Ada.Numerics.Discrete_Random is
    -----------
 
    function Value (Coded_State : String) return State is
+      Last  : constant Natural := Coded_State'Last;
       Start : Positive := Coded_State'First;
       Stop  : Positive := Coded_State'First;
       Outs  : State;
 
    begin
-      while Coded_State (Stop) /= ',' loop
+      while Stop <= Last and then Coded_State (Stop) /= ',' loop
          Stop := Stop + 1;
       end loop;
 
+      if Stop > Last then
+         raise Constraint_Error;
+      end if;
+
       Outs.X1 := Int'Value (Coded_State (Start .. Stop - 1));
       Start := Stop + 1;
 
       loop
          Stop := Stop + 1;
-         exit when Coded_State (Stop) = ',';
+         exit when Stop > Last or else Coded_State (Stop) = ',';
       end loop;
 
+      if Stop > Last then
+         raise Constraint_Error;
+      end if;
+
       Outs.X2  := Int'Value (Coded_State (Start .. Stop - 1));
-      Outs.Q   := Int'Value (Coded_State (Stop + 1 .. Coded_State'Last));
+      Outs.Q   := Int'Value (Coded_State (Stop + 1 .. Last));
       Outs.P   := Outs.Q * 2 + 1;
       Outs.FP  := Flt (Outs.P);
       Outs.Scl := (RstL - RstF + 1.0) / (Flt (Outs.P) * Flt (Outs.Q));
 
-      --  Now do *some* sanity checks.
+      --  Now do *some* sanity checks
 
       if Outs.Q < 31
         or else Outs.X1 not in 2 .. Outs.P - 1