Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / gcc / ada / s-imgrea.adb
blobae939de5fa310094fa6dfb0e89042a9dee4e33e9
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-2002 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, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, 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 -- Decide wether a blank should be prepended before the call to
91 -- Set_Image_Real. We generate a blank for positive values, and
92 -- also for positive zeroes. For negative zeroes, we generate a
93 -- space only if Signed_Zeroes is True (the RM only permits the
94 -- output of -0.0 on targets where this is the case). We can of
95 -- course still see a -0.0 on a target where Signed_Zeroes is
96 -- False (since this attribute refers to the proper handling of
97 -- negative zeroes, not to their existence).
99 if not Is_Negative (V)
100 or else (not Long_Long_Float'Signed_Zeros and then V = -0.0)
101 then
102 S (1) := ' ';
103 P := 1;
104 end if;
106 Set_Image_Real (V, S, P, 1, Digs - 1, 3);
107 return S (1 .. P);
108 end Image_Floating_Point;
110 --------------------------------
111 -- Image_Ordinary_Fixed_Point --
112 --------------------------------
114 function Image_Ordinary_Fixed_Point
115 (V : Long_Long_Float;
116 Aft : Natural)
117 return String
119 P : Natural := 0;
120 S : String (1 .. Long_Long_Float'Width);
122 begin
123 if V >= 0.0 then
124 S (1) := ' ';
125 P := 1;
126 end if;
128 Set_Image_Real (V, S, P, 1, Aft, 0);
129 return S (1 .. P);
130 end Image_Ordinary_Fixed_Point;
132 --------------------
133 -- Set_Image_Real --
134 --------------------
136 procedure Set_Image_Real
137 (V : Long_Long_Float;
138 S : out String;
139 P : in out Natural;
140 Fore : Natural;
141 Aft : Natural;
142 Exp : Natural)
144 procedure Reset;
145 pragma Import (C, Reset, "__gnat_init_float");
146 -- We import the floating-point processor reset routine so that we can
147 -- be sure the floating-point processor is properly set for conversion
148 -- calls (see description of Reset in GNAT.Float_Control (g-flocon.ads).
149 -- This is notably need on Windows, where calls to the operating system
150 -- randomly reset the processor into 64-bit mode.
152 NFrac : constant Natural := Natural'Max (Aft, 1);
153 Sign : Character;
154 X : aliased Long_Long_Float;
155 -- This is declared aliased because the expansion of X'Valid passes
156 -- X by access and JGNAT requires all access parameters to be aliased.
157 -- The Valid attribute probably needs to be handled via a different
158 -- expansion for JGNAT, and this use of aliased should be removed
159 -- once Valid is handled properly. ???
160 Scale : Integer;
161 Expon : Integer;
163 Field_Max : constant := 255;
164 -- This should be the same value as Ada.[Wide_]Text_IO.Field'Last.
165 -- It is not worth dragging in Ada.Text_IO to pick up this value,
166 -- since it really should never be necessary to change it!
168 Digs : String (1 .. 2 * Field_Max + 16);
169 -- Array used to hold digits of converted integer value. This is a
170 -- large enough buffer to accommodate ludicrous values of Fore and Aft.
172 Ndigs : Natural;
173 -- Number of digits stored in Digs (and also subscript of last digit)
175 procedure Adjust_Scale (S : Natural);
176 -- Adjusts the value in X by multiplying or dividing by a power of
177 -- ten so that it is in the range 10**(S-1) <= X < 10**S. Includes
178 -- adding 0.5 to round the result, readjusting if the rounding causes
179 -- the result to wander out of the range. Scale is adjusted to reflect
180 -- the power of ten used to divide the result (i.e. one is added to
181 -- the scale value for each division by 10.0, or one is subtracted
182 -- for each multiplication by 10.0).
184 procedure Convert_Integer;
185 -- Takes the value in X, outputs integer digits into Digs. On return,
186 -- Ndigs is set to the number of digits stored. The digits are stored
187 -- in Digs (1 .. Ndigs),
189 procedure Set (C : Character);
190 -- Sets character C in output buffer
192 procedure Set_Blanks_And_Sign (N : Integer);
193 -- Sets leading blanks and minus sign if needed. N is the number of
194 -- positions to be filled (a minus sign is output even if N is zero
195 -- or negative, but for a positive value, if N is non-positive, then
196 -- the call has no effect).
198 procedure Set_Digs (S, E : Natural);
199 -- Set digits S through E from Digs buffer. No effect if S > E
201 procedure Set_Special_Fill (N : Natural);
202 -- After outputting +Inf, -Inf or NaN, this routine fills out the
203 -- rest of the field with * characters. The argument is the number
204 -- of characters output so far (either 3 or 4)
206 procedure Set_Zeros (N : Integer);
207 -- Set N zeros, no effect if N is negative
209 pragma Inline (Set);
210 pragma Inline (Set_Digs);
211 pragma Inline (Set_Zeros);
213 ------------------
214 -- Adjust_Scale --
215 ------------------
217 procedure Adjust_Scale (S : Natural) is
218 Lo : Natural;
219 Hi : Natural;
220 Mid : Natural;
221 XP : Long_Long_Float;
223 begin
224 -- Cases where scaling up is required
226 if X < Powten (S - 1) then
228 -- What we are looking for is a power of ten to multiply X by
229 -- so that the result lies within the required range.
231 loop
232 XP := X * Powten (Maxpow);
233 exit when XP >= Powten (S - 1) or Scale < -Maxscaling;
234 X := XP;
235 Scale := Scale - Maxpow;
236 end loop;
238 -- The following exception is only raised in case of erroneous
239 -- execution, where a number was considered valid but still
240 -- fails to scale up. One situation where this can happen is
241 -- when a system which is supposed to be IEEE-compliant, but
242 -- has been reconfigured to flush denormals to zero.
244 if Scale < -Maxscaling then
245 raise Constraint_Error;
246 end if;
248 -- Here we know that we must multiply by at least 10**1 and that
249 -- 10**Maxpow takes us too far: binary search to find right one.
251 -- Because of roundoff errors, it is possible for the value
252 -- of XP to be just outside of the interval when Lo >= Hi. In
253 -- that case we adjust explicitly by a factor of 10. This
254 -- can only happen with a value that is very close to an
255 -- exact power of 10.
257 Lo := 1;
258 Hi := Maxpow;
260 loop
261 Mid := (Lo + Hi) / 2;
262 XP := X * Powten (Mid);
264 if XP < Powten (S - 1) then
266 if Lo >= Hi then
267 Mid := Mid + 1;
268 XP := XP * 10.0;
269 exit;
271 else
272 Lo := Mid + 1;
273 end if;
275 elsif XP >= Powten (S) then
277 if Lo >= Hi then
278 Mid := Mid - 1;
279 XP := XP / 10.0;
280 exit;
282 else
283 Hi := Mid - 1;
284 end if;
286 else
287 exit;
288 end if;
289 end loop;
291 X := XP;
292 Scale := Scale - Mid;
294 -- Cases where scaling down is required
296 elsif X >= Powten (S) then
298 -- What we are looking for is a power of ten to divide X by
299 -- so that the result lies within the required range.
301 loop
302 XP := X / Powten (Maxpow);
303 exit when XP < Powten (S) or Scale > Maxscaling;
304 X := XP;
305 Scale := Scale + Maxpow;
306 end loop;
308 -- The following exception is only raised in case of erroneous
309 -- execution, where a number was considered valid but still
310 -- fails to scale up. One situation where this can happen is
311 -- when a system which is supposed to be IEEE-compliant, but
312 -- has been reconfigured to flush denormals to zero.
314 if Scale > Maxscaling then
315 raise Constraint_Error;
316 end if;
318 -- Here we know that we must divide by at least 10**1 and that
319 -- 10**Maxpow takes us too far, binary search to find right one.
321 Lo := 1;
322 Hi := Maxpow;
324 loop
325 Mid := (Lo + Hi) / 2;
326 XP := X / Powten (Mid);
328 if XP < Powten (S - 1) then
330 if Lo >= Hi then
331 XP := XP * 10.0;
332 Mid := Mid - 1;
333 exit;
335 else
336 Hi := Mid - 1;
337 end if;
339 elsif XP >= Powten (S) then
341 if Lo >= Hi then
342 XP := XP / 10.0;
343 Mid := Mid + 1;
344 exit;
346 else
347 Lo := Mid + 1;
348 end if;
350 else
351 exit;
352 end if;
353 end loop;
355 X := XP;
356 Scale := Scale + Mid;
358 -- Here we are already scaled right
360 else
361 null;
362 end if;
364 -- Round, readjusting scale if needed. Note that if a readjustment
365 -- occurs, then it is never necessary to round again, because there
366 -- is no possibility of such a second rounding causing a change.
368 X := X + 0.5;
370 if X >= Powten (S) then
371 X := X / 10.0;
372 Scale := Scale + 1;
373 end if;
375 end Adjust_Scale;
377 ---------------------
378 -- Convert_Integer --
379 ---------------------
381 procedure Convert_Integer is
382 begin
383 -- Use Unsigned routine if possible, since on many machines it will
384 -- be significantly more efficient than the Long_Long_Unsigned one.
386 if X < Powten (Unsdigs) then
387 Ndigs := 0;
388 Set_Image_Unsigned
389 (Unsigned (Long_Long_Float'Truncation (X)),
390 Digs, Ndigs);
392 -- But if we want more digits than fit in Unsigned, we have to use
393 -- the Long_Long_Unsigned routine after all.
395 else
396 Ndigs := 0;
397 Set_Image_Long_Long_Unsigned
398 (Long_Long_Unsigned (Long_Long_Float'Truncation (X)),
399 Digs, Ndigs);
400 end if;
401 end Convert_Integer;
403 ---------
404 -- Set --
405 ---------
407 procedure Set (C : Character) is
408 begin
409 P := P + 1;
410 S (P) := C;
411 end Set;
413 -------------------------
414 -- Set_Blanks_And_Sign --
415 -------------------------
417 procedure Set_Blanks_And_Sign (N : Integer) is
418 begin
419 if Sign = '-' then
420 for J in 1 .. N - 1 loop
421 Set (' ');
422 end loop;
424 Set ('-');
426 else
427 for J in 1 .. N loop
428 Set (' ');
429 end loop;
430 end if;
431 end Set_Blanks_And_Sign;
433 --------------
434 -- Set_Digs --
435 --------------
437 procedure Set_Digs (S, E : Natural) is
438 begin
439 for J in S .. E loop
440 Set (Digs (J));
441 end loop;
442 end Set_Digs;
444 ----------------------
445 -- Set_Special_Fill --
446 ----------------------
448 procedure Set_Special_Fill (N : Natural) is
449 F : Natural;
451 begin
452 F := Fore + 1 + Aft - N;
454 if Exp /= 0 then
455 F := F + Exp + 1;
456 end if;
458 for J in 1 .. F loop
459 Set ('*');
460 end loop;
461 end Set_Special_Fill;
463 ---------------
464 -- Set_Zeros --
465 ---------------
467 procedure Set_Zeros (N : Integer) is
468 begin
469 for J in 1 .. N loop
470 Set ('0');
471 end loop;
472 end Set_Zeros;
474 -- Start of processing for Set_Image_Real
476 begin
477 Reset;
478 Scale := 0;
480 -- Deal with invalid values first,
482 if not V'Valid then
484 -- Note that we're taking our chances here, as V might be
485 -- an invalid bit pattern resulting from erroneous execution
486 -- (caused by using uninitialized variables for example).
488 -- No matter what, we'll at least get reasonable behaviour,
489 -- converting to infinity or some other value, or causing an
490 -- exception to be raised is fine.
492 -- If the following test succeeds, then we definitely have
493 -- an infinite value, so we print Inf.
495 if V > Long_Long_Float'Last then
496 Set ('+');
497 Set ('I');
498 Set ('n');
499 Set ('f');
500 Set_Special_Fill (4);
502 -- In all other cases we print NaN
504 elsif V < Long_Long_Float'First then
505 Set ('-');
506 Set ('I');
507 Set ('n');
508 Set ('f');
509 Set_Special_Fill (4);
511 else
512 Set ('N');
513 Set ('a');
514 Set ('N');
515 Set_Special_Fill (3);
516 end if;
518 return;
519 end if;
521 -- Positive values
523 if V > 0.0 then
524 X := V;
525 Sign := '+';
527 -- Negative values
529 elsif V < 0.0 then
530 X := -V;
531 Sign := '-';
533 -- Zero values
535 elsif V = 0.0 then
536 if Long_Long_Float'Signed_Zeros and then Is_Negative (V) then
537 Sign := '-';
538 else
539 Sign := '+';
540 end if;
542 Set_Blanks_And_Sign (Fore - 1);
543 Set ('0');
544 Set ('.');
545 Set_Zeros (NFrac);
547 if Exp /= 0 then
548 Set ('E');
549 Set ('+');
550 Set_Zeros (Natural'Max (1, Exp - 1));
551 end if;
553 return;
555 else
556 -- It should not be possible for a NaN to end up here.
557 -- Either the 'Valid test has failed, or we have some form
558 -- of erroneous execution. Raise Constraint_Error instead of
559 -- attempting to go ahead printing the value.
561 raise Constraint_Error;
562 end if;
564 -- X and Sign are set here, and X is known to be a valid,
565 -- non-zero floating-point number.
567 -- Case of non-zero value with Exp = 0
569 if Exp = 0 then
571 -- First step is to multiply by 10 ** Nfrac to get an integer
572 -- value to be output, an then add 0.5 to round the result.
574 declare
575 NF : Natural := NFrac;
577 begin
578 loop
579 -- If we are larger than Powten (Maxdigs) now, then
580 -- we have too many significant digits, and we have
581 -- not even finished multiplying by NFrac (NF shows
582 -- the number of unaccounted-for digits).
584 if X >= Powten (Maxdigs) then
586 -- In this situation, we only to generate a reasonable
587 -- number of significant digits, and then zeroes after.
588 -- So first we rescale to get:
590 -- 10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
592 -- and then convert the resulting integer
594 Adjust_Scale (Maxdigs);
595 Convert_Integer;
597 -- If that caused rescaling, then add zeros to the end
598 -- of the number to account for this scaling. Also add
599 -- zeroes to account for the undone multiplications
601 for J in 1 .. Scale + NF loop
602 Ndigs := Ndigs + 1;
603 Digs (Ndigs) := '0';
604 end loop;
606 exit;
608 -- If multiplication is complete, then convert the resulting
609 -- integer after rounding (note that X is non-negative)
611 elsif NF = 0 then
612 X := X + 0.5;
613 Convert_Integer;
614 exit;
616 -- Otherwise we can go ahead with the multiplication. If it
617 -- can be done in one step, then do it in one step.
619 elsif NF < Maxpow then
620 X := X * Powten (NF);
621 NF := 0;
623 -- If it cannot be done in one step, then do partial scaling
625 else
626 X := X * Powten (Maxpow);
627 NF := NF - Maxpow;
628 end if;
629 end loop;
630 end;
632 -- If number of available digits is less or equal to NFrac,
633 -- then we need an extra zero before the decimal point.
635 if Ndigs <= NFrac then
636 Set_Blanks_And_Sign (Fore - 1);
637 Set ('0');
638 Set ('.');
639 Set_Zeros (NFrac - Ndigs);
640 Set_Digs (1, Ndigs);
642 -- Normal case with some digits before the decimal point
644 else
645 Set_Blanks_And_Sign (Fore - (Ndigs - NFrac));
646 Set_Digs (1, Ndigs - NFrac);
647 Set ('.');
648 Set_Digs (Ndigs - NFrac + 1, Ndigs);
649 end if;
651 -- Case of non-zero value with non-zero Exp value
653 else
654 -- If NFrac is less than Maxdigs, then all the fraction digits are
655 -- significant, so we can scale the resulting integer accordingly.
657 if NFrac < Maxdigs then
658 Adjust_Scale (NFrac + 1);
659 Convert_Integer;
661 -- Otherwise, we get the maximum number of digits available
663 else
664 Adjust_Scale (Maxdigs);
665 Convert_Integer;
667 for J in 1 .. NFrac - Maxdigs + 1 loop
668 Ndigs := Ndigs + 1;
669 Digs (Ndigs) := '0';
670 Scale := Scale - 1;
671 end loop;
672 end if;
674 Set_Blanks_And_Sign (Fore - 1);
675 Set (Digs (1));
676 Set ('.');
677 Set_Digs (2, Ndigs);
679 -- The exponent is the scaling factor adjusted for the digits
680 -- that we output after the decimal point, since these were
681 -- included in the scaled digits that we output.
683 Expon := Scale + NFrac;
685 Set ('E');
686 Ndigs := 0;
688 if Expon >= 0 then
689 Set ('+');
690 Set_Image_Unsigned (Unsigned (Expon), Digs, Ndigs);
691 else
692 Set ('-');
693 Set_Image_Unsigned (Unsigned (-Expon), Digs, Ndigs);
694 end if;
696 Set_Zeros (Exp - Ndigs - 1);
697 Set_Digs (1, Ndigs);
698 end if;
700 end Set_Image_Real;
702 end System.Img_Real;