1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- S Y S T E M . I M G _ R E A L --
9 -- Copyright (C) 1992-2014, 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 with System
.Img_LLU
; use System
.Img_LLU
;
33 with System
.Img_Uns
; use System
.Img_Uns
;
34 with System
.Powten_Table
; use System
.Powten_Table
;
35 with System
.Unsigned_Types
; use System
.Unsigned_Types
;
36 with System
.Float_Control
;
38 package body System
.Img_Real
is
40 -- The following defines the maximum number of digits that we can convert
41 -- accurately. This is limited by the precision of Long_Long_Float, and
42 -- also by the number of digits we can hold in Long_Long_Unsigned, which
43 -- is the integer type we use as an intermediate for the result.
45 -- We assume that in practice, the limitation will come from the digits
46 -- value, rather than the integer value. This is true for typical IEEE
47 -- implementations, and at worst, the only loss is for some precision
48 -- in very high precision floating-point output.
50 -- Note that in the following, the "-2" accounts for the sign and one
51 -- extra digits, since we need the maximum number of 9's that can be
52 -- supported, e.g. for the normal 64 bit case, Long_Long_Integer'Width
53 -- is 21, since the maximum value (approx 1.6 * 10**19) has 20 digits,
54 -- but the maximum number of 9's that can be supported is 19.
58 (Long_Long_Unsigned
'Width - 2, Long_Long_Float'Digits);
60 Unsdigs
: constant := Unsigned
'Width - 2;
61 -- Number of digits that can be converted using type Unsigned
62 -- See above for the explanation of the -2.
64 Maxscaling
: constant := 5000;
65 -- Max decimal scaling required during conversion of floating-point
66 -- numbers to decimal. This is used to defend against infinite
67 -- looping in the conversion, as can be caused by erroneous executions.
68 -- The largest exponent used on any current system is 2**16383, which
69 -- is approximately 10**4932, and the highest number of decimal digits
70 -- is about 35 for 128-bit floating-point formats, so 5000 leaves
71 -- enough room for scaling such values
73 function Is_Negative
(V
: Long_Long_Float) return Boolean;
74 pragma Import
(Intrinsic
, Is_Negative
);
76 --------------------------
77 -- Image_Floating_Point --
78 --------------------------
80 procedure Image_Floating_Point
86 pragma Assert
(S
'First = 1);
89 -- Decide whether a blank should be prepended before the call to
90 -- Set_Image_Real. We generate a blank for positive values, and
91 -- also for positive zeroes. For negative zeroes, we generate a
92 -- space only if Signed_Zeroes is True (the RM only permits the
93 -- output of -0.0 on targets where this is the case). We can of
94 -- course still see a -0.0 on a target where Signed_Zeroes is
95 -- False (since this attribute refers to the proper handling of
96 -- negative zeroes, not to their existence). We do not generate
97 -- a blank for positive infinity, since we output an explicit +.
99 if (not Is_Negative
(V
) and then V
<= Long_Long_Float'Last)
100 or else (not Long_Long_Float'Signed_Zeros and then V
= -0.0)
108 Set_Image_Real
(V
, S
, P
, 1, Digs
- 1, 3);
109 end Image_Floating_Point
;
111 --------------------------------
112 -- Image_Ordinary_Fixed_Point --
113 --------------------------------
115 procedure Image_Ordinary_Fixed_Point
116 (V
: Long_Long_Float;
121 pragma Assert
(S
'First = 1);
124 -- Output space at start if non-negative
133 Set_Image_Real
(V
, S
, P
, 1, Aft
, 0);
134 end Image_Ordinary_Fixed_Point
;
140 procedure Set_Image_Real
141 (V
: Long_Long_Float;
148 NFrac
: constant Natural := Natural'Max (Aft
, 1);
150 X
: aliased Long_Long_Float;
151 -- This is declared aliased because the expansion of X'Valid passes
152 -- X by access and JGNAT requires all access parameters to be aliased.
153 -- The Valid attribute probably needs to be handled via a different
154 -- expansion for JGNAT, and this use of aliased should be removed
155 -- once Valid is handled properly. ???
159 Field_Max
: constant := 255;
160 -- This should be the same value as Ada.[Wide_]Text_IO.Field'Last.
161 -- It is not worth dragging in Ada.Text_IO to pick up this value,
162 -- since it really should never be necessary to change it.
164 Digs
: String (1 .. 2 * Field_Max
+ 16);
165 -- Array used to hold digits of converted integer value. This is a
166 -- large enough buffer to accommodate ludicrous values of Fore and Aft.
169 -- Number of digits stored in Digs (and also subscript of last digit)
171 procedure Adjust_Scale
(S
: Natural);
172 -- Adjusts the value in X by multiplying or dividing by a power of
173 -- ten so that it is in the range 10**(S-1) <= X < 10**S. Includes
174 -- adding 0.5 to round the result, readjusting if the rounding causes
175 -- the result to wander out of the range. Scale is adjusted to reflect
176 -- the power of ten used to divide the result (i.e. one is added to
177 -- the scale value for each division by 10.0, or one is subtracted
178 -- for each multiplication by 10.0).
180 procedure Convert_Integer
;
181 -- Takes the value in X, outputs integer digits into Digs. On return,
182 -- Ndigs is set to the number of digits stored. The digits are stored
183 -- in Digs (1 .. Ndigs),
185 procedure Set
(C
: Character);
186 -- Sets character C in output buffer
188 procedure Set_Blanks_And_Sign
(N
: Integer);
189 -- Sets leading blanks and minus sign if needed. N is the number of
190 -- positions to be filled (a minus sign is output even if N is zero
191 -- or negative, but for a positive value, if N is non-positive, then
192 -- the call has no effect).
194 procedure Set_Digs
(S
, E
: Natural);
195 -- Set digits S through E from Digs buffer. No effect if S > E
197 procedure Set_Special_Fill
(N
: Natural);
198 -- After outputting +Inf, -Inf or NaN, this routine fills out the
199 -- rest of the field with * characters. The argument is the number
200 -- of characters output so far (either 3 or 4)
202 procedure Set_Zeros
(N
: Integer);
203 -- Set N zeros, no effect if N is negative
206 pragma Inline
(Set_Digs
);
207 pragma Inline
(Set_Zeros
);
213 procedure Adjust_Scale
(S
: Natural) is
217 XP
: Long_Long_Float;
220 -- Cases where scaling up is required
222 if X
< Powten
(S
- 1) then
224 -- What we are looking for is a power of ten to multiply X by
225 -- so that the result lies within the required range.
228 XP
:= X
* Powten
(Maxpow
);
229 exit when XP
>= Powten
(S
- 1) or else Scale
< -Maxscaling
;
231 Scale
:= Scale
- Maxpow
;
234 -- The following exception is only raised in case of erroneous
235 -- execution, where a number was considered valid but still
236 -- fails to scale up. One situation where this can happen is
237 -- when a system which is supposed to be IEEE-compliant, but
238 -- has been reconfigured to flush denormals to zero.
240 if Scale
< -Maxscaling
then
241 raise Constraint_Error
;
244 -- Here we know that we must multiply by at least 10**1 and that
245 -- 10**Maxpow takes us too far: binary search to find right one.
247 -- Because of roundoff errors, it is possible for the value
248 -- of XP to be just outside of the interval when Lo >= Hi. In
249 -- that case we adjust explicitly by a factor of 10. This
250 -- can only happen with a value that is very close to an
251 -- exact power of 10.
257 Mid
:= (Lo
+ Hi
) / 2;
258 XP
:= X
* Powten
(Mid
);
260 if XP
< Powten
(S
- 1) then
271 elsif XP
>= Powten
(S
) then
288 Scale
:= Scale
- Mid
;
290 -- Cases where scaling down is required
292 elsif X
>= Powten
(S
) then
294 -- What we are looking for is a power of ten to divide X by
295 -- so that the result lies within the required range.
298 XP
:= X
/ Powten
(Maxpow
);
299 exit when XP
< Powten
(S
) or else Scale
> Maxscaling
;
301 Scale
:= Scale
+ Maxpow
;
304 -- The following exception is only raised in case of erroneous
305 -- execution, where a number was considered valid but still
306 -- fails to scale up. One situation where this can happen is
307 -- when a system which is supposed to be IEEE-compliant, but
308 -- has been reconfigured to flush denormals to zero.
310 if Scale
> Maxscaling
then
311 raise Constraint_Error
;
314 -- Here we know that we must divide by at least 10**1 and that
315 -- 10**Maxpow takes us too far, binary search to find right one.
321 Mid
:= (Lo
+ Hi
) / 2;
322 XP
:= X
/ Powten
(Mid
);
324 if XP
< Powten
(S
- 1) then
335 elsif XP
>= Powten
(S
) then
352 Scale
:= Scale
+ Mid
;
354 -- Here we are already scaled right
360 -- Round, readjusting scale if needed. Note that if a readjustment
361 -- occurs, then it is never necessary to round again, because there
362 -- is no possibility of such a second rounding causing a change.
366 if X
>= Powten
(S
) then
373 ---------------------
374 -- Convert_Integer --
375 ---------------------
377 procedure Convert_Integer
is
379 -- Use Unsigned routine if possible, since on many machines it will
380 -- be significantly more efficient than the Long_Long_Unsigned one.
382 if X
< Powten
(Unsdigs
) then
385 (Unsigned
(Long_Long_Float'Truncation (X
)),
388 -- But if we want more digits than fit in Unsigned, we have to use
389 -- the Long_Long_Unsigned routine after all.
393 Set_Image_Long_Long_Unsigned
394 (Long_Long_Unsigned
(Long_Long_Float'Truncation (X
)),
403 procedure Set
(C
: Character) is
409 -------------------------
410 -- Set_Blanks_And_Sign --
411 -------------------------
413 procedure Set_Blanks_And_Sign
(N
: Integer) is
416 for J
in 1 .. N
- 1 loop
427 end Set_Blanks_And_Sign
;
433 procedure Set_Digs
(S
, E
: Natural) is
440 ----------------------
441 -- Set_Special_Fill --
442 ----------------------
444 procedure Set_Special_Fill
(N
: Natural) is
448 F
:= Fore
+ 1 + Aft
- N
;
457 end Set_Special_Fill
;
463 procedure Set_Zeros
(N
: Integer) is
470 -- Start of processing for Set_Image_Real
473 -- We call the floating-point processor reset routine so that we can
474 -- be sure the floating-point processor is properly set for conversion
475 -- calls. This is notably need on Windows, where calls to the operating
476 -- system randomly reset the processor into 64-bit mode.
478 System
.Float_Control
.Reset
;
482 -- Deal with invalid values first,
486 -- Note that we're taking our chances here, as V might be
487 -- an invalid bit pattern resulting from erroneous execution
488 -- (caused by using uninitialized variables for example).
490 -- No matter what, we'll at least get reasonable behaviour,
491 -- converting to infinity or some other value, or causing an
492 -- exception to be raised is fine.
494 -- If the following test succeeds, then we definitely have
495 -- an infinite value, so we print Inf.
497 if V
> Long_Long_Float'Last then
502 Set_Special_Fill
(4);
504 -- In all other cases we print NaN
506 elsif V
< Long_Long_Float'First then
511 Set_Special_Fill
(4);
517 Set_Special_Fill
(3);
538 if Long_Long_Float'Signed_Zeros and then Is_Negative
(V
) then
544 Set_Blanks_And_Sign
(Fore
- 1);
552 Set_Zeros
(Natural'Max (1, Exp
- 1));
558 -- It should not be possible for a NaN to end up here.
559 -- Either the 'Valid test has failed, or we have some form
560 -- of erroneous execution. Raise Constraint_Error instead of
561 -- attempting to go ahead printing the value.
563 raise Constraint_Error
;
566 -- X and Sign are set here, and X is known to be a valid,
567 -- non-zero floating-point number.
569 -- Case of non-zero value with Exp = 0
573 -- First step is to multiply by 10 ** Nfrac to get an integer
574 -- value to be output, an then add 0.5 to round the result.
577 NF
: Natural := NFrac
;
581 -- If we are larger than Powten (Maxdigs) now, then
582 -- we have too many significant digits, and we have
583 -- not even finished multiplying by NFrac (NF shows
584 -- the number of unaccounted-for digits).
586 if X
>= Powten
(Maxdigs
) then
588 -- In this situation, we only to generate a reasonable
589 -- number of significant digits, and then zeroes after.
590 -- So first we rescale to get:
592 -- 10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
594 -- and then convert the resulting integer
596 Adjust_Scale
(Maxdigs
);
599 -- If that caused rescaling, then add zeros to the end
600 -- of the number to account for this scaling. Also add
601 -- zeroes to account for the undone multiplications
603 for J
in 1 .. Scale
+ NF
loop
610 -- If multiplication is complete, then convert the resulting
611 -- integer after rounding (note that X is non-negative)
618 -- Otherwise we can go ahead with the multiplication. If it
619 -- can be done in one step, then do it in one step.
621 elsif NF
< Maxpow
then
622 X
:= X
* Powten
(NF
);
625 -- If it cannot be done in one step, then do partial scaling
628 X
:= X
* Powten
(Maxpow
);
634 -- If number of available digits is less or equal to NFrac,
635 -- then we need an extra zero before the decimal point.
637 if Ndigs
<= NFrac
then
638 Set_Blanks_And_Sign
(Fore
- 1);
641 Set_Zeros
(NFrac
- Ndigs
);
644 -- Normal case with some digits before the decimal point
647 Set_Blanks_And_Sign
(Fore
- (Ndigs
- NFrac
));
648 Set_Digs
(1, Ndigs
- NFrac
);
650 Set_Digs
(Ndigs
- NFrac
+ 1, Ndigs
);
653 -- Case of non-zero value with non-zero Exp value
656 -- If NFrac is less than Maxdigs, then all the fraction digits are
657 -- significant, so we can scale the resulting integer accordingly.
659 if NFrac
< Maxdigs
then
660 Adjust_Scale
(NFrac
+ 1);
663 -- Otherwise, we get the maximum number of digits available
666 Adjust_Scale
(Maxdigs
);
669 for J
in 1 .. NFrac
- Maxdigs
+ 1 loop
676 Set_Blanks_And_Sign
(Fore
- 1);
681 -- The exponent is the scaling factor adjusted for the digits
682 -- that we output after the decimal point, since these were
683 -- included in the scaled digits that we output.
685 Expon
:= Scale
+ NFrac
;
692 Set_Image_Unsigned
(Unsigned
(Expon
), Digs
, Ndigs
);
695 Set_Image_Unsigned
(Unsigned
(-Expon
), Digs
, Ndigs
);
698 Set_Zeros
(Exp
- Ndigs
- 1);