OSDN Git Service

2007-04-20 Ed Schonberg <schonberg@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / eval_fat.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             E V A L _ F A T                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2006, 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 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Einfo;    use Einfo;
28 with Errout;   use Errout;
29 with Sem_Util; use Sem_Util;
30 with Ttypef;   use Ttypef;
31 with Targparm; use Targparm;
32
33 package body Eval_Fat is
34
35    Radix : constant Int := 2;
36    --  This code is currently only correct for the radix 2 case. We use
37    --  the symbolic value Radix where possible to help in the unlikely
38    --  case of anyone ever having to adjust this code for another value,
39    --  and for documentation purposes.
40
41    --  Another assumption is that the range of the floating-point type
42    --  is symmetric around zero.
43
44    type Radix_Power_Table is array (Int range 1 .. 4) of Int;
45
46    Radix_Powers : constant Radix_Power_Table :=
47                     (Radix ** 1, Radix ** 2, Radix ** 3, Radix ** 4);
48
49    -----------------------
50    -- Local Subprograms --
51    -----------------------
52
53    procedure Decompose
54      (RT       : R;
55       X        : T;
56       Fraction : out T;
57       Exponent : out UI;
58       Mode     : Rounding_Mode := Round);
59    --  Decomposes a non-zero floating-point number into fraction and
60    --  exponent parts. The fraction is in the interval 1.0 / Radix ..
61    --  T'Pred (1.0) and uses Rbase = Radix.
62    --  The result is rounded to a nearest machine number.
63
64    procedure Decompose_Int
65      (RT       : R;
66       X        : T;
67       Fraction : out UI;
68       Exponent : out UI;
69       Mode     : Rounding_Mode);
70    --  This is similar to Decompose, except that the Fraction value returned
71    --  is an integer representing the value Fraction * Scale, where Scale is
72    --  the value (Radix ** Machine_Mantissa (RT)). The value is obtained by
73    --  using biased rounding (halfway cases round away from zero), round to
74    --  even, a floor operation or a ceiling operation depending on the setting
75    --  of Mode (see corresponding descriptions in Urealp).
76
77    function Machine_Emin (RT : R) return Int;
78    --  Return value of the Machine_Emin attribute
79
80    --------------
81    -- Adjacent --
82    --------------
83
84    function Adjacent (RT : R; X, Towards : T) return T is
85    begin
86       if Towards = X then
87          return X;
88       elsif Towards > X then
89          return Succ (RT, X);
90       else
91          return Pred (RT, X);
92       end if;
93    end Adjacent;
94
95    -------------
96    -- Ceiling --
97    -------------
98
99    function Ceiling (RT : R; X : T) return T is
100       XT : constant T := Truncation (RT, X);
101    begin
102       if UR_Is_Negative (X) then
103          return XT;
104       elsif X = XT then
105          return X;
106       else
107          return XT + Ureal_1;
108       end if;
109    end Ceiling;
110
111    -------------
112    -- Compose --
113    -------------
114
115    function Compose (RT : R; Fraction : T; Exponent : UI) return T is
116       Arg_Frac : T;
117       Arg_Exp  : UI;
118    begin
119       if UR_Is_Zero (Fraction) then
120          return Fraction;
121       else
122          Decompose (RT, Fraction, Arg_Frac, Arg_Exp);
123          return Scaling (RT, Arg_Frac, Exponent);
124       end if;
125    end Compose;
126
127    ---------------
128    -- Copy_Sign --
129    ---------------
130
131    function Copy_Sign (RT : R; Value, Sign : T) return T is
132       pragma Warnings (Off, RT);
133       Result : T;
134
135    begin
136       Result := abs Value;
137
138       if UR_Is_Negative (Sign) then
139          return -Result;
140       else
141          return Result;
142       end if;
143    end Copy_Sign;
144
145    ---------------
146    -- Decompose --
147    ---------------
148
149    procedure Decompose
150      (RT       : R;
151       X        : T;
152       Fraction : out T;
153       Exponent : out UI;
154       Mode     : Rounding_Mode := Round)
155    is
156       Int_F : UI;
157
158    begin
159       Decompose_Int (RT, abs X, Int_F, Exponent, Mode);
160
161       Fraction := UR_From_Components
162        (Num      => Int_F,
163         Den      => UI_From_Int (Machine_Mantissa (RT)),
164         Rbase    => Radix,
165         Negative => False);
166
167       if UR_Is_Negative (X) then
168          Fraction := -Fraction;
169       end if;
170
171       return;
172    end Decompose;
173
174    -------------------
175    -- Decompose_Int --
176    -------------------
177
178    --  This procedure should be modified with care, as there are many
179    --  non-obvious details that may cause problems that are hard to
180    --  detect. The cases of positive and negative zeroes are also
181    --  special and should be verified separately.
182
183    procedure Decompose_Int
184      (RT       : R;
185       X        : T;
186       Fraction : out UI;
187       Exponent : out UI;
188       Mode     : Rounding_Mode)
189    is
190       Base : Int := Rbase (X);
191       N    : UI  := abs Numerator (X);
192       D    : UI  := Denominator (X);
193
194       N_Times_Radix : UI;
195
196       Even : Boolean;
197       --  True iff Fraction is even
198
199       Most_Significant_Digit : constant UI :=
200                                  Radix ** (Machine_Mantissa (RT) - 1);
201
202       Uintp_Mark : Uintp.Save_Mark;
203       --  The code is divided into blocks that systematically release
204       --  intermediate values (this routine generates lots of junk!)
205
206    begin
207       Calculate_D_And_Exponent_1 : begin
208          Uintp_Mark := Mark;
209          Exponent := Uint_0;
210
211          --  In cases where Base > 1, the actual denominator is
212          --  Base**D. For cases where Base is a power of Radix, use
213          --  the value 1 for the Denominator and adjust the exponent.
214
215          --  Note: Exponent has different sign from D, because D is a divisor
216
217          for Power in 1 .. Radix_Powers'Last loop
218             if Base = Radix_Powers (Power) then
219                Exponent := -D * Power;
220                Base := 0;
221                D := Uint_1;
222                exit;
223             end if;
224          end loop;
225
226          Release_And_Save (Uintp_Mark, D, Exponent);
227       end Calculate_D_And_Exponent_1;
228
229       if Base > 0 then
230          Calculate_Exponent : begin
231             Uintp_Mark := Mark;
232
233             --  For bases that are a multiple of the Radix, divide
234             --  the base by Radix and adjust the Exponent. This will
235             --  help because D will be much smaller and faster to process.
236
237             --  This occurs for decimal bases on a machine with binary
238             --  floating-point for example. When calculating 1E40,
239             --  with Radix = 2, N will be 93 bits instead of 133.
240
241             --        N            E
242             --      ------  * Radix
243             --           D
244             --       Base
245
246             --                  N                        E
247             --    =  --------------------------  *  Radix
248             --                     D        D
249             --         (Base/Radix)  * Radix
250
251             --             N                  E-D
252             --    =  ---------------  *  Radix
253             --                    D
254             --        (Base/Radix)
255
256             --  This code is commented out, because it causes numerous
257             --  failures in the regression suite. To be studied ???
258
259             while False and then Base > 0 and then Base mod Radix = 0 loop
260                Base := Base / Radix;
261                Exponent := Exponent + D;
262             end loop;
263
264             Release_And_Save (Uintp_Mark, Exponent);
265          end Calculate_Exponent;
266
267          --  For remaining bases we must actually compute
268          --  the exponentiation.
269
270          --  Because the exponentiation can be negative, and D must
271          --  be integer, the numerator is corrected instead.
272
273          Calculate_N_And_D : begin
274             Uintp_Mark := Mark;
275
276             if D < 0 then
277                N := N * Base ** (-D);
278                D := Uint_1;
279             else
280                D := Base ** D;
281             end if;
282
283             Release_And_Save (Uintp_Mark, N, D);
284          end Calculate_N_And_D;
285
286          Base := 0;
287       end if;
288
289       --  Now scale N and D so that N / D is a value in the
290       --  interval [1.0 / Radix, 1.0) and adjust Exponent accordingly,
291       --  so the value N / D * Radix ** Exponent remains unchanged.
292
293       --  Step 1 - Adjust N so N / D >= 1 / Radix, or N = 0
294
295       --  N and D are positive, so N / D >= 1 / Radix implies N * Radix >= D.
296       --  This scaling is not possible for N is Uint_0 as there
297       --  is no way to scale Uint_0 so the first digit is non-zero.
298
299       Calculate_N_And_Exponent : begin
300          Uintp_Mark := Mark;
301
302          N_Times_Radix := N * Radix;
303
304          if N /= Uint_0 then
305             while not (N_Times_Radix >= D) loop
306                N := N_Times_Radix;
307                Exponent := Exponent - 1;
308
309                N_Times_Radix := N * Radix;
310             end loop;
311          end if;
312
313          Release_And_Save (Uintp_Mark, N, Exponent);
314       end Calculate_N_And_Exponent;
315
316       --  Step 2 - Adjust D so N / D < 1
317
318       --  Scale up D so N / D < 1, so N < D
319
320       Calculate_D_And_Exponent_2 : begin
321          Uintp_Mark := Mark;
322
323          while not (N < D) loop
324
325             --  As N / D >= 1, N / (D * Radix) will be at least 1 / Radix,
326             --  so the result of Step 1 stays valid
327
328             D := D * Radix;
329             Exponent := Exponent + 1;
330          end loop;
331
332          Release_And_Save (Uintp_Mark, D, Exponent);
333       end Calculate_D_And_Exponent_2;
334
335       --  Here the value N / D is in the range [1.0 / Radix .. 1.0)
336
337       --  Now find the fraction by doing a very simple-minded
338       --  division until enough digits have been computed.
339
340       --  This division works for all radices, but is only efficient for
341       --  a binary radix. It is just like a manual division algorithm,
342       --  but instead of moving the denominator one digit right, we move
343       --  the numerator one digit left so the numerator and denominator
344       --  remain integral.
345
346       Fraction := Uint_0;
347       Even := True;
348
349       Calculate_Fraction_And_N : begin
350          Uintp_Mark := Mark;
351
352          loop
353             while N >= D loop
354                N := N - D;
355                Fraction := Fraction + 1;
356                Even := not Even;
357             end loop;
358
359             --  Stop when the result is in [1.0 / Radix, 1.0)
360
361             exit when Fraction >= Most_Significant_Digit;
362
363             N := N * Radix;
364             Fraction := Fraction * Radix;
365             Even := True;
366          end loop;
367
368          Release_And_Save (Uintp_Mark, Fraction, N);
369       end Calculate_Fraction_And_N;
370
371       Calculate_Fraction_And_Exponent : begin
372          Uintp_Mark := Mark;
373
374          --  Determine correct rounding based on the remainder which is in
375          --  N and the divisor D. The rounding is performed on the absolute
376          --  value of X, so Ceiling and Floor need to check for the sign of
377          --  X explicitly.
378
379          case Mode is
380             when Round_Even =>
381
382                --  This rounding mode should not be used for static
383                --  expressions, but only for compile-time evaluation
384                --  of non-static expressions.
385
386                if (Even and then N * 2 > D)
387                      or else
388                   (not Even and then N * 2 >= D)
389                then
390                   Fraction := Fraction + 1;
391                end if;
392
393             when Round   =>
394
395                --  Do not round to even as is done with IEEE arithmetic,
396                --  but instead round away from zero when the result is
397                --  exactly between two machine numbers. See RM 4.9(38).
398
399                if N * 2 >= D then
400                   Fraction := Fraction + 1;
401                end if;
402
403             when Ceiling =>
404                if N > Uint_0 and then not UR_Is_Negative (X) then
405                   Fraction := Fraction + 1;
406                end if;
407
408             when Floor   =>
409                if N > Uint_0 and then UR_Is_Negative (X) then
410                   Fraction := Fraction + 1;
411                end if;
412          end case;
413
414          --  The result must be normalized to [1.0/Radix, 1.0),
415          --  so adjust if the result is 1.0 because of rounding.
416
417          if Fraction = Most_Significant_Digit * Radix then
418             Fraction := Most_Significant_Digit;
419             Exponent := Exponent + 1;
420          end if;
421
422          --  Put back sign after applying the rounding
423
424          if UR_Is_Negative (X) then
425             Fraction := -Fraction;
426          end if;
427
428          Release_And_Save (Uintp_Mark, Fraction, Exponent);
429       end Calculate_Fraction_And_Exponent;
430    end Decompose_Int;
431
432    --------------
433    -- Exponent --
434    --------------
435
436    function Exponent (RT : R; X : T) return UI is
437       X_Frac : UI;
438       X_Exp  : UI;
439    begin
440       if UR_Is_Zero (X) then
441          return Uint_0;
442       else
443          Decompose_Int (RT, X, X_Frac, X_Exp, Round_Even);
444          return X_Exp;
445       end if;
446    end Exponent;
447
448    -----------
449    -- Floor --
450    -----------
451
452    function Floor (RT : R; X : T) return T is
453       XT : constant T := Truncation (RT, X);
454
455    begin
456       if UR_Is_Positive (X) then
457          return XT;
458
459       elsif XT = X then
460          return X;
461
462       else
463          return XT - Ureal_1;
464       end if;
465    end Floor;
466
467    --------------
468    -- Fraction --
469    --------------
470
471    function Fraction (RT : R; X : T) return T is
472       X_Frac : T;
473       X_Exp  : UI;
474    begin
475       if UR_Is_Zero (X) then
476          return X;
477       else
478          Decompose (RT, X, X_Frac, X_Exp);
479          return X_Frac;
480       end if;
481    end Fraction;
482
483    ------------------
484    -- Leading_Part --
485    ------------------
486
487    function Leading_Part (RT : R; X : T; Radix_Digits : UI) return T is
488       RD : constant UI := UI_Min (Radix_Digits, Machine_Mantissa (RT));
489       L  : UI;
490       Y  : T;
491    begin
492       L := Exponent (RT, X) - RD;
493       Y := UR_From_Uint (UR_Trunc (Scaling (RT, X, -L)));
494       return Scaling (RT, Y, L);
495    end Leading_Part;
496
497    -------------
498    -- Machine --
499    -------------
500
501    function Machine
502      (RT    : R;
503       X     : T;
504       Mode  : Rounding_Mode;
505       Enode : Node_Id) return T
506    is
507       X_Frac : T;
508       X_Exp  : UI;
509       Emin   : constant UI := UI_From_Int (Machine_Emin (RT));
510
511    begin
512       if UR_Is_Zero (X) then
513          return X;
514
515       else
516          Decompose (RT, X, X_Frac, X_Exp, Mode);
517
518          --  Case of denormalized number or (gradual) underflow
519
520          --  A denormalized number is one with the minimum exponent Emin, but
521          --  that breaks the assumption that the first digit of the mantissa
522          --  is a one. This allows the first non-zero digit to be in any
523          --  of the remaining Mant - 1 spots. The gap between subsequent
524          --  denormalized numbers is the same as for the smallest normalized
525          --  numbers. However, the number of significant digits left decreases
526          --  as a result of the mantissa now having leading seros.
527
528          if X_Exp < Emin then
529             declare
530                Emin_Den : constant UI :=
531                             UI_From_Int
532                               (Machine_Emin (RT) - Machine_Mantissa (RT) + 1);
533             begin
534                if X_Exp < Emin_Den or not Denorm_On_Target then
535                   if UR_Is_Negative (X) then
536                      Error_Msg_N
537                        ("floating-point value underflows to -0.0?", Enode);
538                      return Ureal_M_0;
539
540                   else
541                      Error_Msg_N
542                        ("floating-point value underflows to 0.0?", Enode);
543                      return Ureal_0;
544                   end if;
545
546                elsif Denorm_On_Target then
547
548                   --  Emin - Mant <= X_Exp < Emin, so result is denormal.
549                   --  Handle gradual underflow by first computing the
550                   --  number of significant bits still available for the
551                   --  mantissa and then truncating the fraction to this
552                   --  number of bits.
553
554                   --  If this value is different from the original
555                   --  fraction, precision is lost due to gradual underflow.
556
557                   --  We probably should round here and prevent double
558                   --  rounding as a result of first rounding to a model
559                   --  number and then to a machine number. However, this
560                   --  is an extremely rare case that is not worth the extra
561                   --  complexity. In any case, a warning is issued in cases
562                   --  where gradual underflow occurs.
563
564                   declare
565                      Denorm_Sig_Bits : constant UI := X_Exp - Emin_Den + 1;
566
567                      X_Frac_Denorm   : constant T := UR_From_Components
568                        (UR_Trunc (Scaling (RT, abs X_Frac, Denorm_Sig_Bits)),
569                         Denorm_Sig_Bits,
570                         Radix,
571                         UR_Is_Negative (X));
572
573                   begin
574                      if X_Frac_Denorm /= X_Frac then
575                         Error_Msg_N
576                           ("gradual underflow causes loss of precision?",
577                            Enode);
578                         X_Frac := X_Frac_Denorm;
579                      end if;
580                   end;
581                end if;
582             end;
583          end if;
584
585          return Scaling (RT, X_Frac, X_Exp);
586       end if;
587    end Machine;
588
589    ------------------
590    -- Machine_Emin --
591    ------------------
592
593    function Machine_Emin (RT : R) return Int is
594       Digs : constant UI := Digits_Value (RT);
595       Emin : Int;
596
597    begin
598       if Vax_Float (RT) then
599          if Digs = VAXFF_Digits then
600             Emin := VAXFF_Machine_Emin;
601
602          elsif Digs = VAXDF_Digits then
603             Emin := VAXDF_Machine_Emin;
604
605          else
606             pragma Assert (Digs = VAXGF_Digits);
607             Emin := VAXGF_Machine_Emin;
608          end if;
609
610       elsif Is_AAMP_Float (RT) then
611          if Digs = AAMPS_Digits then
612             Emin := AAMPS_Machine_Emin;
613
614          else
615             pragma Assert (Digs = AAMPL_Digits);
616             Emin := AAMPL_Machine_Emin;
617          end if;
618
619       else
620          if Digs = IEEES_Digits then
621             Emin := IEEES_Machine_Emin;
622
623          elsif Digs = IEEEL_Digits then
624             Emin := IEEEL_Machine_Emin;
625
626          else
627             pragma Assert (Digs = IEEEX_Digits);
628             Emin := IEEEX_Machine_Emin;
629          end if;
630       end if;
631
632       return Emin;
633    end Machine_Emin;
634
635    ----------------------
636    -- Machine_Mantissa --
637    ----------------------
638
639    function Machine_Mantissa (RT : R) return Nat is
640       Digs : constant UI := Digits_Value (RT);
641       Mant : Nat;
642
643    begin
644       if Vax_Float (RT) then
645          if Digs = VAXFF_Digits then
646             Mant := VAXFF_Machine_Mantissa;
647
648          elsif Digs = VAXDF_Digits then
649             Mant := VAXDF_Machine_Mantissa;
650
651          else
652             pragma Assert (Digs = VAXGF_Digits);
653             Mant := VAXGF_Machine_Mantissa;
654          end if;
655
656       elsif Is_AAMP_Float (RT) then
657          if Digs = AAMPS_Digits then
658             Mant := AAMPS_Machine_Mantissa;
659
660          else
661             pragma Assert (Digs = AAMPL_Digits);
662             Mant := AAMPL_Machine_Mantissa;
663          end if;
664
665       else
666          if Digs = IEEES_Digits then
667             Mant := IEEES_Machine_Mantissa;
668
669          elsif Digs = IEEEL_Digits then
670             Mant := IEEEL_Machine_Mantissa;
671
672          else
673             pragma Assert (Digs = IEEEX_Digits);
674             Mant := IEEEX_Machine_Mantissa;
675          end if;
676       end if;
677
678       return Mant;
679    end Machine_Mantissa;
680
681    -------------------
682    -- Machine_Radix --
683    -------------------
684
685    function Machine_Radix (RT : R) return Nat is
686       pragma Warnings (Off, RT);
687    begin
688       return Radix;
689    end Machine_Radix;
690
691    -----------
692    -- Model --
693    -----------
694
695    function Model (RT : R; X : T) return T is
696       X_Frac : T;
697       X_Exp  : UI;
698    begin
699       Decompose (RT, X, X_Frac, X_Exp);
700       return Compose (RT, X_Frac, X_Exp);
701    end Model;
702
703    ----------
704    -- Pred --
705    ----------
706
707    function Pred (RT : R; X : T) return T is
708    begin
709       return -Succ (RT, -X);
710    end Pred;
711
712    ---------------
713    -- Remainder --
714    ---------------
715
716    function Remainder (RT : R; X, Y : T) return T is
717       A        : T;
718       B        : T;
719       Arg      : T;
720       P        : T;
721       Arg_Frac : T;
722       P_Frac   : T;
723       Sign_X   : T;
724       IEEE_Rem : T;
725       Arg_Exp  : UI;
726       P_Exp    : UI;
727       K        : UI;
728       P_Even   : Boolean;
729
730    begin
731       if UR_Is_Positive (X) then
732          Sign_X :=  Ureal_1;
733       else
734          Sign_X := -Ureal_1;
735       end if;
736
737       Arg := abs X;
738       P   := abs Y;
739
740       if Arg < P then
741          P_Even := True;
742          IEEE_Rem := Arg;
743          P_Exp := Exponent (RT, P);
744
745       else
746          --  ??? what about zero cases?
747          Decompose (RT, Arg, Arg_Frac, Arg_Exp);
748          Decompose (RT, P,   P_Frac,   P_Exp);
749
750          P := Compose (RT, P_Frac, Arg_Exp);
751          K := Arg_Exp - P_Exp;
752          P_Even := True;
753          IEEE_Rem := Arg;
754
755          for Cnt in reverse 0 .. UI_To_Int (K) loop
756             if IEEE_Rem >= P then
757                P_Even := False;
758                IEEE_Rem := IEEE_Rem - P;
759             else
760                P_Even := True;
761             end if;
762
763             P := P * Ureal_Half;
764          end loop;
765       end if;
766
767       --  That completes the calculation of modulus remainder. The final step
768       --  is get the IEEE remainder. Here we compare Rem with (abs Y) / 2.
769
770       if P_Exp >= 0 then
771          A := IEEE_Rem;
772          B := abs Y * Ureal_Half;
773
774       else
775          A := IEEE_Rem * Ureal_2;
776          B := abs Y;
777       end if;
778
779       if A > B or else (A = B and then not P_Even) then
780          IEEE_Rem := IEEE_Rem - abs Y;
781       end if;
782
783       return Sign_X * IEEE_Rem;
784    end Remainder;
785
786    --------------
787    -- Rounding --
788    --------------
789
790    function Rounding (RT : R; X : T) return T is
791       Result : T;
792       Tail   : T;
793
794    begin
795       Result := Truncation (RT, abs X);
796       Tail   := abs X - Result;
797
798       if Tail >= Ureal_Half  then
799          Result := Result + Ureal_1;
800       end if;
801
802       if UR_Is_Negative (X) then
803          return -Result;
804       else
805          return Result;
806       end if;
807    end Rounding;
808
809    -------------
810    -- Scaling --
811    -------------
812
813    function Scaling (RT : R; X : T; Adjustment : UI) return T is
814       pragma Warnings (Off, RT);
815
816    begin
817       if Rbase (X) = Radix then
818          return UR_From_Components
819            (Num      => Numerator (X),
820             Den      => Denominator (X) - Adjustment,
821             Rbase    => Radix,
822             Negative => UR_Is_Negative (X));
823
824       elsif Adjustment >= 0 then
825          return X * Radix ** Adjustment;
826       else
827          return X / Radix ** (-Adjustment);
828       end if;
829    end Scaling;
830
831    ----------
832    -- Succ --
833    ----------
834
835    function Succ (RT : R; X : T) return T is
836       Emin     : constant UI := UI_From_Int (Machine_Emin (RT));
837       Mantissa : constant UI := UI_From_Int (Machine_Mantissa (RT));
838       Exp      : UI := UI_Max (Emin, Exponent (RT, X));
839       Frac     : T;
840       New_Frac : T;
841
842    begin
843       if UR_Is_Zero (X) then
844          Exp := Emin;
845       end if;
846
847       --  Set exponent such that the radix point will be directly
848       --  following the mantissa after scaling
849
850       if Denorm_On_Target or Exp /= Emin then
851          Exp := Exp - Mantissa;
852       else
853          Exp := Exp - 1;
854       end if;
855
856       Frac := Scaling (RT, X, -Exp);
857       New_Frac := Ceiling (RT, Frac);
858
859       if New_Frac = Frac then
860          if New_Frac = Scaling (RT, -Ureal_1, Mantissa - 1) then
861             New_Frac := New_Frac + Scaling (RT, Ureal_1, Uint_Minus_1);
862          else
863             New_Frac := New_Frac + Ureal_1;
864          end if;
865       end if;
866
867       return Scaling (RT, New_Frac, Exp);
868    end Succ;
869
870    ----------------
871    -- Truncation --
872    ----------------
873
874    function Truncation (RT : R; X : T) return T is
875       pragma Warnings (Off, RT);
876    begin
877       return UR_From_Uint (UR_Trunc (X));
878    end Truncation;
879
880    -----------------------
881    -- Unbiased_Rounding --
882    -----------------------
883
884    function Unbiased_Rounding (RT : R; X : T) return T is
885       Abs_X  : constant T := abs X;
886       Result : T;
887       Tail   : T;
888
889    begin
890       Result := Truncation (RT, Abs_X);
891       Tail   := Abs_X - Result;
892
893       if Tail > Ureal_Half  then
894          Result := Result + Ureal_1;
895
896       elsif Tail = Ureal_Half then
897          Result := Ureal_2 *
898                      Truncation (RT, (Result / Ureal_2) + Ureal_Half);
899       end if;
900
901       if UR_Is_Negative (X) then
902          return -Result;
903       elsif UR_Is_Positive (X) then
904          return Result;
905
906       --  For zero case, make sure sign of zero is preserved
907
908       else
909          return X;
910       end if;
911    end Unbiased_Rounding;
912
913 end Eval_Fat;