PR middle-end/61455
[official-gcc.git] / gcc / ada / s-imgrea.adb
blobfcfd107dd0327f6fb2a38bec6f4dcc4e471bbb09
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- S Y S T E M . I M G _ R E A L --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
10 -- --
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. --
17 -- --
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. --
21 -- --
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/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
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.
56 Maxdigs : constant :=
57 Natural'Min
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
81 (V : Long_Long_Float;
82 S : in out String;
83 P : out Natural;
84 Digs : Natural)
86 pragma Assert (S'First = 1);
88 begin
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).
98 if not Is_Negative (V)
99 or else (not Long_Long_Float'Signed_Zeros and then V = -0.0)
100 then
101 S (1) := ' ';
102 P := 1;
103 else
104 P := 0;
105 end if;
107 Set_Image_Real (V, S, P, 1, Digs - 1, 3);
108 end Image_Floating_Point;
110 --------------------------------
111 -- Image_Ordinary_Fixed_Point --
112 --------------------------------
114 procedure Image_Ordinary_Fixed_Point
115 (V : Long_Long_Float;
116 S : in out String;
117 P : out Natural;
118 Aft : Natural)
120 pragma Assert (S'First = 1);
122 begin
123 -- Output space at start if non-negative
125 if V >= 0.0 then
126 S (1) := ' ';
127 P := 1;
128 else
129 P := 0;
130 end if;
132 Set_Image_Real (V, S, P, 1, Aft, 0);
133 end Image_Ordinary_Fixed_Point;
135 --------------------
136 -- Set_Image_Real --
137 --------------------
139 procedure Set_Image_Real
140 (V : Long_Long_Float;
141 S : out String;
142 P : in out Natural;
143 Fore : Natural;
144 Aft : Natural;
145 Exp : Natural)
147 NFrac : constant Natural := Natural'Max (Aft, 1);
148 Sign : Character;
149 X : aliased Long_Long_Float;
150 -- This is declared aliased because the expansion of X'Valid passes
151 -- X by access and JGNAT requires all access parameters to be aliased.
152 -- The Valid attribute probably needs to be handled via a different
153 -- expansion for JGNAT, and this use of aliased should be removed
154 -- once Valid is handled properly. ???
155 Scale : Integer;
156 Expon : Integer;
158 Field_Max : constant := 255;
159 -- This should be the same value as Ada.[Wide_]Text_IO.Field'Last.
160 -- It is not worth dragging in Ada.Text_IO to pick up this value,
161 -- since it really should never be necessary to change it.
163 Digs : String (1 .. 2 * Field_Max + 16);
164 -- Array used to hold digits of converted integer value. This is a
165 -- large enough buffer to accommodate ludicrous values of Fore and Aft.
167 Ndigs : Natural;
168 -- Number of digits stored in Digs (and also subscript of last digit)
170 procedure Adjust_Scale (S : Natural);
171 -- Adjusts the value in X by multiplying or dividing by a power of
172 -- ten so that it is in the range 10**(S-1) <= X < 10**S. Includes
173 -- adding 0.5 to round the result, readjusting if the rounding causes
174 -- the result to wander out of the range. Scale is adjusted to reflect
175 -- the power of ten used to divide the result (i.e. one is added to
176 -- the scale value for each division by 10.0, or one is subtracted
177 -- for each multiplication by 10.0).
179 procedure Convert_Integer;
180 -- Takes the value in X, outputs integer digits into Digs. On return,
181 -- Ndigs is set to the number of digits stored. The digits are stored
182 -- in Digs (1 .. Ndigs),
184 procedure Set (C : Character);
185 -- Sets character C in output buffer
187 procedure Set_Blanks_And_Sign (N : Integer);
188 -- Sets leading blanks and minus sign if needed. N is the number of
189 -- positions to be filled (a minus sign is output even if N is zero
190 -- or negative, but for a positive value, if N is non-positive, then
191 -- the call has no effect).
193 procedure Set_Digs (S, E : Natural);
194 -- Set digits S through E from Digs buffer. No effect if S > E
196 procedure Set_Special_Fill (N : Natural);
197 -- After outputting +Inf, -Inf or NaN, this routine fills out the
198 -- rest of the field with * characters. The argument is the number
199 -- of characters output so far (either 3 or 4)
201 procedure Set_Zeros (N : Integer);
202 -- Set N zeros, no effect if N is negative
204 pragma Inline (Set);
205 pragma Inline (Set_Digs);
206 pragma Inline (Set_Zeros);
208 ------------------
209 -- Adjust_Scale --
210 ------------------
212 procedure Adjust_Scale (S : Natural) is
213 Lo : Natural;
214 Hi : Natural;
215 Mid : Natural;
216 XP : Long_Long_Float;
218 begin
219 -- Cases where scaling up is required
221 if X < Powten (S - 1) then
223 -- What we are looking for is a power of ten to multiply X by
224 -- so that the result lies within the required range.
226 loop
227 XP := X * Powten (Maxpow);
228 exit when XP >= Powten (S - 1) or else Scale < -Maxscaling;
229 X := XP;
230 Scale := Scale - Maxpow;
231 end loop;
233 -- The following exception is only raised in case of erroneous
234 -- execution, where a number was considered valid but still
235 -- fails to scale up. One situation where this can happen is
236 -- when a system which is supposed to be IEEE-compliant, but
237 -- has been reconfigured to flush denormals to zero.
239 if Scale < -Maxscaling then
240 raise Constraint_Error;
241 end if;
243 -- Here we know that we must multiply by at least 10**1 and that
244 -- 10**Maxpow takes us too far: binary search to find right one.
246 -- Because of roundoff errors, it is possible for the value
247 -- of XP to be just outside of the interval when Lo >= Hi. In
248 -- that case we adjust explicitly by a factor of 10. This
249 -- can only happen with a value that is very close to an
250 -- exact power of 10.
252 Lo := 1;
253 Hi := Maxpow;
255 loop
256 Mid := (Lo + Hi) / 2;
257 XP := X * Powten (Mid);
259 if XP < Powten (S - 1) then
261 if Lo >= Hi then
262 Mid := Mid + 1;
263 XP := XP * 10.0;
264 exit;
266 else
267 Lo := Mid + 1;
268 end if;
270 elsif XP >= Powten (S) then
272 if Lo >= Hi then
273 Mid := Mid - 1;
274 XP := XP / 10.0;
275 exit;
277 else
278 Hi := Mid - 1;
279 end if;
281 else
282 exit;
283 end if;
284 end loop;
286 X := XP;
287 Scale := Scale - Mid;
289 -- Cases where scaling down is required
291 elsif X >= Powten (S) then
293 -- What we are looking for is a power of ten to divide X by
294 -- so that the result lies within the required range.
296 loop
297 XP := X / Powten (Maxpow);
298 exit when XP < Powten (S) or else Scale > Maxscaling;
299 X := XP;
300 Scale := Scale + Maxpow;
301 end loop;
303 -- The following exception is only raised in case of erroneous
304 -- execution, where a number was considered valid but still
305 -- fails to scale up. One situation where this can happen is
306 -- when a system which is supposed to be IEEE-compliant, but
307 -- has been reconfigured to flush denormals to zero.
309 if Scale > Maxscaling then
310 raise Constraint_Error;
311 end if;
313 -- Here we know that we must divide by at least 10**1 and that
314 -- 10**Maxpow takes us too far, binary search to find right one.
316 Lo := 1;
317 Hi := Maxpow;
319 loop
320 Mid := (Lo + Hi) / 2;
321 XP := X / Powten (Mid);
323 if XP < Powten (S - 1) then
325 if Lo >= Hi then
326 XP := XP * 10.0;
327 Mid := Mid - 1;
328 exit;
330 else
331 Hi := Mid - 1;
332 end if;
334 elsif XP >= Powten (S) then
336 if Lo >= Hi then
337 XP := XP / 10.0;
338 Mid := Mid + 1;
339 exit;
341 else
342 Lo := Mid + 1;
343 end if;
345 else
346 exit;
347 end if;
348 end loop;
350 X := XP;
351 Scale := Scale + Mid;
353 -- Here we are already scaled right
355 else
356 null;
357 end if;
359 -- Round, readjusting scale if needed. Note that if a readjustment
360 -- occurs, then it is never necessary to round again, because there
361 -- is no possibility of such a second rounding causing a change.
363 X := X + 0.5;
365 if X >= Powten (S) then
366 X := X / 10.0;
367 Scale := Scale + 1;
368 end if;
370 end Adjust_Scale;
372 ---------------------
373 -- Convert_Integer --
374 ---------------------
376 procedure Convert_Integer is
377 begin
378 -- Use Unsigned routine if possible, since on many machines it will
379 -- be significantly more efficient than the Long_Long_Unsigned one.
381 if X < Powten (Unsdigs) then
382 Ndigs := 0;
383 Set_Image_Unsigned
384 (Unsigned (Long_Long_Float'Truncation (X)),
385 Digs, Ndigs);
387 -- But if we want more digits than fit in Unsigned, we have to use
388 -- the Long_Long_Unsigned routine after all.
390 else
391 Ndigs := 0;
392 Set_Image_Long_Long_Unsigned
393 (Long_Long_Unsigned (Long_Long_Float'Truncation (X)),
394 Digs, Ndigs);
395 end if;
396 end Convert_Integer;
398 ---------
399 -- Set --
400 ---------
402 procedure Set (C : Character) is
403 begin
404 P := P + 1;
405 S (P) := C;
406 end Set;
408 -------------------------
409 -- Set_Blanks_And_Sign --
410 -------------------------
412 procedure Set_Blanks_And_Sign (N : Integer) is
413 begin
414 if Sign = '-' then
415 for J in 1 .. N - 1 loop
416 Set (' ');
417 end loop;
419 Set ('-');
421 else
422 for J in 1 .. N loop
423 Set (' ');
424 end loop;
425 end if;
426 end Set_Blanks_And_Sign;
428 --------------
429 -- Set_Digs --
430 --------------
432 procedure Set_Digs (S, E : Natural) is
433 begin
434 for J in S .. E loop
435 Set (Digs (J));
436 end loop;
437 end Set_Digs;
439 ----------------------
440 -- Set_Special_Fill --
441 ----------------------
443 procedure Set_Special_Fill (N : Natural) is
444 F : Natural;
446 begin
447 F := Fore + 1 + Aft - N;
449 if Exp /= 0 then
450 F := F + Exp + 1;
451 end if;
453 for J in 1 .. F loop
454 Set ('*');
455 end loop;
456 end Set_Special_Fill;
458 ---------------
459 -- Set_Zeros --
460 ---------------
462 procedure Set_Zeros (N : Integer) is
463 begin
464 for J in 1 .. N loop
465 Set ('0');
466 end loop;
467 end Set_Zeros;
469 -- Start of processing for Set_Image_Real
471 begin
472 -- We call the floating-point processor reset routine so that we can
473 -- be sure the floating-point processor is properly set for conversion
474 -- calls. This is notably need on Windows, where calls to the operating
475 -- system randomly reset the processor into 64-bit mode.
477 System.Float_Control.Reset;
479 Scale := 0;
481 -- Deal with invalid values first,
483 if not V'Valid then
485 -- Note that we're taking our chances here, as V might be
486 -- an invalid bit pattern resulting from erroneous execution
487 -- (caused by using uninitialized variables for example).
489 -- No matter what, we'll at least get reasonable behaviour,
490 -- converting to infinity or some other value, or causing an
491 -- exception to be raised is fine.
493 -- If the following test succeeds, then we definitely have
494 -- an infinite value, so we print Inf.
496 if V > Long_Long_Float'Last then
497 Set ('+');
498 Set ('I');
499 Set ('n');
500 Set ('f');
501 Set_Special_Fill (4);
503 -- In all other cases we print NaN
505 elsif V < Long_Long_Float'First then
506 Set ('-');
507 Set ('I');
508 Set ('n');
509 Set ('f');
510 Set_Special_Fill (4);
512 else
513 Set ('N');
514 Set ('a');
515 Set ('N');
516 Set_Special_Fill (3);
517 end if;
519 return;
520 end if;
522 -- Positive values
524 if V > 0.0 then
525 X := V;
526 Sign := '+';
528 -- Negative values
530 elsif V < 0.0 then
531 X := -V;
532 Sign := '-';
534 -- Zero values
536 elsif V = 0.0 then
537 if Long_Long_Float'Signed_Zeros and then Is_Negative (V) then
538 Sign := '-';
539 else
540 Sign := '+';
541 end if;
543 Set_Blanks_And_Sign (Fore - 1);
544 Set ('0');
545 Set ('.');
546 Set_Zeros (NFrac);
548 if Exp /= 0 then
549 Set ('E');
550 Set ('+');
551 Set_Zeros (Natural'Max (1, Exp - 1));
552 end if;
554 return;
556 else
557 -- It should not be possible for a NaN to end up here.
558 -- Either the 'Valid test has failed, or we have some form
559 -- of erroneous execution. Raise Constraint_Error instead of
560 -- attempting to go ahead printing the value.
562 raise Constraint_Error;
563 end if;
565 -- X and Sign are set here, and X is known to be a valid,
566 -- non-zero floating-point number.
568 -- Case of non-zero value with Exp = 0
570 if Exp = 0 then
572 -- First step is to multiply by 10 ** Nfrac to get an integer
573 -- value to be output, an then add 0.5 to round the result.
575 declare
576 NF : Natural := NFrac;
578 begin
579 loop
580 -- If we are larger than Powten (Maxdigs) now, then
581 -- we have too many significant digits, and we have
582 -- not even finished multiplying by NFrac (NF shows
583 -- the number of unaccounted-for digits).
585 if X >= Powten (Maxdigs) then
587 -- In this situation, we only to generate a reasonable
588 -- number of significant digits, and then zeroes after.
589 -- So first we rescale to get:
591 -- 10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
593 -- and then convert the resulting integer
595 Adjust_Scale (Maxdigs);
596 Convert_Integer;
598 -- If that caused rescaling, then add zeros to the end
599 -- of the number to account for this scaling. Also add
600 -- zeroes to account for the undone multiplications
602 for J in 1 .. Scale + NF loop
603 Ndigs := Ndigs + 1;
604 Digs (Ndigs) := '0';
605 end loop;
607 exit;
609 -- If multiplication is complete, then convert the resulting
610 -- integer after rounding (note that X is non-negative)
612 elsif NF = 0 then
613 X := X + 0.5;
614 Convert_Integer;
615 exit;
617 -- Otherwise we can go ahead with the multiplication. If it
618 -- can be done in one step, then do it in one step.
620 elsif NF < Maxpow then
621 X := X * Powten (NF);
622 NF := 0;
624 -- If it cannot be done in one step, then do partial scaling
626 else
627 X := X * Powten (Maxpow);
628 NF := NF - Maxpow;
629 end if;
630 end loop;
631 end;
633 -- If number of available digits is less or equal to NFrac,
634 -- then we need an extra zero before the decimal point.
636 if Ndigs <= NFrac then
637 Set_Blanks_And_Sign (Fore - 1);
638 Set ('0');
639 Set ('.');
640 Set_Zeros (NFrac - Ndigs);
641 Set_Digs (1, Ndigs);
643 -- Normal case with some digits before the decimal point
645 else
646 Set_Blanks_And_Sign (Fore - (Ndigs - NFrac));
647 Set_Digs (1, Ndigs - NFrac);
648 Set ('.');
649 Set_Digs (Ndigs - NFrac + 1, Ndigs);
650 end if;
652 -- Case of non-zero value with non-zero Exp value
654 else
655 -- If NFrac is less than Maxdigs, then all the fraction digits are
656 -- significant, so we can scale the resulting integer accordingly.
658 if NFrac < Maxdigs then
659 Adjust_Scale (NFrac + 1);
660 Convert_Integer;
662 -- Otherwise, we get the maximum number of digits available
664 else
665 Adjust_Scale (Maxdigs);
666 Convert_Integer;
668 for J in 1 .. NFrac - Maxdigs + 1 loop
669 Ndigs := Ndigs + 1;
670 Digs (Ndigs) := '0';
671 Scale := Scale - 1;
672 end loop;
673 end if;
675 Set_Blanks_And_Sign (Fore - 1);
676 Set (Digs (1));
677 Set ('.');
678 Set_Digs (2, Ndigs);
680 -- The exponent is the scaling factor adjusted for the digits
681 -- that we output after the decimal point, since these were
682 -- included in the scaled digits that we output.
684 Expon := Scale + NFrac;
686 Set ('E');
687 Ndigs := 0;
689 if Expon >= 0 then
690 Set ('+');
691 Set_Image_Unsigned (Unsigned (Expon), Digs, Ndigs);
692 else
693 Set ('-');
694 Set_Image_Unsigned (Unsigned (-Expon), Digs, Ndigs);
695 end if;
697 Set_Zeros (Exp - Ndigs - 1);
698 Set_Digs (1, Ndigs);
699 end if;
701 end Set_Image_Real;
703 end System.Img_Real;