* ChangeLog: Repair from previous update.
[platform/upstream/gcc.git] / gcc / ada / s-exngen.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT RUNTIME COMPONENTS                          --
4 --                                                                          --
5 --                       S Y S T E M . E X N _ G E N                        --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --                            $Revision: 1.9 $
10 --                                                                          --
11 --          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
12 --                                                                          --
13 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
14 -- terms of the  GNU General Public License as published  by the Free Soft- --
15 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
16 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
19 -- for  more details.  You should have  received  a copy of the GNU General --
20 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
21 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
22 -- MA 02111-1307, USA.                                                      --
23 --                                                                          --
24 -- As a special exception,  if other files  instantiate  generics from this --
25 -- unit, or you link  this unit with other files  to produce an executable, --
26 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
27 -- covered  by the  GNU  General  Public  License.  This exception does not --
28 -- however invalidate  any other reasons why  the executable file  might be --
29 -- covered by the  GNU Public License.                                      --
30 --                                                                          --
31 -- GNAT was originally developed  by the GNAT team at  New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
33 --                                                                          --
34 ------------------------------------------------------------------------------
35
36 package body System.Exn_Gen is
37
38    --------------------
39    -- Exn_Float_Type --
40    --------------------
41
42    function Exn_Float_Type
43      (Left  : Type_Of_Base;
44       Right : Integer)
45       return  Type_Of_Base
46    is
47       pragma Suppress (Division_Check);
48       pragma Suppress (Overflow_Check);
49       pragma Suppress (Range_Check);
50
51       Result : Type_Of_Base := 1.0;
52       Factor : Type_Of_Base := Left;
53       Exp    : Integer := Right;
54
55    begin
56       --  We use the standard logarithmic approach, Exp gets shifted right
57       --  testing successive low order bits and Factor is the value of the
58       --  base raised to the next power of 2. For positive exponents we
59       --  multiply the result by this factor, for negative exponents, we
60       --  Division by this factor.
61
62       if Exp >= 0 then
63          loop
64             if Exp rem 2 /= 0 then
65                Result := Result * Factor;
66             end if;
67
68             Exp := Exp / 2;
69             exit when Exp = 0;
70             Factor := Factor * Factor;
71          end loop;
72
73          return Result;
74
75       --  Negative exponent. For a zero base, we should arguably return an
76       --  infinity of the right sign, but it is not clear that there is
77       --  proper authorization to do so, so for now raise Constraint_Error???
78
79       elsif Factor = 0.0 then
80          raise Constraint_Error;
81
82       --  Here we have a non-zero base and a negative exponent
83
84       else
85          --  For the negative exponent case, a constraint error during this
86          --  calculation happens if Factor gets too large, and the proper
87          --  response is to return 0.0, since what we essentially have is
88          --  1.0 / infinity, and the closest model number will be zero.
89
90          begin
91             loop
92                if Exp rem 2 /= 0 then
93                   Result := Result * Factor;
94                end if;
95
96                Exp := Exp / 2;
97                exit when Exp = 0;
98                Factor := Factor * Factor;
99             end loop;
100
101             return 1.0 / Result;
102
103          exception
104
105             when Constraint_Error =>
106                return 0.0;
107          end;
108       end if;
109    end Exn_Float_Type;
110
111    ----------------------
112    -- Exn_Integer_Type --
113    ----------------------
114
115    --  Note that negative exponents get a constraint error because the
116    --  subtype of the Right argument (the exponent) is Natural.
117
118    function Exn_Integer_Type
119      (Left  : Type_Of_Base;
120       Right : Natural)
121       return  Type_Of_Base
122    is
123       pragma Suppress (Division_Check);
124       pragma Suppress (Overflow_Check);
125
126       Result : Type_Of_Base := 1;
127       Factor : Type_Of_Base := Left;
128       Exp    : Natural := Right;
129
130    begin
131       --  We use the standard logarithmic approach, Exp gets shifted right
132       --  testing successive low order bits and Factor is the value of the
133       --  base raised to the next power of 2.
134
135       --  Note: it is not worth special casing the cases of base values -1,0,+1
136       --  since the expander does this when the base is a literal, and other
137       --  cases will be extremely rare.
138
139       if Exp /= 0 then
140          loop
141             if Exp rem 2 /= 0 then
142                Result := Result * Factor;
143             end if;
144
145             Exp := Exp / 2;
146             exit when Exp = 0;
147             Factor := Factor * Factor;
148          end loop;
149       end if;
150
151       return Result;
152    end Exn_Integer_Type;
153
154 end System.Exn_Gen;