Daily bump.
[official-gcc.git] / gcc / ada / s-imgrea.adb
blobf013214b1fb481c7d960292b6b250b6b98b7a7ed
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 -- $Revision: 1.2 $
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 -- Extensive contributions were provided by Ada Core Technologies Inc. --
33 -- --
34 ------------------------------------------------------------------------------
36 with System.Img_LLU; use System.Img_LLU;
37 with System.Img_Uns; use System.Img_Uns;
38 with System.Powten_Table; use System.Powten_Table;
39 with System.Unsigned_Types; use System.Unsigned_Types;
41 package body System.Img_Real is
43 -- The following defines the maximum number of digits that we can convert
44 -- accurately. This is limited by the precision of Long_Long_Float, and
45 -- also by the number of digits we can hold in Long_Long_Unsigned, which
46 -- is the integer type we use as an intermediate for the result.
48 -- We assume that in practice, the limitation will come from the digits
49 -- value, rather than the integer value. This is true for typical IEEE
50 -- implementations, and at worst, the only loss is for some precision
51 -- in very high precision floating-point output.
53 -- Note that in the following, the "-2" accounts for the sign and one
54 -- extra digits, since we need the maximum number of 9's that can be
55 -- supported, e.g. for the normal 64 bit case, Long_Long_Integer'Width
56 -- is 21, since the maximum value (approx 1.6 * 10**19) has 20 digits,
57 -- but the maximum number of 9's that can be supported is 19.
59 Maxdigs : constant :=
60 Natural'Min
61 (Long_Long_Unsigned'Width - 2, Long_Long_Float'Digits);
63 Unsdigs : constant := Unsigned'Width - 2;
64 -- Number of digits that can be converted using type Unsigned
65 -- See above for the explanation of the -2.
67 Maxscaling : constant := 5000;
68 -- Max decimal scaling required during conversion of floating-point
69 -- numbers to decimal. This is used to defend against infinite
70 -- looping in the conversion, as can be caused by erroneous executions.
71 -- The largest exponent used on any current system is 2**16383, which
72 -- is approximately 10**4932, and the highest number of decimal digits
73 -- is about 35 for 128-bit floating-point formats, so 5000 leaves
74 -- enough room for scaling such values
76 function Is_Negative (V : Long_Long_Float) return Boolean;
77 pragma Import (Intrinsic, Is_Negative);
79 --------------------------
80 -- Image_Floating_Point --
81 --------------------------
83 function Image_Floating_Point
84 (V : Long_Long_Float;
85 Digs : Natural)
86 return String
88 P : Natural := 0;
89 S : String (1 .. Long_Long_Float'Width);
91 begin
92 if not Is_Negative (V) then
93 S (1) := ' ';
94 P := 1;
95 end if;
97 Set_Image_Real (V, S, P, 1, Digs - 1, 3);
98 return S (1 .. P);
99 end Image_Floating_Point;
101 --------------------------------
102 -- Image_Ordinary_Fixed_Point --
103 --------------------------------
105 function Image_Ordinary_Fixed_Point
106 (V : Long_Long_Float;
107 Aft : Natural)
108 return String
110 P : Natural := 0;
111 S : String (1 .. Long_Long_Float'Width);
113 begin
114 if V >= 0.0 then
115 S (1) := ' ';
116 P := 1;
117 end if;
119 Set_Image_Real (V, S, P, 1, Aft, 0);
120 return S (1 .. P);
121 end Image_Ordinary_Fixed_Point;
123 --------------------
124 -- Set_Image_Real --
125 --------------------
127 procedure Set_Image_Real
128 (V : Long_Long_Float;
129 S : out String;
130 P : in out Natural;
131 Fore : Natural;
132 Aft : Natural;
133 Exp : Natural)
135 procedure Reset;
136 pragma Import (C, Reset, "__gnat_init_float");
137 -- We import the floating-point processor reset routine so that we can
138 -- be sure the floating-point processor is properly set for conversion
139 -- calls (see description of Reset in GNAT.Float_Control (g-flocon.ads).
140 -- This is notably need on Windows, where calls to the operating system
141 -- randomly reset the processor into 64-bit mode.
143 NFrac : constant Natural := Natural'Max (Aft, 1);
144 Sign : Character;
145 X : aliased Long_Long_Float;
146 -- This is declared aliased because the expansion of X'Valid passes
147 -- X by access and JGNAT requires all access parameters to be aliased.
148 -- The Valid attribute probably needs to be handled via a different
149 -- expansion for JGNAT, and this use of aliased should be removed
150 -- once Valid is handled properly. ???
151 Scale : Integer;
152 Expon : Integer;
154 Field_Max : constant := 255;
155 -- This should be the same value as Ada.[Wide_]Text_IO.Field'Last.
156 -- It is not worth dragging in Ada.Text_IO to pick up this value,
157 -- since it really should never be necessary to change it!
159 Digs : String (1 .. 2 * Field_Max + 16);
160 -- Array used to hold digits of converted integer value. This is a
161 -- large enough buffer to accommodate ludicrous values of Fore and Aft.
163 Ndigs : Natural;
164 -- Number of digits stored in Digs (and also subscript of last digit)
166 procedure Adjust_Scale (S : Natural);
167 -- Adjusts the value in X by multiplying or dividing by a power of
168 -- ten so that it is in the range 10**(S-1) <= X < 10**S. Includes
169 -- adding 0.5 to round the result, readjusting if the rounding causes
170 -- the result to wander out of the range. Scale is adjusted to reflect
171 -- the power of ten used to divide the result (i.e. one is added to
172 -- the scale value for each division by 10.0, or one is subtracted
173 -- for each multiplication by 10.0).
175 procedure Convert_Integer;
176 -- Takes the value in X, outputs integer digits into Digs. On return,
177 -- Ndigs is set to the number of digits stored. The digits are stored
178 -- in Digs (1 .. Ndigs),
180 procedure Set (C : Character);
181 -- Sets character C in output buffer
183 procedure Set_Blanks_And_Sign (N : Integer);
184 -- Sets leading blanks and minus sign if needed. N is the number of
185 -- positions to be filled (a minus sign is output even if N is zero
186 -- or negative, but for a positive value, if N is non-positive, then
187 -- the call has no effect).
189 procedure Set_Digs (S, E : Natural);
190 -- Set digits S through E from Digs buffer. No effect if S > E
192 procedure Set_Special_Fill (N : Natural);
193 -- After outputting +Inf, -Inf or NaN, this routine fills out the
194 -- rest of the field with * characters. The argument is the number
195 -- of characters output so far (either 3 or 4)
197 procedure Set_Zeros (N : Integer);
198 -- Set N zeros, no effect if N is negative
200 pragma Inline (Set);
201 pragma Inline (Set_Digs);
202 pragma Inline (Set_Zeros);
204 ------------------
205 -- Adjust_Scale --
206 ------------------
208 procedure Adjust_Scale (S : Natural) is
209 Lo : Natural;
210 Hi : Natural;
211 Mid : Natural;
212 XP : Long_Long_Float;
214 begin
215 -- Cases where scaling up is required
217 if X < Powten (S - 1) then
219 -- What we are looking for is a power of ten to multiply X by
220 -- so that the result lies within the required range.
222 loop
223 XP := X * Powten (Maxpow);
224 exit when XP >= Powten (S - 1) or Scale < -Maxscaling;
225 X := XP;
226 Scale := Scale - Maxpow;
227 end loop;
229 -- The following exception is only raised in case of erroneous
230 -- execution, where a number was considered valid but still
231 -- fails to scale up. One situation where this can happen is
232 -- when a system which is supposed to be IEEE-compliant, but
233 -- has been reconfigured to flush denormals to zero.
235 if Scale < -Maxscaling then
236 raise Constraint_Error;
237 end if;
239 -- Here we know that we must multiply by at least 10**1 and that
240 -- 10**Maxpow takes us too far: binary search to find right one.
242 -- Because of roundoff errors, it is possible for the value
243 -- of XP to be just outside of the interval when Lo >= Hi. In
244 -- that case we adjust explicitly by a factor of 10. This
245 -- can only happen with a value that is very close to an
246 -- exact power of 10.
248 Lo := 1;
249 Hi := Maxpow;
251 loop
252 Mid := (Lo + Hi) / 2;
253 XP := X * Powten (Mid);
255 if XP < Powten (S - 1) then
257 if Lo >= Hi then
258 Mid := Mid + 1;
259 XP := XP * 10.0;
260 exit;
262 else
263 Lo := Mid + 1;
264 end if;
266 elsif XP >= Powten (S) then
268 if Lo >= Hi then
269 Mid := Mid - 1;
270 XP := XP / 10.0;
271 exit;
273 else
274 Hi := Mid - 1;
275 end if;
277 else
278 exit;
279 end if;
280 end loop;
282 X := XP;
283 Scale := Scale - Mid;
285 -- Cases where scaling down is required
287 elsif X >= Powten (S) then
289 -- What we are looking for is a power of ten to divide X by
290 -- so that the result lies within the required range.
292 loop
293 XP := X / Powten (Maxpow);
294 exit when XP < Powten (S) or Scale > Maxscaling;
295 X := XP;
296 Scale := Scale + Maxpow;
297 end loop;
299 -- The following exception is only raised in case of erroneous
300 -- execution, where a number was considered valid but still
301 -- fails to scale up. One situation where this can happen is
302 -- when a system which is supposed to be IEEE-compliant, but
303 -- has been reconfigured to flush denormals to zero.
305 if Scale > Maxscaling then
306 raise Constraint_Error;
307 end if;
309 -- Here we know that we must divide by at least 10**1 and that
310 -- 10**Maxpow takes us too far, binary search to find right one.
312 Lo := 1;
313 Hi := Maxpow;
315 loop
316 Mid := (Lo + Hi) / 2;
317 XP := X / Powten (Mid);
319 if XP < Powten (S - 1) then
321 if Lo >= Hi then
322 XP := XP * 10.0;
323 Mid := Mid - 1;
324 exit;
326 else
327 Hi := Mid - 1;
328 end if;
330 elsif XP >= Powten (S) then
332 if Lo >= Hi then
333 XP := XP / 10.0;
334 Mid := Mid + 1;
335 exit;
337 else
338 Lo := Mid + 1;
339 end if;
341 else
342 exit;
343 end if;
344 end loop;
346 X := XP;
347 Scale := Scale + Mid;
349 -- Here we are already scaled right
351 else
352 null;
353 end if;
355 -- Round, readjusting scale if needed. Note that if a readjustment
356 -- occurs, then it is never necessary to round again, because there
357 -- is no possibility of such a second rounding causing a change.
359 X := X + 0.5;
361 if X >= Powten (S) then
362 X := X / 10.0;
363 Scale := Scale + 1;
364 end if;
366 end Adjust_Scale;
368 ---------------------
369 -- Convert_Integer --
370 ---------------------
372 procedure Convert_Integer is
373 begin
374 -- Use Unsigned routine if possible, since on many machines it will
375 -- be significantly more efficient than the Long_Long_Unsigned one.
377 if X < Powten (Unsdigs) then
378 Ndigs := 0;
379 Set_Image_Unsigned
380 (Unsigned (Long_Long_Float'Truncation (X)),
381 Digs, Ndigs);
383 -- But if we want more digits than fit in Unsigned, we have to use
384 -- the Long_Long_Unsigned routine after all.
386 else
387 Ndigs := 0;
388 Set_Image_Long_Long_Unsigned
389 (Long_Long_Unsigned (Long_Long_Float'Truncation (X)),
390 Digs, Ndigs);
391 end if;
392 end Convert_Integer;
394 ---------
395 -- Set --
396 ---------
398 procedure Set (C : Character) is
399 begin
400 P := P + 1;
401 S (P) := C;
402 end Set;
404 -------------------------
405 -- Set_Blanks_And_Sign --
406 -------------------------
408 procedure Set_Blanks_And_Sign (N : Integer) is
409 begin
410 if Sign = '-' then
411 for J in 1 .. N - 1 loop
412 Set (' ');
413 end loop;
415 Set ('-');
417 else
418 for J in 1 .. N loop
419 Set (' ');
420 end loop;
421 end if;
422 end Set_Blanks_And_Sign;
424 --------------
425 -- Set_Digs --
426 --------------
428 procedure Set_Digs (S, E : Natural) is
429 begin
430 for J in S .. E loop
431 Set (Digs (J));
432 end loop;
433 end Set_Digs;
435 ----------------------
436 -- Set_Special_Fill --
437 ----------------------
439 procedure Set_Special_Fill (N : Natural) is
440 F : Natural;
442 begin
443 F := Fore + 1 + Aft - N;
445 if Exp /= 0 then
446 F := F + Exp + 1;
447 end if;
449 for J in 1 .. F loop
450 Set ('*');
451 end loop;
452 end Set_Special_Fill;
454 ---------------
455 -- Set_Zeros --
456 ---------------
458 procedure Set_Zeros (N : Integer) is
459 begin
460 for J in 1 .. N loop
461 Set ('0');
462 end loop;
463 end Set_Zeros;
465 -- Start of processing for Set_Image_Real
467 begin
468 Reset;
469 Scale := 0;
471 -- Positive values
473 if V > 0.0 then
474 X := V;
475 Sign := '+';
477 -- Negative values
479 elsif V < 0.0 then
480 X := -V;
481 Sign := '-';
483 -- Zero values
485 elsif V = 0.0 then
486 if Long_Long_Float'Signed_Zeros and then Is_Negative (V) then
487 Sign := '-';
488 else
489 Sign := '+';
490 end if;
492 Set_Blanks_And_Sign (Fore - 1);
493 Set ('0');
494 Set ('.');
495 Set_Zeros (NFrac);
497 if Exp /= 0 then
498 Set ('E');
499 Set ('+');
500 Set_Zeros (Natural'Max (1, Exp - 1));
501 end if;
503 return;
504 end if;
506 -- Deal with invalid values
508 if not X'Valid then
510 -- Note that we're taking our chances here, as X might be
511 -- an invalid bit pattern resulting from erroneous execution
512 -- (caused by using uninitialized variables for example).
514 -- No matter what, we'll at least get reasonable behaviour,
515 -- converting to infinity or some other value, or causing an
516 -- exception to be raised is fine.
518 -- If the following test succeeds, then we definitely have
519 -- an infinite value, so we print Inf.
521 if X > Long_Long_Float'Last then
522 Set (Sign);
523 Set ('I');
524 Set ('n');
525 Set ('f');
526 Set_Special_Fill (4);
528 -- In all other cases we print NaN
530 else
531 Set ('N');
532 Set ('a');
533 Set ('N');
534 Set_Special_Fill (3);
535 end if;
537 return;
539 -- Case of non-zero value with Exp = 0
541 elsif Exp = 0 then
543 -- First step is to multiply by 10 ** Nfrac to get an integer
544 -- value to be output, an then add 0.5 to round the result.
546 declare
547 NF : Natural := NFrac;
549 begin
550 loop
551 -- If we are larger than Powten (Maxdigs) now, then
552 -- we have too many significant digits, and we have
553 -- not even finished multiplying by NFrac (NF shows
554 -- the number of unaccounted-for digits).
556 if X >= Powten (Maxdigs) then
558 -- In this situation, we only to generate a reasonable
559 -- number of significant digits, and then zeroes after.
560 -- So first we rescale to get:
562 -- 10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
564 -- and then convert the resulting integer
566 Adjust_Scale (Maxdigs);
567 Convert_Integer;
569 -- If that caused rescaling, then add zeros to the end
570 -- of the number to account for this scaling. Also add
571 -- zeroes to account for the undone multiplications
573 for J in 1 .. Scale + NF loop
574 Ndigs := Ndigs + 1;
575 Digs (Ndigs) := '0';
576 end loop;
578 exit;
580 -- If multiplication is complete, then convert the resulting
581 -- integer after rounding (note that X is non-negative)
583 elsif NF = 0 then
584 X := X + 0.5;
585 Convert_Integer;
586 exit;
588 -- Otherwise we can go ahead with the multiplication. If it
589 -- can be done in one step, then do it in one step.
591 elsif NF < Maxpow then
592 X := X * Powten (NF);
593 NF := 0;
595 -- If it cannot be done in one step, then do partial scaling
597 else
598 X := X * Powten (Maxpow);
599 NF := NF - Maxpow;
600 end if;
601 end loop;
602 end;
604 -- If number of available digits is less or equal to NFrac,
605 -- then we need an extra zero before the decimal point.
607 if Ndigs <= NFrac then
608 Set_Blanks_And_Sign (Fore - 1);
609 Set ('0');
610 Set ('.');
611 Set_Zeros (NFrac - Ndigs);
612 Set_Digs (1, Ndigs);
614 -- Normal case with some digits before the decimal point
616 else
617 Set_Blanks_And_Sign (Fore - (Ndigs - NFrac));
618 Set_Digs (1, Ndigs - NFrac);
619 Set ('.');
620 Set_Digs (Ndigs - NFrac + 1, Ndigs);
621 end if;
623 -- Case of non-zero value with non-zero Exp value
625 else
626 -- If NFrac is less than Maxdigs, then all the fraction digits are
627 -- significant, so we can scale the resulting integer accordingly.
629 if NFrac < Maxdigs then
630 Adjust_Scale (NFrac + 1);
631 Convert_Integer;
633 -- Otherwise, we get the maximum number of digits available
635 else
636 Adjust_Scale (Maxdigs);
637 Convert_Integer;
639 for J in 1 .. NFrac - Maxdigs + 1 loop
640 Ndigs := Ndigs + 1;
641 Digs (Ndigs) := '0';
642 Scale := Scale - 1;
643 end loop;
644 end if;
646 Set_Blanks_And_Sign (Fore - 1);
647 Set (Digs (1));
648 Set ('.');
649 Set_Digs (2, Ndigs);
651 -- The exponent is the scaling factor adjusted for the digits
652 -- that we output after the decimal point, since these were
653 -- included in the scaled digits that we output.
655 Expon := Scale + NFrac;
657 Set ('E');
658 Ndigs := 0;
660 if Expon >= 0 then
661 Set ('+');
662 Set_Image_Unsigned (Unsigned (Expon), Digs, Ndigs);
663 else
664 Set ('-');
665 Set_Image_Unsigned (Unsigned (-Expon), Digs, Ndigs);
666 end if;
668 Set_Zeros (Exp - Ndigs - 1);
669 Set_Digs (1, Ndigs);
670 end if;
672 end Set_Image_Real;
674 end System.Img_Real;