1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- S Y S T E M . F A T _ G E N --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This implementation is portable to any IEEE implementation. It does not
33 -- handle nonbinary radix, and also assumes that model numbers and machine
34 -- numbers are basically identical, which is not true of all possible
35 -- floating-point implementations.
37 with Ada
.Unchecked_Conversion
;
38 with System
.Unsigned_Types
;
40 pragma Warnings
(Off
, "non-static constant in preelaborated unit");
41 -- Every constant is static given our instantiation model
43 package body System
.Fat_Gen
is
44 pragma Assert
(T
'Machine_Radix = 2);
45 -- This version does not handle radix 16
47 Rad
: constant T
:= T
(T
'Machine_Radix);
48 -- Renaming for the machine radix
50 Mantissa
: constant Integer := T
'Machine_Mantissa;
51 -- Renaming for the machine mantissa
53 Invrad
: constant T
:= 1.0 / Rad
;
54 -- Smallest positive mantissa in the canonical form (RM A.5.3(4))
56 -- Small : constant T := Rad ** (T'Machine_Emin - 1);
57 -- Smallest positive normalized number
59 -- Tiny : constant T := Rad ** (T'Machine_Emin - Mantissa);
60 -- Smallest positive denormalized number
62 RM1
: constant T
:= Rad
** (Mantissa
- 1);
63 -- Smallest positive member of the large consecutive integers. It is equal
64 -- to the ratio Small / Tiny, which means that multiplying by it normalizes
65 -- any nonzero denormalized number.
67 IEEE_Emin
: constant Integer := T
'Machine_Emin - 1;
68 IEEE_Emax
: constant Integer := T
'Machine_Emax - 1;
69 -- The mantissa is a fraction with first digit set in Ada whereas it is
70 -- shifted by 1 digit to the left in the IEEE floating-point format.
72 subtype IEEE_Erange
is Integer range IEEE_Emin
- 1 .. IEEE_Emax
+ 1;
73 -- The IEEE floating-point format extends the machine range by 1 to the
74 -- left for denormalized numbers and 1 to the right for infinities/NaNs.
76 IEEE_Ebias
: constant Integer := -(IEEE_Emin
- 1);
77 -- The exponent is biased such that denormalized numbers have it zero
79 -- The implementation uses a representation type Float_Rep that allows
80 -- direct access to exponent and mantissa of the floating point number.
82 -- The Float_Rep type is a simple array of Float_Word elements. This
83 -- representation is chosen to make it possible to size the type based
84 -- on a generic parameter. Since the array size is known at compile
85 -- time, efficient code can still be generated. The size of Float_Word
86 -- elements should be large enough to allow accessing the exponent in
87 -- one read, but small enough so that all floating-point object sizes
88 -- are a multiple of Float_Word'Size.
90 -- The following conditions must be met for all possible instantiations
91 -- of the attribute package:
93 -- - T'Size is an integral multiple of Float_Word'Size
95 -- - The exponent and sign are completely contained in a single
96 -- component of Float_Rep, named Most Significant Word (MSW).
98 -- - The sign occupies the most significant bit of the MSW and the
99 -- exponent is in the following bits.
101 -- The low-level primitives Copy_Sign, Decompose, Finite_Succ, Scaling and
102 -- Valid are implemented by accessing the bit pattern of the floating-point
103 -- number. Only the normalization of denormalized numbers, if any, and the
104 -- gradual underflow are left to the hardware, mainly because there is some
105 -- leeway for the hardware implementation in this area: for example the MSB
106 -- of the mantissa, that is 1 for normalized numbers and 0 for denormalized
107 -- numbers, may or may not be stored by the hardware.
109 Siz
: constant := 16;
110 type Float_Word
is mod 2**Siz
;
111 -- We use the GCD of the size of all the supported floating-point formats
113 N
: constant Natural := (T
'Size + Siz
- 1) / Siz
;
114 NR
: constant Natural := (Mantissa
+ 16 + Siz
- 1) / Siz
;
115 Rep_Last
: constant Natural := Natural'Min (N
, NR
) - 1;
116 -- Determine the number of Float_Words needed for representing the
117 -- entire floating-point value. Do not take into account excessive
118 -- padding, as occurs on IA-64 where 80 bits floats get padded to 128
119 -- bits. In general, the exponent field cannot be larger than 15 bits,
120 -- even for 128-bit floating-point types, so the final format size
121 -- won't be larger than Mantissa + 16.
123 type Float_Rep
is array (Natural range 0 .. N
- 1) of Float_Word
;
124 pragma Suppress_Initialization
(Float_Rep
);
125 -- This pragma suppresses the generation of an initialization procedure
126 -- for type Float_Rep when operating in Initialize/Normalize_Scalars mode.
128 MSW
: constant Natural := Rep_Last
* Standard
'Default_Bit_Order;
129 -- Finding the location of the Exponent_Word is a bit tricky. In general
130 -- we assume Word_Order = Bit_Order.
132 Exp_Factor
: constant Float_Word
:=
133 2**(Siz
- 1) / Float_Word
(IEEE_Emax
- IEEE_Emin
+ 3);
134 -- Factor that the extracted exponent needs to be divided by to be in
135 -- range 0 .. IEEE_Emax - IEEE_Emin + 2
137 Exp_Mask
: constant Float_Word
:=
138 Float_Word
(IEEE_Emax
- IEEE_Emin
+ 2) * Exp_Factor
;
139 -- Value needed to mask out the exponent field. This assumes that the
140 -- range 0 .. IEEE_Emax - IEEE_Emin + 2 contains 2**N values, for some
143 Sign_Mask
: constant Float_Word
:= 2**(Siz
- 1);
144 -- Value needed to mask out the sign field
146 -----------------------
147 -- Local Subprograms --
148 -----------------------
150 procedure Decompose
(XX
: T
; Frac
: out T
; Expo
: out UI
);
151 -- Decomposes a floating-point number into fraction and exponent parts.
152 -- Both results are signed, with Frac having the sign of XX, and UI has
153 -- the sign of the exponent. The absolute value of Frac is in the range
154 -- 0.0 <= Frac < 1.0. If Frac = 0.0 or -0.0, then Expo is always zero.
156 function Finite_Succ
(X
: T
) return T
;
157 -- Return the successor of X, a finite number not equal to T'Last
163 function Adjacent
(X
, Towards
: T
) return T
is
167 elsif Towards
> X
then
178 function Ceiling
(X
: T
) return T
is
179 XT
: constant T
:= Truncation
(X
);
194 function Compose
(Fraction
: T
; Exponent
: UI
) return T
is
198 Decompose
(Fraction
, Arg_Frac
, Arg_Exp
);
199 return Scaling
(Arg_Frac
, Exponent
);
206 function Copy_Sign
(Value
, Sign
: T
) return T
is
207 S
: constant T
:= T
'Machine (Sign
);
210 for Rep_S
'Address use S
'Address;
211 -- Rep_S is a view of the Sign parameter
213 V
: T
:= T
'Machine (Value
);
216 for Rep_V
'Address use V
'Address;
217 -- Rep_V is a view of the Value parameter
221 (Rep_V
(MSW
) and not Sign_Mask
) or (Rep_S
(MSW
) and Sign_Mask
);
229 procedure Decompose
(XX
: T
; Frac
: out T
; Expo
: out UI
) is
230 X
: T
:= T
'Machine (XX
);
233 for Rep
'Address use X
'Address;
234 -- Rep is a view of the input floating-point parameter
236 Exp
: constant IEEE_Erange
:=
237 Integer ((Rep
(MSW
) and Exp_Mask
) / Exp_Factor
) - IEEE_Ebias
;
238 -- Mask/Shift X to only get bits from the exponent. Then convert biased
239 -- value to final value.
241 Minus
: constant Boolean := (Rep
(MSW
) and Sign_Mask
) /= 0;
242 -- Mask/Shift X to only get bit from the sign
245 -- The normalized exponent of zero is zero, see RM A.5.3(15)
251 -- Check for infinities and NaNs
253 elsif Exp
= IEEE_Emax
+ 1 then
254 Expo
:= T
'Machine_Emax + 1;
255 Frac
:= (if Minus
then -Invrad
else Invrad
);
257 -- Check for nonzero denormalized numbers
259 elsif Exp
= IEEE_Emin
- 1 then
260 -- Normalize by multiplying by Radix ** (Mantissa - 1)
262 Decompose
(X
* RM1
, Frac
, Expo
);
263 Expo
:= Expo
- (Mantissa
- 1);
265 -- Case of normalized numbers
268 -- The Ada exponent is the IEEE exponent plus 1, see above
272 -- Set Ada exponent of X to zero, so we end up with the fraction
274 Rep
(MSW
) := (Rep
(MSW
) and not Exp_Mask
) +
275 Float_Word
(IEEE_Ebias
- 1) * Exp_Factor
;
284 function Exponent
(X
: T
) return UI
is
288 Decompose
(X
, X_Frac
, X_Exp
);
296 function Finite_Succ
(X
: T
) return T
is
297 XX
: T
:= T
'Machine (X
);
300 for Rep
'Address use XX
'Address;
301 -- Rep is a view of the input floating-point parameter
304 -- If the floating-point type does not support denormalized numbers,
305 -- there is a couple of problematic values, namely -Small and Zero,
306 -- because the increment is equal to Small in these cases.
310 Small
: constant T
:= Rad
** (T
'Machine_Emin - 1);
311 -- Smallest positive normalized number declared here and not at
312 -- library level for the sake of the CCG compiler, which cannot
313 -- currently compile the constant because the target is C90.
325 -- In all the other cases, the increment is equal to 1 in the binary
326 -- integer representation of the number if X is nonnegative and equal
327 -- to -1 if X is negative.
330 -- First clear the sign of negative Zero
332 Rep
(MSW
) := Rep
(MSW
) and not Sign_Mask
;
334 -- Deal with big endian
337 for J
in reverse 0 .. Rep_Last
loop
338 Rep
(J
) := Rep
(J
) + 1;
340 -- For 80-bit IEEE Extended, the MSB of the mantissa is stored
341 -- so, when it has been flipped, its status must be reanalyzed.
343 if Mantissa
= 64 and then J
= 1 then
345 -- If the MSB changed from denormalized to normalized, then
346 -- keep it normalized since the exponent will be bumped.
348 if Rep
(J
) = 2**(Siz
- 1) then
351 -- If the MSB changed from normalized, restore it since we
352 -- cannot denormalize in this context.
354 elsif Rep
(J
) = 0 then
355 Rep
(J
) := 2**(Siz
- 1);
361 -- In other cases, stop if there is no carry
364 exit when Rep
(J
) > 0;
368 -- Deal with little endian
371 for J
in 0 .. Rep_Last
loop
372 Rep
(J
) := Rep
(J
) + 1;
374 -- For 80-bit IEEE Extended, the MSB of the mantissa is stored
375 -- so, when it has been flipped, its status must be reanalyzed.
377 if Mantissa
= 64 and then J
= Rep_Last
- 1 then
379 -- If the MSB changed from denormalized to normalized, then
380 -- keep it normalized since the exponent will be bumped.
382 if Rep
(J
) = 2**(Siz
- 1) then
385 -- If the MSB changed from normalized, restore it since we
386 -- cannot denormalize in this context.
388 elsif Rep
(J
) = 0 then
389 Rep
(J
) := 2**(Siz
- 1);
395 -- In other cases, stop if there is no carry
398 exit when Rep
(J
) > 0;
405 for J
in reverse 0 .. Rep_Last
loop
406 Rep
(J
) := Rep
(J
) - 1;
408 -- For 80-bit IEEE Extended, the MSB of the mantissa is stored
409 -- so, when it has been flipped, its status must be reanalyzed.
411 if Mantissa
= 64 and then J
= 1 then
413 -- If the MSB changed from normalized to denormalized, then
414 -- keep it normalized if the exponent is not 1.
416 if Rep
(J
) = 2**(Siz
- 1) - 1 then
417 if Rep
(0) /= 2**(Siz
- 1) + 1 then
418 Rep
(J
) := 2**Siz
- 1;
425 -- In other cases, stop if there is no borrow
428 exit when Rep
(J
) < 2**Siz
- 1;
433 for J
in 0 .. Rep_Last
loop
434 Rep
(J
) := Rep
(J
) - 1;
436 -- For 80-bit IEEE Extended, the MSB of the mantissa is stored
437 -- so, when it has been flipped, its status must be reanalyzed.
439 if Mantissa
= 64 and then J
= Rep_Last
- 1 then
441 -- If the MSB changed from normalized to denormalized, then
442 -- keep it normalized if the exponent is not 1.
444 if Rep
(J
) = 2**(Siz
- 1) - 1 then
445 if Rep
(Rep_Last
) /= 2**(Siz
- 1) + 1 then
446 Rep
(J
) := 2**Siz
- 1;
453 -- In other cases, stop if there is no borrow
456 exit when Rep
(J
) < 2**Siz
- 1;
469 function Floor
(X
: T
) return T
is
470 XT
: constant T
:= Truncation
(X
);
485 function Fraction
(X
: T
) return T
is
489 Decompose
(X
, X_Frac
, X_Exp
);
497 function Leading_Part
(X
: T
; Radix_Digits
: UI
) return T
is
502 if Radix_Digits
>= Mantissa
then
505 elsif Radix_Digits
<= 0 then
506 raise Constraint_Error
;
509 L
:= Exponent
(X
) - Radix_Digits
;
510 Y
:= Truncation
(Scaling
(X
, -L
));
520 -- The trick with Machine is to force the compiler to store the result
521 -- in memory so that we do not have extra precision used. The compiler
522 -- is clever, so we have to outwit its possible optimizations. We do
523 -- this by using an intermediate pragma Volatile location.
525 function Machine
(X
: T
) return T
is
527 pragma Volatile
(Temp
);
533 ----------------------
534 -- Machine_Rounding --
535 ----------------------
537 -- For now, the implementation is identical to that of Rounding, which is
538 -- a permissible behavior, but is not the most efficient possible approach.
540 function Machine_Rounding
(X
: T
) return T
is
545 Result
:= Truncation
(abs X
);
546 Tail
:= abs X
- Result
;
549 Result
:= Result
+ 1.0;
558 -- For zero case, make sure sign of zero is preserved
563 end Machine_Rounding
;
569 -- We treat Model as identical to Machine. This is true of IEEE and other
570 -- nice floating-point systems, but not necessarily true of all systems.
572 function Model
(X
: T
) return T
is
574 return T
'Machine (X
);
581 function Pred
(X
: T
) return T
is
583 -- Special treatment for largest negative number: raise Constraint_Error
586 raise Constraint_Error
with "Pred of largest negative number";
588 -- For finite numbers, use the symmetry around zero of floating point
590 elsif X
> T
'First and then X
<= T
'Last then
591 pragma Annotate
(CodePeer
, Intentional
, "test always true",
592 "Check for invalid float");
593 pragma Annotate
(CodePeer
, Intentional
, "condition predetermined",
594 "Check for invalid float");
595 return -Finite_Succ
(-X
);
597 -- For infinities and NaNs, return unchanged
601 pragma Annotate
(CodePeer
, Intentional
, "dead code",
602 "Check float range.");
610 function Remainder
(X
, Y
: T
) return T
is
627 raise Constraint_Error
;
643 P_Exp
:= Exponent
(P
);
646 Decompose
(Arg
, Arg_Frac
, Arg_Exp
);
647 Decompose
(P
, P_Frac
, P_Exp
);
649 P
:= Compose
(P_Frac
, Arg_Exp
);
650 K
:= Arg_Exp
- P_Exp
;
654 for Cnt
in reverse 0 .. K
loop
655 if IEEE_Rem
>= P
then
657 IEEE_Rem
:= IEEE_Rem
- P
;
666 -- That completes the calculation of modulus remainder. The final
667 -- step is get the IEEE remainder. Here we need to compare Rem with
668 -- (abs Y) / 2. We must be careful of unrepresentable Y/2 value
669 -- caused by subnormal numbers
680 if A
> B
or else (A
= B
and then not P_Even
) then
681 IEEE_Rem
:= IEEE_Rem
- abs Y
;
684 return Sign_X
* IEEE_Rem
;
691 function Rounding
(X
: T
) return T
is
696 Result
:= Truncation
(abs X
);
697 Tail
:= abs X
- Result
;
700 Result
:= Result
+ 1.0;
709 -- For zero case, make sure sign of zero is preserved
720 function Scaling
(X
: T
; Adjustment
: UI
) return T
is
721 pragma Assert
(Mantissa
<= 64);
722 -- This implementation handles only 80-bit IEEE Extended or smaller
724 package UST
renames System
.Unsigned_Types
;
725 use type UST
.Long_Long_Unsigned
;
727 XX
: T
:= T
'Machine (X
);
730 for Rep
'Address use XX
'Address;
731 -- Rep is a view of the input floating-point parameter
733 Exp
: constant IEEE_Erange
:=
734 Integer ((Rep
(MSW
) and Exp_Mask
) / Exp_Factor
) - IEEE_Ebias
;
735 -- Mask/Shift X to only get bits from the exponent. Then convert biased
736 -- value to final value.
738 Minus
: constant Boolean := (Rep
(MSW
) and Sign_Mask
) /= 0;
739 -- Mask/Shift X to only get bit from the sign
741 Expi
, Expf
: IEEE_Erange
;
744 -- Check for zero, infinities, NaNs as well as no adjustment
746 if X
= 0.0 or else Exp
= IEEE_Emax
+ 1 or else Adjustment
= 0 then
749 -- Check for nonzero denormalized numbers
751 elsif Exp
= IEEE_Emin
- 1 then
752 -- Check for zero result to protect the subtraction below
754 if Adjustment
< -(Mantissa
- 1) then
756 return (if Minus
then -XX
else XX
);
758 -- Normalize by multiplying by Radix ** (Mantissa - 1)
761 return Scaling
(XX
* RM1
, Adjustment
- (Mantissa
- 1));
764 -- Case of normalized numbers
767 -- Check for overflow
769 if Adjustment
> IEEE_Emax
- Exp
then
770 -- Optionally raise Constraint_Error as per RM A.5.3(29)
772 if T
'Machine_Overflows then
773 raise Constraint_Error
with "Too large exponent";
777 return (if Minus
then -1.0 / XX
else 1.0 / XX
);
778 pragma Annotate
(CodePeer
, Intentional
, "overflow check",
779 "Infinity produced");
780 pragma Annotate
(CodePeer
, Intentional
, "divide by zero",
781 "Infinity produced");
784 -- Check for underflow
786 elsif Adjustment
< IEEE_Emin
- Exp
then
787 -- Check for possibly gradual underflow (up to the hardware)
789 if Adjustment
>= IEEE_Emin
- Mantissa
- Exp
then
791 Expi
:= Exp
+ Adjustment
- Expf
;
793 -- Case of zero result
797 return (if Minus
then -XX
else XX
);
800 -- Case of normalized results
803 Expf
:= Exp
+ Adjustment
;
807 Rep
(MSW
) := (Rep
(MSW
) and not Exp_Mask
) +
808 Float_Word
(IEEE_Ebias
+ Expf
) * Exp_Factor
;
811 -- Given that Expi >= -Mantissa, only -64 is problematic
815 (CodePeer
, Intentional
, "test always false",
816 "test always false in some instantiations");
821 XX
:= XX
/ T
(UST
.Long_Long_Unsigned
(2) ** (-Expi
));
832 function Succ
(X
: T
) return T
is
834 -- Special treatment for largest positive number: raise Constraint_Error
837 raise Constraint_Error
with "Succ of largest positive number";
839 -- For finite numbers, call the specific routine
841 elsif X
>= T
'First and then X
< T
'Last then
842 pragma Annotate
(CodePeer
, Intentional
, "test always true",
843 "Check for invalid float");
844 pragma Annotate
(CodePeer
, Intentional
, "condition predetermined",
845 "Check for invalid float");
846 return Finite_Succ
(X
);
848 -- For infinities and NaNs, return unchanged
852 pragma Annotate
(CodePeer
, Intentional
, "dead code",
853 "Check float range.");
861 -- The basic approach is to compute
863 -- T'Machine (RM1 + N) - RM1
865 -- where N >= 0.0 and RM1 = Radix ** (Mantissa - 1)
867 -- This works provided that the intermediate result (RM1 + N) does not
868 -- have extra precision (which is why we call Machine). When we compute
869 -- RM1 + N, the exponent of N will be normalized and the mantissa shifted
870 -- appropriately so the lower order bits, which cannot contribute to the
871 -- integer part of N, fall off on the right. When we subtract RM1 again,
872 -- the significant bits of N are shifted to the left, and what we have is
873 -- an integer, because only the first e bits are different from zero
874 -- (assuming binary radix here).
876 function Truncation
(X
: T
) return T
is
882 if Result
>= RM1
then
883 return T
'Machine (X
);
886 Result
:= T
'Machine (RM1
+ Result
) - RM1
;
888 if Result
> abs X
then
889 Result
:= Result
- 1.0;
898 -- For zero case, make sure sign of zero is preserved
906 -----------------------
907 -- Unbiased_Rounding --
908 -----------------------
910 function Unbiased_Rounding
(X
: T
) return T
is
911 Abs_X
: constant T
:= abs X
;
916 Result
:= Truncation
(Abs_X
);
917 Tail
:= Abs_X
- Result
;
920 Result
:= Result
+ 1.0;
922 elsif Tail
= 0.5 then
923 Result
:= 2.0 * Truncation
((Result
/ 2.0) + 0.5);
932 -- For zero case, make sure sign of zero is preserved
937 end Unbiased_Rounding
;
943 function Valid
(X
: not null access T
) return Boolean is
944 type Access_T
is access all T
;
945 function To_Address
is
946 new Ada
.Unchecked_Conversion
(Access_T
, System
.Address
);
949 for Rep
'Address use To_Address
(Access_T
(X
));
950 -- Rep is a view of the input floating-point parameter. Note that we
951 -- must avoid reading the actual bits of this parameter in float form
952 -- since it may be a signalling NaN.
954 Exp
: constant IEEE_Erange
:=
955 Integer ((Rep
(MSW
) and Exp_Mask
) / Exp_Factor
) - IEEE_Ebias
;
956 -- Mask/Shift X to only get bits from the exponent. Then convert biased
957 -- value to final value.
960 if Exp
= IEEE_Emax
+ 1 then
961 -- This is an infinity or a NaN, i.e. always invalid
965 elsif Exp
in IEEE_Emin
.. IEEE_Emax
then
966 -- This is a normalized number, i.e. always valid
970 else pragma Assert
(Exp
= IEEE_Emin
- 1);
971 -- This is a denormalized number, valid if T'Denorm is True or 0.0
976 -- Note that we cannot do a direct comparison with 0.0 because the
977 -- hardware may evaluate it to True for all denormalized numbers.
980 -- First clear the sign bit (the exponent is already zero)
982 Rep
(MSW
) := Rep
(MSW
) and not Sign_Mask
;
984 return (for all J
in 0 .. Rep_Last
=> Rep
(J
) = 0);