OSDN Git Service

* doc/install.texi (xtensa-*-elf): New target.
[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 --                            $Revision: 1.1 $
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 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
33 --                                                                          --
34 ------------------------------------------------------------------------------
35
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;
40
41 package body System.Img_Real is
42
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.
47
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.
52
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.
58
59    Maxdigs : constant :=
60                Natural'Min
61                  (Long_Long_Unsigned'Width - 2, Long_Long_Float'Digits);
62
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.
66
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
75
76    function Is_Negative (V : Long_Long_Float) return Boolean;
77    pragma Import (Intrinsic, Is_Negative);
78
79    --------------------------
80    -- Image_Floating_Point --
81    --------------------------
82
83    function Image_Floating_Point
84      (V    : Long_Long_Float;
85       Digs : Natural)
86       return String
87    is
88       P : Natural := 0;
89       S : String (1 .. Long_Long_Float'Width);
90
91    begin
92       if not Is_Negative (V) then
93          S (1) := ' ';
94          P := 1;
95       end if;
96
97       Set_Image_Real (V, S, P, 1, Digs - 1, 3);
98       return S (1 .. P);
99    end Image_Floating_Point;
100
101    --------------------------------
102    -- Image_Ordinary_Fixed_Point --
103    --------------------------------
104
105    function Image_Ordinary_Fixed_Point
106      (V    : Long_Long_Float;
107       Aft  : Natural)
108       return String
109    is
110       P : Natural := 0;
111       S : String (1 .. Long_Long_Float'Width);
112
113    begin
114       if V >= 0.0 then
115          S (1) := ' ';
116          P := 1;
117       end if;
118
119       Set_Image_Real (V, S, P, 1, Aft, 0);
120       return S (1 .. P);
121    end Image_Ordinary_Fixed_Point;
122
123    --------------------
124    -- Set_Image_Real --
125    --------------------
126
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)
134    is
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.
142
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;
153
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!
158
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.
162
163       Ndigs : Natural;
164       --  Number of digits stored in Digs (and also subscript of last digit)
165
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).
174
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),
179
180       procedure Set (C : Character);
181       --  Sets character C in output buffer
182
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).
188
189       procedure Set_Digs (S, E : Natural);
190       --  Set digits S through E from Digs buffer. No effect if S > E
191
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)
196
197       procedure Set_Zeros (N : Integer);
198       --  Set N zeros, no effect if N is negative
199
200       pragma Inline (Set);
201       pragma Inline (Set_Digs);
202       pragma Inline (Set_Zeros);
203
204       ------------------
205       -- Adjust_Scale --
206       ------------------
207
208       procedure Adjust_Scale (S : Natural) is
209          Lo  : Natural;
210          Hi  : Natural;
211          Mid : Natural;
212          XP  : Long_Long_Float;
213
214       begin
215          --  Cases where scaling up is required
216
217          if X < Powten (S - 1) then
218
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.
221
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;
228
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.
234
235             if Scale < -Maxscaling then
236                raise Constraint_Error;
237             end if;
238
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.
241
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.
247
248             Lo := 1;
249             Hi := Maxpow;
250
251             loop
252                Mid := (Lo + Hi) / 2;
253                XP := X * Powten (Mid);
254
255                if XP < Powten (S - 1) then
256
257                   if Lo >= Hi then
258                      Mid := Mid + 1;
259                      XP := XP * 10.0;
260                      exit;
261
262                   else
263                      Lo := Mid + 1;
264                   end if;
265
266                elsif XP >= Powten (S) then
267
268                   if Lo >= Hi then
269                      Mid := Mid - 1;
270                      XP := XP / 10.0;
271                      exit;
272
273                   else
274                      Hi := Mid - 1;
275                   end if;
276
277                else
278                   exit;
279                end if;
280             end loop;
281
282             X := XP;
283             Scale := Scale - Mid;
284
285          --  Cases where scaling down is required
286
287          elsif X >= Powten (S) then
288
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.
291
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;
298
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.
304
305             if Scale > Maxscaling then
306                raise Constraint_Error;
307             end if;
308
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.
311
312             Lo := 1;
313             Hi := Maxpow;
314
315             loop
316                Mid := (Lo + Hi) / 2;
317                XP := X / Powten (Mid);
318
319                if XP < Powten (S - 1) then
320
321                   if Lo >= Hi then
322                      XP := XP * 10.0;
323                      Mid := Mid - 1;
324                      exit;
325
326                   else
327                      Hi := Mid - 1;
328                   end if;
329
330                elsif XP >= Powten (S) then
331
332                   if Lo >= Hi then
333                      XP := XP / 10.0;
334                      Mid := Mid + 1;
335                      exit;
336
337                   else
338                      Lo := Mid + 1;
339                   end if;
340
341                else
342                   exit;
343                end if;
344             end loop;
345
346             X := XP;
347             Scale := Scale + Mid;
348
349          --  Here we are already scaled right
350
351          else
352             null;
353          end if;
354
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.
358
359          X := X + 0.5;
360
361          if X >= Powten (S) then
362             X := X / 10.0;
363             Scale := Scale + 1;
364          end if;
365
366       end Adjust_Scale;
367
368       ---------------------
369       -- Convert_Integer --
370       ---------------------
371
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.
376
377          if X < Powten (Unsdigs) then
378             Ndigs := 0;
379             Set_Image_Unsigned
380               (Unsigned (Long_Long_Float'Truncation (X)),
381                Digs, Ndigs);
382
383          --  But if we want more digits than fit in Unsigned, we have to use
384          --  the Long_Long_Unsigned routine after all.
385
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;
393
394       ---------
395       -- Set --
396       ---------
397
398       procedure Set (C : Character) is
399       begin
400          P := P + 1;
401          S (P) := C;
402       end Set;
403
404       -------------------------
405       -- Set_Blanks_And_Sign --
406       -------------------------
407
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;
414
415             Set ('-');
416
417          else
418             for J in 1 .. N loop
419                Set (' ');
420             end loop;
421          end if;
422       end Set_Blanks_And_Sign;
423
424       --------------
425       -- Set_Digs --
426       --------------
427
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;
434
435       ----------------------
436       -- Set_Special_Fill --
437       ----------------------
438
439       procedure Set_Special_Fill (N : Natural) is
440          F : Natural;
441
442       begin
443          F := Fore + 1 + Aft - N;
444
445          if Exp /= 0 then
446             F := F + Exp + 1;
447          end if;
448
449          for J in 1 .. F loop
450             Set ('*');
451          end loop;
452       end Set_Special_Fill;
453
454       ---------------
455       -- Set_Zeros --
456       ---------------
457
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;
464
465    --  Start of processing for Set_Image_Real
466
467    begin
468       Reset;
469       Scale := 0;
470
471       --  Positive values
472
473       if V > 0.0 then
474          X := V;
475          Sign := '+';
476
477       --  Negative values
478
479       elsif V < 0.0 then
480          X := -V;
481          Sign := '-';
482
483       --  Zero values
484
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;
491
492          Set_Blanks_And_Sign (Fore - 1);
493          Set ('0');
494          Set ('.');
495          Set_Zeros (NFrac);
496
497          if Exp /= 0 then
498             Set ('E');
499             Set ('+');
500             Set_Zeros (Natural'Max (1, Exp - 1));
501          end if;
502
503          return;
504       end if;
505
506       --  Deal with invalid values
507
508       if not X'Valid then
509
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).
513
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.
517
518          --  If the following test succeeds, then we definitely have
519          --  an infinite value, so we print Inf.
520
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);
527
528          --  In all other cases we print NaN
529
530          else
531             Set ('N');
532             Set ('a');
533             Set ('N');
534             Set_Special_Fill (3);
535          end if;
536
537          return;
538
539       --  Case of non-zero value with Exp = 0
540
541       elsif Exp = 0 then
542
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.
545
546          declare
547             NF : Natural := NFrac;
548
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).
555
556                if X >= Powten (Maxdigs) then
557
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:
561
562                   --    10 ** (Maxdigs - 1) <= X < 10 ** Maxdigs
563
564                   --  and then convert the resulting integer
565
566                   Adjust_Scale (Maxdigs);
567                   Convert_Integer;
568
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
572
573                   for J in 1 .. Scale + NF loop
574                      Ndigs := Ndigs + 1;
575                      Digs (Ndigs) := '0';
576                   end loop;
577
578                   exit;
579
580                --  If multiplication is complete, then convert the resulting
581                --  integer after rounding (note that X is non-negative)
582
583                elsif NF = 0 then
584                   X := X + 0.5;
585                   Convert_Integer;
586                   exit;
587
588                --  Otherwise we can go ahead with the multiplication. If it
589                --  can be done in one step, then do it in one step.
590
591                elsif NF < Maxpow then
592                   X := X * Powten (NF);
593                   NF := 0;
594
595                --  If it cannot be done in one step, then do partial scaling
596
597                else
598                   X := X * Powten (Maxpow);
599                   NF := NF - Maxpow;
600                end if;
601             end loop;
602          end;
603
604          --  If number of available digits is less or equal to NFrac,
605          --  then we need an extra zero before the decimal point.
606
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);
613
614          --  Normal case with some digits before the decimal point
615
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;
622
623       --  Case of non-zero value with non-zero Exp value
624
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.
628
629          if NFrac < Maxdigs then
630             Adjust_Scale (NFrac + 1);
631             Convert_Integer;
632
633          --  Otherwise, we get the maximum number of digits available
634
635          else
636             Adjust_Scale (Maxdigs);
637             Convert_Integer;
638
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;
645
646          Set_Blanks_And_Sign (Fore - 1);
647          Set (Digs (1));
648          Set ('.');
649          Set_Digs (2, Ndigs);
650
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.
654
655          Expon := Scale + NFrac;
656
657          Set ('E');
658          Ndigs := 0;
659
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;
667
668          Set_Zeros (Exp - Ndigs - 1);
669          Set_Digs (1, Ndigs);
670       end if;
671
672    end Set_Image_Real;
673
674 end System.Img_Real;