* doc/install.texi (Prerequisites): New section documenting
[official-gcc.git] / gcc / ada / s-imgrea.adb
blob89bbccef576a9a50e1204c8939deb6535c4174b7
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-2001 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 with System.Img_LLU; use System.Img_LLU;
35 with System.Img_Uns; use System.Img_Uns;
36 with System.Powten_Table; use System.Powten_Table;
37 with System.Unsigned_Types; use System.Unsigned_Types;
39 package body System.Img_Real is
41 -- The following defines the maximum number of digits that we can convert
42 -- accurately. This is limited by the precision of Long_Long_Float, and
43 -- also by the number of digits we can hold in Long_Long_Unsigned, which
44 -- is the integer type we use as an intermediate for the result.
46 -- We assume that in practice, the limitation will come from the digits
47 -- value, rather than the integer value. This is true for typical IEEE
48 -- implementations, and at worst, the only loss is for some precision
49 -- in very high precision floating-point output.
51 -- Note that in the following, the "-2" accounts for the sign and one
52 -- extra digits, since we need the maximum number of 9's that can be
53 -- supported, e.g. for the normal 64 bit case, Long_Long_Integer'Width
54 -- is 21, since the maximum value (approx 1.6 * 10**19) has 20 digits,
55 -- but the maximum number of 9's that can be supported is 19.
57 Maxdigs : constant :=
58 Natural'Min
59 (Long_Long_Unsigned'Width - 2, Long_Long_Float'Digits);
61 Unsdigs : constant := Unsigned'Width - 2;
62 -- Number of digits that can be converted using type Unsigned
63 -- See above for the explanation of the -2.
65 Maxscaling : constant := 5000;
66 -- Max decimal scaling required during conversion of floating-point
67 -- numbers to decimal. This is used to defend against infinite
68 -- looping in the conversion, as can be caused by erroneous executions.
69 -- The largest exponent used on any current system is 2**16383, which
70 -- is approximately 10**4932, and the highest number of decimal digits
71 -- is about 35 for 128-bit floating-point formats, so 5000 leaves
72 -- enough room for scaling such values
74 function Is_Negative (V : Long_Long_Float) return Boolean;
75 pragma Import (Intrinsic, Is_Negative);
77 --------------------------
78 -- Image_Floating_Point --
79 --------------------------
81 function Image_Floating_Point
82 (V : Long_Long_Float;
83 Digs : Natural)
84 return String
86 P : Natural := 0;
87 S : String (1 .. Long_Long_Float'Width);
89 begin
90 if not Is_Negative (V) then
91 S (1) := ' ';
92 P := 1;
93 end if;
95 Set_Image_Real (V, S, P, 1, Digs - 1, 3);
96 return S (1 .. P);
97 end Image_Floating_Point;
99 --------------------------------
100 -- Image_Ordinary_Fixed_Point --
101 --------------------------------
103 function Image_Ordinary_Fixed_Point
104 (V : Long_Long_Float;
105 Aft : Natural)
106 return String
108 P : Natural := 0;
109 S : String (1 .. Long_Long_Float'Width);
111 begin
112 if V >= 0.0 then
113 S (1) := ' ';
114 P := 1;
115 end if;
117 Set_Image_Real (V, S, P, 1, Aft, 0);
118 return S (1 .. P);
119 end Image_Ordinary_Fixed_Point;
121 --------------------
122 -- Set_Image_Real --
123 --------------------
125 procedure Set_Image_Real
126 (V : Long_Long_Float;
127 S : out String;
128 P : in out Natural;
129 Fore : Natural;
130 Aft : Natural;
131 Exp : Natural)
133 procedure Reset;
134 pragma Import (C, Reset, "__gnat_init_float");
135 -- We import the floating-point processor reset routine so that we can
136 -- be sure the floating-point processor is properly set for conversion
137 -- calls (see description of Reset in GNAT.Float_Control (g-flocon.ads).
138 -- This is notably need on Windows, where calls to the operating system
139 -- randomly reset the processor into 64-bit mode.
141 NFrac : constant Natural := Natural'Max (Aft, 1);
142 Sign : Character;
143 X : aliased Long_Long_Float;
144 -- This is declared aliased because the expansion of X'Valid passes
145 -- X by access and JGNAT requires all access parameters to be aliased.
146 -- The Valid attribute probably needs to be handled via a different
147 -- expansion for JGNAT, and this use of aliased should be removed
148 -- once Valid is handled properly. ???
149 Scale : Integer;
150 Expon : Integer;
152 Field_Max : constant := 255;
153 -- This should be the same value as Ada.[Wide_]Text_IO.Field'Last.
154 -- It is not worth dragging in Ada.Text_IO to pick up this value,
155 -- since it really should never be necessary to change it!
157 Digs : String (1 .. 2 * Field_Max + 16);
158 -- Array used to hold digits of converted integer value. This is a
159 -- large enough buffer to accommodate ludicrous values of Fore and Aft.
161 Ndigs : Natural;
162 -- Number of digits stored in Digs (and also subscript of last digit)
164 procedure Adjust_Scale (S : Natural);
165 -- Adjusts the value in X by multiplying or dividing by a power of
166 -- ten so that it is in the range 10**(S-1) <= X < 10**S. Includes
167 -- adding 0.5 to round the result, readjusting if the rounding causes
168 -- the result to wander out of the range. Scale is adjusted to reflect
169 -- the power of ten used to divide the result (i.e. one is added to
170 -- the scale value for each division by 10.0, or one is subtracted
171 -- for each multiplication by 10.0).
173 procedure Convert_Integer;
174 -- Takes the value in X, outputs integer digits into Digs. On return,
175 -- Ndigs is set to the number of digits stored. The digits are stored
176 -- in Digs (1 .. Ndigs),
178 procedure Set (C : Character);
179 -- Sets character C in output buffer
181 procedure Set_Blanks_And_Sign (N : Integer);
182 -- Sets leading blanks and minus sign if needed. N is the number of
183 -- positions to be filled (a minus sign is output even if N is zero
184 -- or negative, but for a positive value, if N is non-positive, then
185 -- the call has no effect).
187 procedure Set_Digs (S, E : Natural);
188 -- Set digits S through E from Digs buffer. No effect if S > E
190 procedure Set_Special_Fill (N : Natural);
191 -- After outputting +Inf, -Inf or NaN, this routine fills out the
192 -- rest of the field with * characters. The argument is the number
193 -- of characters output so far (either 3 or 4)
195 procedure Set_Zeros (N : Integer);
196 -- Set N zeros, no effect if N is negative
198 pragma Inline (Set);
199 pragma Inline (Set_Digs);
200 pragma Inline (Set_Zeros);
202 ------------------
203 -- Adjust_Scale --
204 ------------------
206 procedure Adjust_Scale (S : Natural) is
207 Lo : Natural;
208 Hi : Natural;
209 Mid : Natural;
210 XP : Long_Long_Float;
212 begin
213 -- Cases where scaling up is required
215 if X < Powten (S - 1) then
217 -- What we are looking for is a power of ten to multiply X by
218 -- so that the result lies within the required range.
220 loop
221 XP := X * Powten (Maxpow);
222 exit when XP >= Powten (S - 1) or Scale < -Maxscaling;
223 X := XP;
224 Scale := Scale - Maxpow;
225 end loop;
227 -- The following exception is only raised in case of erroneous
228 -- execution, where a number was considered valid but still
229 -- fails to scale up. One situation where this can happen is
230 -- when a system which is supposed to be IEEE-compliant, but
231 -- has been reconfigured to flush denormals to zero.
233 if Scale < -Maxscaling then
234 raise Constraint_Error;
235 end if;
237 -- Here we know that we must multiply by at least 10**1 and that
238 -- 10**Maxpow takes us too far: binary search to find right one.
240 -- Because of roundoff errors, it is possible for the value
241 -- of XP to be just outside of the interval when Lo >= Hi. In
242 -- that case we adjust explicitly by a factor of 10. This
243 -- can only happen with a value that is very close to an
244 -- exact power of 10.
246 Lo := 1;
247 Hi := Maxpow;
249 loop
250 Mid := (Lo + Hi) / 2;
251 XP := X * Powten (Mid);
253 if XP < Powten (S - 1) then
255 if Lo >= Hi then
256 Mid := Mid + 1;
257 XP := XP * 10.0;
258 exit;
260 else
261 Lo := Mid + 1;
262 end if;
264 elsif XP >= Powten (S) then
266 if Lo >= Hi then
267 Mid := Mid - 1;
268 XP := XP / 10.0;
269 exit;
271 else
272 Hi := Mid - 1;
273 end if;
275 else
276 exit;
277 end if;
278 end loop;
280 X := XP;
281 Scale := Scale - Mid;
283 -- Cases where scaling down is required
285 elsif X >= Powten (S) then
287 -- What we are looking for is a power of ten to divide X by
288 -- so that the result lies within the required range.
290 loop
291 XP := X / Powten (Maxpow);
292 exit when XP < Powten (S) or Scale > Maxscaling;
293 X := XP;
294 Scale := Scale + Maxpow;
295 end loop;
297 -- The following exception is only raised in case of erroneous
298 -- execution, where a number was considered valid but still
299 -- fails to scale up. One situation where this can happen is
300 -- when a system which is supposed to be IEEE-compliant, but
301 -- has been reconfigured to flush denormals to zero.
303 if Scale > Maxscaling then
304 raise Constraint_Error;
305 end if;
307 -- Here we know that we must divide by at least 10**1 and that
308 -- 10**Maxpow takes us too far, binary search to find right one.
310 Lo := 1;
311 Hi := Maxpow;
313 loop
314 Mid := (Lo + Hi) / 2;
315 XP := X / Powten (Mid);
317 if XP < Powten (S - 1) then
319 if Lo >= Hi then
320 XP := XP * 10.0;
321 Mid := Mid - 1;
322 exit;
324 else
325 Hi := Mid - 1;
326 end if;
328 elsif XP >= Powten (S) then
330 if Lo >= Hi then
331 XP := XP / 10.0;
332 Mid := Mid + 1;
333 exit;
335 else
336 Lo := Mid + 1;
337 end if;
339 else
340 exit;
341 end if;
342 end loop;
344 X := XP;
345 Scale := Scale + Mid;
347 -- Here we are already scaled right
349 else
350 null;
351 end if;
353 -- Round, readjusting scale if needed. Note that if a readjustment
354 -- occurs, then it is never necessary to round again, because there
355 -- is no possibility of such a second rounding causing a change.
357 X := X + 0.5;
359 if X >= Powten (S) then
360 X := X / 10.0;
361 Scale := Scale + 1;
362 end if;
364 end Adjust_Scale;
366 ---------------------
367 -- Convert_Integer --
368 ---------------------
370 procedure Convert_Integer is
371 begin
372 -- Use Unsigned routine if possible, since on many machines it will
373 -- be significantly more efficient than the Long_Long_Unsigned one.
375 if X < Powten (Unsdigs) then
376 Ndigs := 0;
377 Set_Image_Unsigned
378 (Unsigned (Long_Long_Float'Truncation (X)),
379 Digs, Ndigs);
381 -- But if we want more digits than fit in Unsigned, we have to use
382 -- the Long_Long_Unsigned routine after all.
384 else
385 Ndigs := 0;
386 Set_Image_Long_Long_Unsigned
387 (Long_Long_Unsigned (Long_Long_Float'Truncation (X)),
388 Digs, Ndigs);
389 end if;
390 end Convert_Integer;
392 ---------
393 -- Set --
394 ---------
396 procedure Set (C : Character) is
397 begin
398 P := P + 1;
399 S (P) := C;
400 end Set;
402 -------------------------
403 -- Set_Blanks_And_Sign --
404 -------------------------
406 procedure Set_Blanks_And_Sign (N : Integer) is
407 begin
408 if Sign = '-' then
409 for J in 1 .. N - 1 loop
410 Set (' ');
411 end loop;
413 Set ('-');
415 else
416 for J in 1 .. N loop
417 Set (' ');
418 end loop;
419 end if;
420 end Set_Blanks_And_Sign;
422 --------------
423 -- Set_Digs --
424 --------------
426 procedure Set_Digs (S, E : Natural) is
427 begin
428 for J in S .. E loop
429 Set (Digs (J));
430 end loop;
431 end Set_Digs;
433 ----------------------
434 -- Set_Special_Fill --
435 ----------------------
437 procedure Set_Special_Fill (N : Natural) is
438 F : Natural;
440 begin
441 F := Fore + 1 + Aft - N;
443 if Exp /= 0 then
444 F := F + Exp + 1;
445 end if;
447 for J in 1 .. F loop
448 Set ('*');
449 end loop;
450 end Set_Special_Fill;
452 ---------------
453 -- Set_Zeros --
454 ---------------
456 procedure Set_Zeros (N : Integer) is
457 begin
458 for J in 1 .. N loop
459 Set ('0');
460 end loop;
461 end Set_Zeros;
463 -- Start of processing for Set_Image_Real
465 begin
466 Reset;
467 Scale := 0;
469 -- Positive values
471 if V > 0.0 then
472 X := V;
473 Sign := '+';
475 -- Negative values
477 elsif V < 0.0 then
478 X := -V;
479 Sign := '-';
481 -- Zero values
483 elsif V = 0.0 then
484 if Long_Long_Float'Signed_Zeros and then Is_Negative (V) then
485 Sign := '-';
486 else
487 Sign := '+';
488 end if;
490 Set_Blanks_And_Sign (Fore - 1);
491 Set ('0');
492 Set ('.');
493 Set_Zeros (NFrac);
495 if Exp /= 0 then
496 Set ('E');
497 Set ('+');
498 Set_Zeros (Natural'Max (1, Exp - 1));
499 end if;
501 return;
502 end if;
504 -- Deal with invalid values
506 if not X'Valid then
508 -- Note that we're taking our chances here, as X might be
509 -- an invalid bit pattern resulting from erroneous execution
510 -- (caused by using uninitialized variables for example).
512 -- No matter what, we'll at least get reasonable behaviour,
513 -- converting to infinity or some other value, or causing an
514 -- exception to be raised is fine.
516 -- If the following test succeeds, then we definitely have
517 -- an infinite value, so we print Inf.
519 if X > Long_Long_Float'Last then
520 Set (Sign);
521 Set ('I');
522 Set ('n');
523 Set ('f');
524 Set_Special_Fill (4);
526 -- In all other cases we print NaN
528 else
529 Set ('N');
530 Set ('a');
531 Set ('N');
532 Set_Special_Fill (3);
533 end if;
535 return;
537 -- Case of non-zero value with Exp = 0
539 elsif Exp = 0 then
541 -- First step is to multiply by 10 ** Nfrac to get an integer
542 -- value to be output, an then add 0.5 to round the result.
544 declare
545 NF : Natural := NFrac;
547 begin
548 loop
549 -- If we are larger than Powten (Maxdigs) now, then
550 -- we have too many significant digits, and we have
551 -- not even finished multiplying by NFrac (NF shows
552 -- the number of unaccounted-for digits).
554 if X >= Powten (Maxdigs) then
556 -- In this situation, we only to generate a reasonable
557 -- number of significant digits, and then zeroes after.
558 -- So first we rescale to get:
560 -- 10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
562 -- and then convert the resulting integer
564 Adjust_Scale (Maxdigs);
565 Convert_Integer;
567 -- If that caused rescaling, then add zeros to the end
568 -- of the number to account for this scaling. Also add
569 -- zeroes to account for the undone multiplications
571 for J in 1 .. Scale + NF loop
572 Ndigs := Ndigs + 1;
573 Digs (Ndigs) := '0';
574 end loop;
576 exit;
578 -- If multiplication is complete, then convert the resulting
579 -- integer after rounding (note that X is non-negative)
581 elsif NF = 0 then
582 X := X + 0.5;
583 Convert_Integer;
584 exit;
586 -- Otherwise we can go ahead with the multiplication. If it
587 -- can be done in one step, then do it in one step.
589 elsif NF < Maxpow then
590 X := X * Powten (NF);
591 NF := 0;
593 -- If it cannot be done in one step, then do partial scaling
595 else
596 X := X * Powten (Maxpow);
597 NF := NF - Maxpow;
598 end if;
599 end loop;
600 end;
602 -- If number of available digits is less or equal to NFrac,
603 -- then we need an extra zero before the decimal point.
605 if Ndigs <= NFrac then
606 Set_Blanks_And_Sign (Fore - 1);
607 Set ('0');
608 Set ('.');
609 Set_Zeros (NFrac - Ndigs);
610 Set_Digs (1, Ndigs);
612 -- Normal case with some digits before the decimal point
614 else
615 Set_Blanks_And_Sign (Fore - (Ndigs - NFrac));
616 Set_Digs (1, Ndigs - NFrac);
617 Set ('.');
618 Set_Digs (Ndigs - NFrac + 1, Ndigs);
619 end if;
621 -- Case of non-zero value with non-zero Exp value
623 else
624 -- If NFrac is less than Maxdigs, then all the fraction digits are
625 -- significant, so we can scale the resulting integer accordingly.
627 if NFrac < Maxdigs then
628 Adjust_Scale (NFrac + 1);
629 Convert_Integer;
631 -- Otherwise, we get the maximum number of digits available
633 else
634 Adjust_Scale (Maxdigs);
635 Convert_Integer;
637 for J in 1 .. NFrac - Maxdigs + 1 loop
638 Ndigs := Ndigs + 1;
639 Digs (Ndigs) := '0';
640 Scale := Scale - 1;
641 end loop;
642 end if;
644 Set_Blanks_And_Sign (Fore - 1);
645 Set (Digs (1));
646 Set ('.');
647 Set_Digs (2, Ndigs);
649 -- The exponent is the scaling factor adjusted for the digits
650 -- that we output after the decimal point, since these were
651 -- included in the scaled digits that we output.
653 Expon := Scale + NFrac;
655 Set ('E');
656 Ndigs := 0;
658 if Expon >= 0 then
659 Set ('+');
660 Set_Image_Unsigned (Unsigned (Expon), Digs, Ndigs);
661 else
662 Set ('-');
663 Set_Image_Unsigned (Unsigned (-Expon), Digs, Ndigs);
664 end if;
666 Set_Zeros (Exp - Ndigs - 1);
667 Set_Digs (1, Ndigs);
668 end if;
670 end Set_Image_Real;
672 end System.Img_Real;