OSDN Git Service

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