OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [urealp.adb] - Blame information for rev 706

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                               U R E A L P                                --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2011, 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 3,  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.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNAT was originally developed  by the GNAT team at  New York University. --
28
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with Alloc;
33
with Output;  use Output;
34
with Table;
35
with Tree_IO; use Tree_IO;
36
 
37
package body Urealp is
38
 
39
   Ureal_First_Entry : constant Ureal := Ureal'Succ (No_Ureal);
40
   --  First subscript allocated in Ureal table (note that we can't just
41
   --  add 1 to No_Ureal, since "+" means something different for Ureals!
42
 
43
   type Ureal_Entry is record
44
      Num  : Uint;
45
      --  Numerator (always non-negative)
46
 
47
      Den : Uint;
48
      --  Denominator (always non-zero, always positive if base is zero)
49
 
50
      Rbase : Nat;
51
      --  Base value. If Rbase is zero, then the value is simply Num / Den.
52
      --  If Rbase is non-zero, then the value is Num / (Rbase ** Den)
53
 
54
      Negative : Boolean;
55
      --  Flag set if value is negative
56
   end record;
57
 
58
   --  The following representation clause ensures that the above record
59
   --  has no holes. We do this so that when instances of this record are
60
   --  written by Tree_Gen, we do not write uninitialized values to the file.
61
 
62
   for Ureal_Entry use record
63
      Num      at  0 range 0 .. 31;
64
      Den      at  4 range 0 .. 31;
65
      Rbase    at  8 range 0 .. 31;
66
      Negative at 12 range 0 .. 31;
67
   end record;
68
 
69
   for Ureal_Entry'Size use 16 * 8;
70
   --  This ensures that we did not leave out any fields
71
 
72
   package Ureals is new Table.Table (
73
     Table_Component_Type => Ureal_Entry,
74
     Table_Index_Type     => Ureal'Base,
75
     Table_Low_Bound      => Ureal_First_Entry,
76
     Table_Initial        => Alloc.Ureals_Initial,
77
     Table_Increment      => Alloc.Ureals_Increment,
78
     Table_Name           => "Ureals");
79
 
80
   --  The following universal reals are the values returned by the constant
81
   --  functions. They are initialized by the initialization procedure.
82
 
83
   UR_0       : Ureal;
84
   UR_M_0     : Ureal;
85
   UR_Tenth   : Ureal;
86
   UR_Half    : Ureal;
87
   UR_1       : Ureal;
88
   UR_2       : Ureal;
89
   UR_10      : Ureal;
90
   UR_10_36   : Ureal;
91
   UR_M_10_36 : Ureal;
92
   UR_100     : Ureal;
93
   UR_2_128   : Ureal;
94
   UR_2_80    : Ureal;
95
   UR_2_M_128 : Ureal;
96
   UR_2_M_80  : Ureal;
97
 
98
   Num_Ureal_Constants : constant := 10;
99
   --  This is used for an assertion check in Tree_Read and Tree_Write to
100
   --  help remember to add values to these routines when we add to the list.
101
 
102
   Normalized_Real : Ureal := No_Ureal;
103
   --  Used to memoize Norm_Num and Norm_Den, if either of these functions
104
   --  is called, this value is set and Normalized_Entry contains the result
105
   --  of the normalization. On subsequent calls, this is used to avoid the
106
   --  call to Normalize if it has already been made.
107
 
108
   Normalized_Entry : Ureal_Entry;
109
   --  Entry built by most recent call to Normalize
110
 
111
   -----------------------
112
   -- Local Subprograms --
113
   -----------------------
114
 
115
   function Decimal_Exponent_Hi (V : Ureal) return Int;
116
   --  Returns an estimate of the exponent of Val represented as a normalized
117
   --  decimal number (non-zero digit before decimal point), The estimate is
118
   --  either correct, or high, but never low. The accuracy of the estimate
119
   --  affects only the efficiency of the comparison routines.
120
 
121
   function Decimal_Exponent_Lo (V : Ureal) return Int;
122
   --  Returns an estimate of the exponent of Val represented as a normalized
123
   --  decimal number (non-zero digit before decimal point), The estimate is
124
   --  either correct, or low, but never high. The accuracy of the estimate
125
   --  affects only the efficiency of the comparison routines.
126
 
127
   function Equivalent_Decimal_Exponent (U : Ureal_Entry) return Int;
128
   --  U is a Ureal entry for which the base value is non-zero, the value
129
   --  returned is the equivalent decimal exponent value, i.e. the value of
130
   --  Den, adjusted as though the base were base 10. The value is rounded
131
   --  toward zero (truncated), and so its value can be off by one.
132
 
133
   function Is_Integer (Num, Den : Uint) return Boolean;
134
   --  Return true if the real quotient of Num / Den is an integer value
135
 
136
   function Normalize (Val : Ureal_Entry) return Ureal_Entry;
137
   --  Normalizes the Ureal_Entry by reducing it to lowest terms (with a base
138
   --  value of 0).
139
 
140
   function Same (U1, U2 : Ureal) return Boolean;
141
   pragma Inline (Same);
142
   --  Determines if U1 and U2 are the same Ureal. Note that we cannot use
143
   --  the equals operator for this test, since that tests for equality, not
144
   --  identity.
145
 
146
   function Store_Ureal (Val : Ureal_Entry) return Ureal;
147
   --  This store a new entry in the universal reals table and return its index
148
   --  in the table.
149
 
150
   function Store_Ureal_Normalized (Val : Ureal_Entry) return Ureal;
151
   pragma Inline (Store_Ureal_Normalized);
152
   --  Like Store_Ureal, but normalizes its operand first
153
 
154
   -------------------------
155
   -- Decimal_Exponent_Hi --
156
   -------------------------
157
 
158
   function Decimal_Exponent_Hi (V : Ureal) return Int is
159
      Val : constant Ureal_Entry := Ureals.Table (V);
160
 
161
   begin
162
      --  Zero always returns zero
163
 
164
      if UR_Is_Zero (V) then
165
         return 0;
166
 
167
      --  For numbers in rational form, get the maximum number of digits in the
168
      --  numerator and the minimum number of digits in the denominator, and
169
      --  subtract. For example:
170
 
171
      --     1000 / 99 = 1.010E+1
172
      --     9999 / 10 = 9.999E+2
173
 
174
      --  This estimate may of course be high, but that is acceptable
175
 
176
      elsif Val.Rbase = 0 then
177
         return UI_Decimal_Digits_Hi (Val.Num) -
178
                UI_Decimal_Digits_Lo (Val.Den);
179
 
180
      --  For based numbers, just subtract the decimal exponent from the
181
      --  high estimate of the number of digits in the numerator and add
182
      --  one to accommodate possible round off errors for non-decimal
183
      --  bases. For example:
184
 
185
      --     1_500_000 / 10**4 = 1.50E-2
186
 
187
      else -- Val.Rbase /= 0
188
         return UI_Decimal_Digits_Hi (Val.Num) -
189
                Equivalent_Decimal_Exponent (Val) + 1;
190
      end if;
191
   end Decimal_Exponent_Hi;
192
 
193
   -------------------------
194
   -- Decimal_Exponent_Lo --
195
   -------------------------
196
 
197
   function Decimal_Exponent_Lo (V : Ureal) return Int is
198
      Val : constant Ureal_Entry := Ureals.Table (V);
199
 
200
   begin
201
      --  Zero always returns zero
202
 
203
      if UR_Is_Zero (V) then
204
         return 0;
205
 
206
      --  For numbers in rational form, get min digits in numerator, max digits
207
      --  in denominator, and subtract and subtract one more for possible loss
208
      --  during the division. For example:
209
 
210
      --     1000 / 99 = 1.010E+1
211
      --     9999 / 10 = 9.999E+2
212
 
213
      --  This estimate may of course be low, but that is acceptable
214
 
215
      elsif Val.Rbase = 0 then
216
         return UI_Decimal_Digits_Lo (Val.Num) -
217
                UI_Decimal_Digits_Hi (Val.Den) - 1;
218
 
219
      --  For based numbers, just subtract the decimal exponent from the
220
      --  low estimate of the number of digits in the numerator and subtract
221
      --  one to accommodate possible round off errors for non-decimal
222
      --  bases. For example:
223
 
224
      --     1_500_000 / 10**4 = 1.50E-2
225
 
226
      else -- Val.Rbase /= 0
227
         return UI_Decimal_Digits_Lo (Val.Num) -
228
                Equivalent_Decimal_Exponent (Val) - 1;
229
      end if;
230
   end Decimal_Exponent_Lo;
231
 
232
   -----------------
233
   -- Denominator --
234
   -----------------
235
 
236
   function Denominator (Real : Ureal) return Uint is
237
   begin
238
      return Ureals.Table (Real).Den;
239
   end Denominator;
240
 
241
   ---------------------------------
242
   -- Equivalent_Decimal_Exponent --
243
   ---------------------------------
244
 
245
   function Equivalent_Decimal_Exponent (U : Ureal_Entry) return Int is
246
 
247
      type Ratio is record
248
         Num : Nat;
249
         Den : Nat;
250
      end record;
251
 
252
      --  The following table is a table of logs to the base 10. All values
253
      --  have at least 15 digits of precision, and do not exceed the true
254
      --  value. To avoid the use of floating point, and as a result potential
255
      --  target dependency, each entry is represented as a fraction of two
256
      --  integers.
257
 
258
      Logs : constant array (Nat range 1 .. 16) of Ratio :=
259
        (1 => (Num =>           0, Den =>            1),  -- 0
260
         2 => (Num =>  15_392_313, Den =>   51_132_157),  -- 0.301029995663981
261
         3 => (Num => 731_111_920, Den => 1532_339_867),  -- 0.477121254719662
262
         4 => (Num =>  30_784_626, Den =>   51_132_157),  -- 0.602059991327962
263
         5 => (Num => 111_488_153, Den =>  159_503_487),  -- 0.698970004336018
264
         6 => (Num =>  84_253_929, Den =>  108_274_489),  -- 0.778151250383643
265
         7 => (Num =>  35_275_468, Den =>   41_741_273),  -- 0.845098040014256
266
         8 => (Num =>  46_176_939, Den =>   51_132_157),  -- 0.903089986991943
267
         9 => (Num => 417_620_173, Den =>  437_645_744),  -- 0.954242509439324
268
        10 => (Num =>           1, Den =>            1),  -- 1.000000000000000
269
        11 => (Num => 136_507_510, Den =>  131_081_687),  -- 1.041392685158225
270
        12 => (Num =>  26_797_783, Den =>   24_831_587),  -- 1.079181246047624
271
        13 => (Num =>  73_333_297, Den =>   65_832_160),  -- 1.113943352306836
272
        14 => (Num => 102_941_258, Den =>   89_816_543),  -- 1.146128035678238
273
        15 => (Num =>  53_385_559, Den =>   45_392_361),  -- 1.176091259055681
274
        16 => (Num =>  78_897_839, Den =>   65_523_237)); -- 1.204119982655924
275
 
276
      function Scale (X : Int; R : Ratio) return Int;
277
      --  Compute the value of X scaled by R
278
 
279
      -----------
280
      -- Scale --
281
      -----------
282
 
283
      function Scale (X : Int; R : Ratio) return Int is
284
         type Wide_Int is range -2**63 .. 2**63 - 1;
285
 
286
      begin
287
         return Int (Wide_Int (X) * Wide_Int (R.Num) / Wide_Int (R.Den));
288
      end Scale;
289
 
290
   begin
291
      pragma Assert (U.Rbase /= 0);
292
      return Scale (UI_To_Int (U.Den), Logs (U.Rbase));
293
   end Equivalent_Decimal_Exponent;
294
 
295
   ----------------
296
   -- Initialize --
297
   ----------------
298
 
299
   procedure Initialize is
300
   begin
301
      Ureals.Init;
302
      UR_0       := UR_From_Components (Uint_0, Uint_1,         0, False);
303
      UR_M_0     := UR_From_Components (Uint_0, Uint_1,         0, True);
304
      UR_Half    := UR_From_Components (Uint_1, Uint_1,         2, False);
305
      UR_Tenth   := UR_From_Components (Uint_1, Uint_1,        10, False);
306
      UR_1       := UR_From_Components (Uint_1, Uint_1,         0, False);
307
      UR_2       := UR_From_Components (Uint_1, Uint_Minus_1,   2, False);
308
      UR_10      := UR_From_Components (Uint_1, Uint_Minus_1,  10, False);
309
      UR_10_36   := UR_From_Components (Uint_1, Uint_Minus_36, 10, False);
310
      UR_M_10_36 := UR_From_Components (Uint_1, Uint_Minus_36, 10, True);
311
      UR_100     := UR_From_Components (Uint_1, Uint_Minus_2,  10, False);
312
      UR_2_128   := UR_From_Components (Uint_1, Uint_Minus_128, 2, False);
313
      UR_2_M_128 := UR_From_Components (Uint_1, Uint_128,       2, False);
314
      UR_2_80    := UR_From_Components (Uint_1, Uint_Minus_80,  2, False);
315
      UR_2_M_80  := UR_From_Components (Uint_1, Uint_80,        2, False);
316
   end Initialize;
317
 
318
   ----------------
319
   -- Is_Integer --
320
   ----------------
321
 
322
   function Is_Integer (Num, Den : Uint) return Boolean is
323
   begin
324
      return (Num / Den) * Den = Num;
325
   end Is_Integer;
326
 
327
   ----------
328
   -- Mark --
329
   ----------
330
 
331
   function Mark return Save_Mark is
332
   begin
333
      return Save_Mark (Ureals.Last);
334
   end Mark;
335
 
336
   --------------
337
   -- Norm_Den --
338
   --------------
339
 
340
   function Norm_Den (Real : Ureal) return Uint is
341
   begin
342
      if not Same (Real, Normalized_Real) then
343
         Normalized_Real  := Real;
344
         Normalized_Entry := Normalize (Ureals.Table (Real));
345
      end if;
346
 
347
      return Normalized_Entry.Den;
348
   end Norm_Den;
349
 
350
   --------------
351
   -- Norm_Num --
352
   --------------
353
 
354
   function Norm_Num (Real : Ureal) return Uint is
355
   begin
356
      if not Same (Real, Normalized_Real) then
357
         Normalized_Real  := Real;
358
         Normalized_Entry := Normalize (Ureals.Table (Real));
359
      end if;
360
 
361
      return Normalized_Entry.Num;
362
   end Norm_Num;
363
 
364
   ---------------
365
   -- Normalize --
366
   ---------------
367
 
368
   function Normalize (Val : Ureal_Entry) return Ureal_Entry is
369
      J   : Uint;
370
      K   : Uint;
371
      Tmp : Uint;
372
      Num : Uint;
373
      Den : Uint;
374
      M   : constant Uintp.Save_Mark := Uintp.Mark;
375
 
376
   begin
377
      --  Start by setting J to the greatest of the absolute values of the
378
      --  numerator and the denominator (taking into account the base value),
379
      --  and K to the lesser of the two absolute values. The gcd of Num and
380
      --  Den is the gcd of J and K.
381
 
382
      if Val.Rbase = 0 then
383
         J := Val.Num;
384
         K := Val.Den;
385
 
386
      elsif Val.Den < 0 then
387
         J := Val.Num * Val.Rbase ** (-Val.Den);
388
         K := Uint_1;
389
 
390
      else
391
         J := Val.Num;
392
         K := Val.Rbase ** Val.Den;
393
      end if;
394
 
395
      Num := J;
396
      Den := K;
397
 
398
      if K > J then
399
         Tmp := J;
400
         J := K;
401
         K := Tmp;
402
      end if;
403
 
404
      J := UI_GCD (J, K);
405
      Num := Num / J;
406
      Den := Den / J;
407
      Uintp.Release_And_Save (M, Num, Den);
408
 
409
      --  Divide numerator and denominator by gcd and return result
410
 
411
      return (Num      => Num,
412
              Den      => Den,
413
              Rbase    => 0,
414
              Negative => Val.Negative);
415
   end Normalize;
416
 
417
   ---------------
418
   -- Numerator --
419
   ---------------
420
 
421
   function Numerator (Real : Ureal) return Uint is
422
   begin
423
      return Ureals.Table (Real).Num;
424
   end Numerator;
425
 
426
   --------
427
   -- pr --
428
   --------
429
 
430
   procedure pr (Real : Ureal) is
431
   begin
432
      UR_Write (Real);
433
      Write_Eol;
434
   end pr;
435
 
436
   -----------
437
   -- Rbase --
438
   -----------
439
 
440
   function Rbase (Real : Ureal) return Nat is
441
   begin
442
      return Ureals.Table (Real).Rbase;
443
   end Rbase;
444
 
445
   -------------
446
   -- Release --
447
   -------------
448
 
449
   procedure Release (M : Save_Mark) is
450
   begin
451
      Ureals.Set_Last (Ureal (M));
452
   end Release;
453
 
454
   ----------
455
   -- Same --
456
   ----------
457
 
458
   function Same (U1, U2 : Ureal) return Boolean is
459
   begin
460
      return Int (U1) = Int (U2);
461
   end Same;
462
 
463
   -----------------
464
   -- Store_Ureal --
465
   -----------------
466
 
467
   function Store_Ureal (Val : Ureal_Entry) return Ureal is
468
   begin
469
      Ureals.Append (Val);
470
 
471
      --  Normalize representation of signed values
472
 
473
      if Val.Num < 0 then
474
         Ureals.Table (Ureals.Last).Negative := True;
475
         Ureals.Table (Ureals.Last).Num := -Val.Num;
476
      end if;
477
 
478
      return Ureals.Last;
479
   end Store_Ureal;
480
 
481
   ----------------------------
482
   -- Store_Ureal_Normalized --
483
   ----------------------------
484
 
485
   function Store_Ureal_Normalized (Val : Ureal_Entry) return Ureal is
486
   begin
487
      return Store_Ureal (Normalize (Val));
488
   end Store_Ureal_Normalized;
489
 
490
   ---------------
491
   -- Tree_Read --
492
   ---------------
493
 
494
   procedure Tree_Read is
495
   begin
496
      pragma Assert (Num_Ureal_Constants = 10);
497
 
498
      Ureals.Tree_Read;
499
      Tree_Read_Int (Int (UR_0));
500
      Tree_Read_Int (Int (UR_M_0));
501
      Tree_Read_Int (Int (UR_Tenth));
502
      Tree_Read_Int (Int (UR_Half));
503
      Tree_Read_Int (Int (UR_1));
504
      Tree_Read_Int (Int (UR_2));
505
      Tree_Read_Int (Int (UR_10));
506
      Tree_Read_Int (Int (UR_100));
507
      Tree_Read_Int (Int (UR_2_128));
508
      Tree_Read_Int (Int (UR_2_M_128));
509
 
510
      --  Clear the normalization cache
511
 
512
      Normalized_Real := No_Ureal;
513
   end Tree_Read;
514
 
515
   ----------------
516
   -- Tree_Write --
517
   ----------------
518
 
519
   procedure Tree_Write is
520
   begin
521
      pragma Assert (Num_Ureal_Constants = 10);
522
 
523
      Ureals.Tree_Write;
524
      Tree_Write_Int (Int (UR_0));
525
      Tree_Write_Int (Int (UR_M_0));
526
      Tree_Write_Int (Int (UR_Tenth));
527
      Tree_Write_Int (Int (UR_Half));
528
      Tree_Write_Int (Int (UR_1));
529
      Tree_Write_Int (Int (UR_2));
530
      Tree_Write_Int (Int (UR_10));
531
      Tree_Write_Int (Int (UR_100));
532
      Tree_Write_Int (Int (UR_2_128));
533
      Tree_Write_Int (Int (UR_2_M_128));
534
   end Tree_Write;
535
 
536
   ------------
537
   -- UR_Abs --
538
   ------------
539
 
540
   function UR_Abs (Real : Ureal) return Ureal is
541
      Val : constant Ureal_Entry := Ureals.Table (Real);
542
 
543
   begin
544
      return Store_Ureal
545
               ((Num      => Val.Num,
546
                 Den      => Val.Den,
547
                 Rbase    => Val.Rbase,
548
                 Negative => False));
549
   end UR_Abs;
550
 
551
   ------------
552
   -- UR_Add --
553
   ------------
554
 
555
   function UR_Add (Left : Uint; Right : Ureal) return Ureal is
556
   begin
557
      return UR_From_Uint (Left) + Right;
558
   end UR_Add;
559
 
560
   function UR_Add (Left : Ureal; Right : Uint) return Ureal is
561
   begin
562
      return Left + UR_From_Uint (Right);
563
   end UR_Add;
564
 
565
   function UR_Add (Left : Ureal; Right : Ureal) return Ureal is
566
      Lval : Ureal_Entry := Ureals.Table (Left);
567
      Rval : Ureal_Entry := Ureals.Table (Right);
568
      Num  : Uint;
569
 
570
   begin
571
      --  Note, in the temporary Ureal_Entry values used in this procedure,
572
      --  we store the sign as the sign of the numerator (i.e. xxx.Num may
573
      --  be negative, even though in stored entries this can never be so)
574
 
575
      if Lval.Rbase /= 0 and then Lval.Rbase = Rval.Rbase then
576
         declare
577
            Opd_Min, Opd_Max   : Ureal_Entry;
578
            Exp_Min, Exp_Max   : Uint;
579
 
580
         begin
581
            if Lval.Negative then
582
               Lval.Num := (-Lval.Num);
583
            end if;
584
 
585
            if Rval.Negative then
586
               Rval.Num := (-Rval.Num);
587
            end if;
588
 
589
            if Lval.Den < Rval.Den then
590
               Exp_Min := Lval.Den;
591
               Exp_Max := Rval.Den;
592
               Opd_Min := Lval;
593
               Opd_Max := Rval;
594
            else
595
               Exp_Min := Rval.Den;
596
               Exp_Max := Lval.Den;
597
               Opd_Min := Rval;
598
               Opd_Max := Lval;
599
            end if;
600
 
601
            Num :=
602
              Opd_Min.Num * Lval.Rbase ** (Exp_Max - Exp_Min) + Opd_Max.Num;
603
 
604
            if Num = 0 then
605
               return Store_Ureal
606
                        ((Num      => Uint_0,
607
                          Den      => Uint_1,
608
                          Rbase    => 0,
609
                          Negative => Lval.Negative));
610
 
611
            else
612
               return Store_Ureal
613
                        ((Num      => abs Num,
614
                          Den      => Exp_Max,
615
                          Rbase    => Lval.Rbase,
616
                          Negative => (Num < 0)));
617
            end if;
618
         end;
619
 
620
      else
621
         declare
622
            Ln : Ureal_Entry := Normalize (Lval);
623
            Rn : Ureal_Entry := Normalize (Rval);
624
 
625
         begin
626
            if Ln.Negative then
627
               Ln.Num := (-Ln.Num);
628
            end if;
629
 
630
            if Rn.Negative then
631
               Rn.Num := (-Rn.Num);
632
            end if;
633
 
634
            Num := (Ln.Num * Rn.Den) + (Rn.Num * Ln.Den);
635
 
636
            if Num = 0 then
637
               return Store_Ureal
638
                        ((Num      => Uint_0,
639
                          Den      => Uint_1,
640
                          Rbase    => 0,
641
                          Negative => Lval.Negative));
642
 
643
            else
644
               return Store_Ureal_Normalized
645
                        ((Num      => abs Num,
646
                          Den      => Ln.Den * Rn.Den,
647
                          Rbase    => 0,
648
                          Negative => (Num < 0)));
649
            end if;
650
         end;
651
      end if;
652
   end UR_Add;
653
 
654
   ----------------
655
   -- UR_Ceiling --
656
   ----------------
657
 
658
   function UR_Ceiling (Real : Ureal) return Uint is
659
      Val : constant Ureal_Entry := Normalize (Ureals.Table (Real));
660
   begin
661
      if Val.Negative then
662
         return UI_Negate (Val.Num / Val.Den);
663
      else
664
         return (Val.Num + Val.Den - 1) / Val.Den;
665
      end if;
666
   end UR_Ceiling;
667
 
668
   ------------
669
   -- UR_Div --
670
   ------------
671
 
672
   function UR_Div (Left : Uint; Right : Ureal) return Ureal is
673
   begin
674
      return UR_From_Uint (Left) / Right;
675
   end UR_Div;
676
 
677
   function UR_Div (Left : Ureal; Right : Uint) return Ureal is
678
   begin
679
      return Left / UR_From_Uint (Right);
680
   end UR_Div;
681
 
682
   function UR_Div (Left, Right : Ureal) return Ureal is
683
      Lval : constant Ureal_Entry := Ureals.Table (Left);
684
      Rval : constant Ureal_Entry := Ureals.Table (Right);
685
      Rneg : constant Boolean     := Rval.Negative xor Lval.Negative;
686
 
687
   begin
688
      pragma Assert (Rval.Num /= Uint_0);
689
 
690
      if Lval.Rbase = 0 then
691
         if Rval.Rbase = 0 then
692
            return Store_Ureal_Normalized
693
                     ((Num      => Lval.Num * Rval.Den,
694
                       Den      => Lval.Den * Rval.Num,
695
                       Rbase    => 0,
696
                       Negative => Rneg));
697
 
698
         elsif Is_Integer (Lval.Num, Rval.Num * Lval.Den) then
699
            return Store_Ureal
700
                     ((Num      => Lval.Num / (Rval.Num * Lval.Den),
701
                       Den      => (-Rval.Den),
702
                       Rbase    => Rval.Rbase,
703
                       Negative => Rneg));
704
 
705
         elsif Rval.Den < 0 then
706
            return Store_Ureal_Normalized
707
                     ((Num      => Lval.Num,
708
                       Den      => Rval.Rbase ** (-Rval.Den) *
709
                                   Rval.Num *
710
                                   Lval.Den,
711
                       Rbase    => 0,
712
                       Negative => Rneg));
713
 
714
         else
715
            return Store_Ureal_Normalized
716
                     ((Num      => Lval.Num * Rval.Rbase ** Rval.Den,
717
                       Den      => Rval.Num * Lval.Den,
718
                       Rbase    => 0,
719
                       Negative => Rneg));
720
         end if;
721
 
722
      elsif Is_Integer (Lval.Num, Rval.Num) then
723
         if Rval.Rbase = Lval.Rbase then
724
            return Store_Ureal
725
                     ((Num      => Lval.Num / Rval.Num,
726
                       Den      => Lval.Den - Rval.Den,
727
                       Rbase    => Lval.Rbase,
728
                       Negative => Rneg));
729
 
730
         elsif Rval.Rbase = 0 then
731
            return Store_Ureal
732
                     ((Num      => (Lval.Num / Rval.Num) * Rval.Den,
733
                       Den      => Lval.Den,
734
                       Rbase    => Lval.Rbase,
735
                       Negative => Rneg));
736
 
737
         elsif Rval.Den < 0 then
738
            declare
739
               Num, Den : Uint;
740
 
741
            begin
742
               if Lval.Den < 0 then
743
                  Num := (Lval.Num / Rval.Num) * (Lval.Rbase ** (-Lval.Den));
744
                  Den := Rval.Rbase ** (-Rval.Den);
745
               else
746
                  Num := Lval.Num / Rval.Num;
747
                  Den := (Lval.Rbase ** Lval.Den) *
748
                         (Rval.Rbase ** (-Rval.Den));
749
               end if;
750
 
751
               return Store_Ureal
752
                        ((Num      => Num,
753
                          Den      => Den,
754
                          Rbase    => 0,
755
                          Negative => Rneg));
756
            end;
757
 
758
         else
759
            return Store_Ureal
760
                     ((Num      => (Lval.Num / Rval.Num) *
761
                                   (Rval.Rbase ** Rval.Den),
762
                       Den      => Lval.Den,
763
                       Rbase    => Lval.Rbase,
764
                       Negative => Rneg));
765
         end if;
766
 
767
      else
768
         declare
769
            Num, Den : Uint;
770
 
771
         begin
772
            if Lval.Den < 0 then
773
               Num := Lval.Num * (Lval.Rbase ** (-Lval.Den));
774
               Den := Rval.Num;
775
            else
776
               Num := Lval.Num;
777
               Den := Rval.Num * (Lval.Rbase ** Lval.Den);
778
            end if;
779
 
780
            if Rval.Rbase /= 0 then
781
               if Rval.Den < 0 then
782
                  Den := Den * (Rval.Rbase ** (-Rval.Den));
783
               else
784
                  Num := Num * (Rval.Rbase ** Rval.Den);
785
               end if;
786
 
787
            else
788
               Num := Num * Rval.Den;
789
            end if;
790
 
791
            return Store_Ureal_Normalized
792
                     ((Num      => Num,
793
                       Den      => Den,
794
                       Rbase    => 0,
795
                       Negative => Rneg));
796
         end;
797
      end if;
798
   end UR_Div;
799
 
800
   -----------
801
   -- UR_Eq --
802
   -----------
803
 
804
   function UR_Eq (Left, Right : Ureal) return Boolean is
805
   begin
806
      return not UR_Ne (Left, Right);
807
   end UR_Eq;
808
 
809
   ---------------------
810
   -- UR_Exponentiate --
811
   ---------------------
812
 
813
   function UR_Exponentiate (Real : Ureal; N : Uint) return Ureal is
814
      X    : constant Uint := abs N;
815
      Bas  : Ureal;
816
      Val  : Ureal_Entry;
817
      Neg  : Boolean;
818
      IBas : Uint;
819
 
820
   begin
821
      --  If base is negative, then the resulting sign depends on whether
822
      --  the exponent is even or odd (even => positive, odd = negative)
823
 
824
      if UR_Is_Negative (Real) then
825
         Neg := (N mod 2) /= 0;
826
         Bas := UR_Negate (Real);
827
      else
828
         Neg := False;
829
         Bas := Real;
830
      end if;
831
 
832
      Val := Ureals.Table (Bas);
833
 
834
      --  If the base is a small integer, then we can return the result in
835
      --  exponential form, which can save a lot of time for junk exponents.
836
 
837
      IBas := UR_Trunc (Bas);
838
 
839
      if IBas <= 16
840
        and then UR_From_Uint (IBas) = Bas
841
      then
842
         return Store_Ureal
843
                  ((Num      => Uint_1,
844
                    Den      => -N,
845
                    Rbase    => UI_To_Int (UR_Trunc (Bas)),
846
                    Negative => Neg));
847
 
848
      --  If the exponent is negative then we raise the numerator and the
849
      --  denominator (after normalization) to the absolute value of the
850
      --  exponent and we return the reciprocal. An assert error will happen
851
      --  if the numerator is zero.
852
 
853
      elsif N < 0 then
854
         pragma Assert (Val.Num /= 0);
855
         Val := Normalize (Val);
856
 
857
         return Store_Ureal
858
                  ((Num      => Val.Den ** X,
859
                    Den      => Val.Num ** X,
860
                    Rbase    => 0,
861
                    Negative => Neg));
862
 
863
      --  If positive, we distinguish the case when the base is not zero, in
864
      --  which case the new denominator is just the product of the old one
865
      --  with the exponent,
866
 
867
      else
868
         if Val.Rbase /= 0 then
869
 
870
            return Store_Ureal
871
                     ((Num      => Val.Num ** X,
872
                       Den      => Val.Den * X,
873
                       Rbase    => Val.Rbase,
874
                       Negative => Neg));
875
 
876
         --  And when the base is zero, in which case we exponentiate
877
         --  the old denominator.
878
 
879
         else
880
            return Store_Ureal
881
                     ((Num      => Val.Num ** X,
882
                       Den      => Val.Den ** X,
883
                       Rbase    => 0,
884
                       Negative => Neg));
885
         end if;
886
      end if;
887
   end UR_Exponentiate;
888
 
889
   --------------
890
   -- UR_Floor --
891
   --------------
892
 
893
   function UR_Floor (Real : Ureal) return Uint is
894
      Val : constant Ureal_Entry := Normalize (Ureals.Table (Real));
895
   begin
896
      if Val.Negative then
897
         return UI_Negate ((Val.Num + Val.Den - 1) / Val.Den);
898
      else
899
         return Val.Num / Val.Den;
900
      end if;
901
   end UR_Floor;
902
 
903
   ------------------------
904
   -- UR_From_Components --
905
   ------------------------
906
 
907
   function UR_From_Components
908
     (Num      : Uint;
909
      Den      : Uint;
910
      Rbase    : Nat := 0;
911
      Negative : Boolean := False)
912
      return     Ureal
913
   is
914
   begin
915
      return Store_Ureal
916
               ((Num      => Num,
917
                 Den      => Den,
918
                 Rbase    => Rbase,
919
                 Negative => Negative));
920
   end UR_From_Components;
921
 
922
   ------------------
923
   -- UR_From_Uint --
924
   ------------------
925
 
926
   function UR_From_Uint (UI : Uint) return Ureal is
927
   begin
928
      return UR_From_Components
929
               (abs UI, Uint_1, Negative => (UI < 0));
930
   end UR_From_Uint;
931
 
932
   -----------
933
   -- UR_Ge --
934
   -----------
935
 
936
   function UR_Ge (Left, Right : Ureal) return Boolean is
937
   begin
938
      return not (Left < Right);
939
   end UR_Ge;
940
 
941
   -----------
942
   -- UR_Gt --
943
   -----------
944
 
945
   function UR_Gt (Left, Right : Ureal) return Boolean is
946
   begin
947
      return (Right < Left);
948
   end UR_Gt;
949
 
950
   --------------------
951
   -- UR_Is_Negative --
952
   --------------------
953
 
954
   function UR_Is_Negative (Real : Ureal) return Boolean is
955
   begin
956
      return Ureals.Table (Real).Negative;
957
   end UR_Is_Negative;
958
 
959
   --------------------
960
   -- UR_Is_Positive --
961
   --------------------
962
 
963
   function UR_Is_Positive (Real : Ureal) return Boolean is
964
   begin
965
      return not Ureals.Table (Real).Negative
966
        and then Ureals.Table (Real).Num /= 0;
967
   end UR_Is_Positive;
968
 
969
   ----------------
970
   -- UR_Is_Zero --
971
   ----------------
972
 
973
   function UR_Is_Zero (Real : Ureal) return Boolean is
974
   begin
975
      return Ureals.Table (Real).Num = 0;
976
   end UR_Is_Zero;
977
 
978
   -----------
979
   -- UR_Le --
980
   -----------
981
 
982
   function UR_Le (Left, Right : Ureal) return Boolean is
983
   begin
984
      return not (Right < Left);
985
   end UR_Le;
986
 
987
   -----------
988
   -- UR_Lt --
989
   -----------
990
 
991
   function UR_Lt (Left, Right : Ureal) return Boolean is
992
   begin
993
      --  An operand is not less than itself
994
 
995
      if Same (Left, Right) then
996
         return False;
997
 
998
      --  Deal with zero cases
999
 
1000
      elsif UR_Is_Zero (Left) then
1001
         return UR_Is_Positive (Right);
1002
 
1003
      elsif UR_Is_Zero (Right) then
1004
         return Ureals.Table (Left).Negative;
1005
 
1006
      --  Different signs are decisive (note we dealt with zero cases)
1007
 
1008
      elsif Ureals.Table (Left).Negative
1009
        and then not Ureals.Table (Right).Negative
1010
      then
1011
         return True;
1012
 
1013
      elsif not Ureals.Table (Left).Negative
1014
        and then Ureals.Table (Right).Negative
1015
      then
1016
         return False;
1017
 
1018
      --  Signs are same, do rapid check based on worst case estimates of
1019
      --  decimal exponent, which will often be decisive. Precise test
1020
      --  depends on whether operands are positive or negative.
1021
 
1022
      elsif Decimal_Exponent_Hi (Left) < Decimal_Exponent_Lo (Right) then
1023
         return UR_Is_Positive (Left);
1024
 
1025
      elsif Decimal_Exponent_Lo (Left) > Decimal_Exponent_Hi (Right) then
1026
         return UR_Is_Negative (Left);
1027
 
1028
      --  If we fall through, full gruesome test is required. This happens
1029
      --  if the numbers are close together, or in some weird (/=10) base.
1030
 
1031
      else
1032
         declare
1033
            Imrk   : constant Uintp.Save_Mark  := Mark;
1034
            Rmrk   : constant Urealp.Save_Mark := Mark;
1035
            Lval   : Ureal_Entry;
1036
            Rval   : Ureal_Entry;
1037
            Result : Boolean;
1038
 
1039
         begin
1040
            Lval := Ureals.Table (Left);
1041
            Rval := Ureals.Table (Right);
1042
 
1043
            --  An optimization. If both numbers are based, then subtract
1044
            --  common value of base to avoid unnecessarily giant numbers
1045
 
1046
            if Lval.Rbase = Rval.Rbase and then Lval.Rbase /= 0 then
1047
               if Lval.Den < Rval.Den then
1048
                  Rval.Den := Rval.Den - Lval.Den;
1049
                  Lval.Den := Uint_0;
1050
               else
1051
                  Lval.Den := Lval.Den - Rval.Den;
1052
                  Rval.Den := Uint_0;
1053
               end if;
1054
            end if;
1055
 
1056
            Lval := Normalize (Lval);
1057
            Rval := Normalize (Rval);
1058
 
1059
            if Lval.Negative then
1060
               Result := (Lval.Num * Rval.Den) > (Rval.Num * Lval.Den);
1061
            else
1062
               Result := (Lval.Num * Rval.Den) < (Rval.Num * Lval.Den);
1063
            end if;
1064
 
1065
            Release (Imrk);
1066
            Release (Rmrk);
1067
            return Result;
1068
         end;
1069
      end if;
1070
   end UR_Lt;
1071
 
1072
   ------------
1073
   -- UR_Max --
1074
   ------------
1075
 
1076
   function UR_Max (Left, Right : Ureal) return Ureal is
1077
   begin
1078
      if Left >= Right then
1079
         return Left;
1080
      else
1081
         return Right;
1082
      end if;
1083
   end UR_Max;
1084
 
1085
   ------------
1086
   -- UR_Min --
1087
   ------------
1088
 
1089
   function UR_Min (Left, Right : Ureal) return Ureal is
1090
   begin
1091
      if Left <= Right then
1092
         return Left;
1093
      else
1094
         return Right;
1095
      end if;
1096
   end UR_Min;
1097
 
1098
   ------------
1099
   -- UR_Mul --
1100
   ------------
1101
 
1102
   function UR_Mul (Left : Uint; Right : Ureal) return Ureal is
1103
   begin
1104
      return UR_From_Uint (Left) * Right;
1105
   end UR_Mul;
1106
 
1107
   function UR_Mul (Left : Ureal; Right : Uint) return Ureal is
1108
   begin
1109
      return Left * UR_From_Uint (Right);
1110
   end UR_Mul;
1111
 
1112
   function UR_Mul (Left, Right : Ureal) return Ureal is
1113
      Lval : constant Ureal_Entry := Ureals.Table (Left);
1114
      Rval : constant Ureal_Entry := Ureals.Table (Right);
1115
      Num  : Uint                 := Lval.Num * Rval.Num;
1116
      Den  : Uint;
1117
      Rneg : constant Boolean     := Lval.Negative xor Rval.Negative;
1118
 
1119
   begin
1120
      if Lval.Rbase = 0 then
1121
         if Rval.Rbase = 0 then
1122
            return Store_Ureal_Normalized
1123
                     ((Num      => Num,
1124
                       Den      => Lval.Den * Rval.Den,
1125
                       Rbase    => 0,
1126
                       Negative => Rneg));
1127
 
1128
         elsif Is_Integer (Num, Lval.Den) then
1129
            return Store_Ureal
1130
                     ((Num      => Num / Lval.Den,
1131
                       Den      => Rval.Den,
1132
                       Rbase    => Rval.Rbase,
1133
                       Negative => Rneg));
1134
 
1135
         elsif Rval.Den < 0 then
1136
            return Store_Ureal_Normalized
1137
                     ((Num      => Num * (Rval.Rbase ** (-Rval.Den)),
1138
                       Den      => Lval.Den,
1139
                       Rbase    => 0,
1140
                       Negative => Rneg));
1141
 
1142
         else
1143
            return Store_Ureal_Normalized
1144
                     ((Num      => Num,
1145
                       Den      => Lval.Den * (Rval.Rbase ** Rval.Den),
1146
                       Rbase    => 0,
1147
                       Negative => Rneg));
1148
         end if;
1149
 
1150
      elsif Lval.Rbase = Rval.Rbase then
1151
         return Store_Ureal
1152
                  ((Num      => Num,
1153
                    Den      => Lval.Den + Rval.Den,
1154
                    Rbase    => Lval.Rbase,
1155
                    Negative => Rneg));
1156
 
1157
      elsif Rval.Rbase = 0 then
1158
         if Is_Integer (Num, Rval.Den) then
1159
            return Store_Ureal
1160
                     ((Num      => Num / Rval.Den,
1161
                       Den      => Lval.Den,
1162
                       Rbase    => Lval.Rbase,
1163
                       Negative => Rneg));
1164
 
1165
         elsif Lval.Den < 0 then
1166
            return Store_Ureal_Normalized
1167
                     ((Num      => Num * (Lval.Rbase ** (-Lval.Den)),
1168
                       Den      => Rval.Den,
1169
                       Rbase    => 0,
1170
                       Negative => Rneg));
1171
 
1172
         else
1173
            return Store_Ureal_Normalized
1174
                     ((Num      => Num,
1175
                       Den      => Rval.Den * (Lval.Rbase ** Lval.Den),
1176
                       Rbase    => 0,
1177
                       Negative => Rneg));
1178
         end if;
1179
 
1180
      else
1181
         Den := Uint_1;
1182
 
1183
         if Lval.Den < 0 then
1184
            Num := Num * (Lval.Rbase ** (-Lval.Den));
1185
         else
1186
            Den := Den * (Lval.Rbase ** Lval.Den);
1187
         end if;
1188
 
1189
         if Rval.Den < 0 then
1190
            Num := Num * (Rval.Rbase ** (-Rval.Den));
1191
         else
1192
            Den := Den * (Rval.Rbase ** Rval.Den);
1193
         end if;
1194
 
1195
         return Store_Ureal_Normalized
1196
                  ((Num      => Num,
1197
                    Den      => Den,
1198
                    Rbase    => 0,
1199
                    Negative => Rneg));
1200
      end if;
1201
   end UR_Mul;
1202
 
1203
   -----------
1204
   -- UR_Ne --
1205
   -----------
1206
 
1207
   function UR_Ne (Left, Right : Ureal) return Boolean is
1208
   begin
1209
      --  Quick processing for case of identical Ureal values (note that
1210
      --  this also deals with comparing two No_Ureal values).
1211
 
1212
      if Same (Left, Right) then
1213
         return False;
1214
 
1215
      --  Deal with case of one or other operand is No_Ureal, but not both
1216
 
1217
      elsif Same (Left, No_Ureal) or else Same (Right, No_Ureal) then
1218
         return True;
1219
 
1220
      --  Do quick check based on number of decimal digits
1221
 
1222
      elsif Decimal_Exponent_Hi (Left) < Decimal_Exponent_Lo (Right) or else
1223
            Decimal_Exponent_Lo (Left) > Decimal_Exponent_Hi (Right)
1224
      then
1225
         return True;
1226
 
1227
      --  Otherwise full comparison is required
1228
 
1229
      else
1230
         declare
1231
            Imrk   : constant Uintp.Save_Mark  := Mark;
1232
            Rmrk   : constant Urealp.Save_Mark := Mark;
1233
            Lval   : constant Ureal_Entry := Normalize (Ureals.Table (Left));
1234
            Rval   : constant Ureal_Entry := Normalize (Ureals.Table (Right));
1235
            Result : Boolean;
1236
 
1237
         begin
1238
            if UR_Is_Zero (Left) then
1239
               return not UR_Is_Zero (Right);
1240
 
1241
            elsif UR_Is_Zero (Right) then
1242
               return not UR_Is_Zero (Left);
1243
 
1244
            --  Both operands are non-zero
1245
 
1246
            else
1247
               Result :=
1248
                  Rval.Negative /= Lval.Negative
1249
                    or else Rval.Num /= Lval.Num
1250
                    or else Rval.Den /= Lval.Den;
1251
               Release (Imrk);
1252
               Release (Rmrk);
1253
               return Result;
1254
            end if;
1255
         end;
1256
      end if;
1257
   end UR_Ne;
1258
 
1259
   ---------------
1260
   -- UR_Negate --
1261
   ---------------
1262
 
1263
   function UR_Negate (Real : Ureal) return Ureal is
1264
   begin
1265
      return Store_Ureal
1266
               ((Num      => Ureals.Table (Real).Num,
1267
                 Den      => Ureals.Table (Real).Den,
1268
                 Rbase    => Ureals.Table (Real).Rbase,
1269
                 Negative => not Ureals.Table (Real).Negative));
1270
   end UR_Negate;
1271
 
1272
   ------------
1273
   -- UR_Sub --
1274
   ------------
1275
 
1276
   function UR_Sub (Left : Uint; Right : Ureal) return Ureal is
1277
   begin
1278
      return UR_From_Uint (Left) + UR_Negate (Right);
1279
   end UR_Sub;
1280
 
1281
   function UR_Sub (Left : Ureal; Right : Uint) return Ureal is
1282
   begin
1283
      return Left + UR_From_Uint (-Right);
1284
   end UR_Sub;
1285
 
1286
   function UR_Sub (Left, Right : Ureal) return Ureal is
1287
   begin
1288
      return Left + UR_Negate (Right);
1289
   end UR_Sub;
1290
 
1291
   ----------------
1292
   -- UR_To_Uint --
1293
   ----------------
1294
 
1295
   function UR_To_Uint (Real : Ureal) return Uint is
1296
      Val : constant Ureal_Entry := Normalize (Ureals.Table (Real));
1297
      Res : Uint;
1298
 
1299
   begin
1300
      Res := (Val.Num + (Val.Den / 2)) / Val.Den;
1301
 
1302
      if Val.Negative then
1303
         return UI_Negate (Res);
1304
      else
1305
         return Res;
1306
      end if;
1307
   end UR_To_Uint;
1308
 
1309
   --------------
1310
   -- UR_Trunc --
1311
   --------------
1312
 
1313
   function UR_Trunc (Real : Ureal) return Uint is
1314
      Val : constant Ureal_Entry := Normalize (Ureals.Table (Real));
1315
   begin
1316
      if Val.Negative then
1317
         return -(Val.Num / Val.Den);
1318
      else
1319
         return Val.Num / Val.Den;
1320
      end if;
1321
   end UR_Trunc;
1322
 
1323
   --------------
1324
   -- UR_Write --
1325
   --------------
1326
 
1327
   procedure UR_Write (Real : Ureal; Brackets : Boolean := False) is
1328
      Val : constant Ureal_Entry := Ureals.Table (Real);
1329
      T   : Uint;
1330
 
1331
   begin
1332
      --  If value is negative, we precede the constant by a minus sign
1333
 
1334
      if Val.Negative then
1335
         Write_Char ('-');
1336
      end if;
1337
 
1338
      --  Zero is zero
1339
 
1340
      if Val.Num = 0 then
1341
         Write_Str ("0.0");
1342
 
1343
      --  For constants with a denominator of zero, the value is simply the
1344
      --  numerator value, since we are dividing by base**0, which is 1.
1345
 
1346
      elsif Val.Den = 0 then
1347
         UI_Write (Val.Num, Decimal);
1348
         Write_Str (".0");
1349
 
1350
      --  Small powers of 2 get written in decimal fixed-point format
1351
 
1352
      elsif Val.Rbase = 2
1353
        and then Val.Den <= 3
1354
        and then Val.Den >= -16
1355
      then
1356
         if Val.Den = 1 then
1357
            T := Val.Num * (10/2);
1358
            UI_Write (T / 10, Decimal);
1359
            Write_Char ('.');
1360
            UI_Write (T mod 10, Decimal);
1361
 
1362
         elsif Val.Den = 2 then
1363
            T := Val.Num * (100/4);
1364
            UI_Write (T / 100, Decimal);
1365
            Write_Char ('.');
1366
            UI_Write (T mod 100 / 10, Decimal);
1367
 
1368
            if T mod 10 /= 0 then
1369
               UI_Write (T mod 10, Decimal);
1370
            end if;
1371
 
1372
         elsif Val.Den = 3 then
1373
            T := Val.Num * (1000 / 8);
1374
            UI_Write (T / 1000, Decimal);
1375
            Write_Char ('.');
1376
            UI_Write (T mod 1000 / 100, Decimal);
1377
 
1378
            if T mod 100 /= 0 then
1379
               UI_Write (T mod 100 / 10, Decimal);
1380
 
1381
               if T mod 10 /= 0 then
1382
                  UI_Write (T mod 10, Decimal);
1383
               end if;
1384
            end if;
1385
 
1386
         else
1387
            UI_Write (Val.Num * (Uint_2 ** (-Val.Den)), Decimal);
1388
            Write_Str (".0");
1389
         end if;
1390
 
1391
      --  Constants in base 10 or 16 can be written in normal Ada literal
1392
      --  style, as long as they fit in the UI_Image_Buffer. Using hexadecimal
1393
      --  notation, 4 bytes are required for the 16# # part, and every fifth
1394
      --  character is an underscore. So, a buffer of size N has room for
1395
      --     ((N - 4) - (N - 4) / 5) * 4 bits,
1396
      --  or at least
1397
      --     N * 16 / 5 - 12 bits.
1398
 
1399
      elsif (Val.Rbase = 10 or else Val.Rbase = 16)
1400
        and then Num_Bits (Val.Num) < UI_Image_Buffer'Length * 16 / 5 - 12
1401
      then
1402
         pragma Assert (Val.Den /= 0);
1403
 
1404
         --  Use fixed-point format for small scaling values
1405
 
1406
         if (Val.Rbase = 10 and then Val.Den < 0 and then Val.Den > -3)
1407
              or else (Val.Rbase = 16 and then Val.Den = -1)
1408
         then
1409
            UI_Write (Val.Num * Val.Rbase**(-Val.Den), Decimal);
1410
            Write_Str (".0");
1411
 
1412
         --  Write hexadecimal constants in exponential notation with a zero
1413
         --  unit digit. This matches the Ada canonical form for floating point
1414
         --  numbers, and also ensures that the underscores end up in the
1415
         --  correct place.
1416
 
1417
         elsif Val.Rbase = 16 then
1418
            UI_Image (Val.Num, Hex);
1419
            pragma Assert (Val.Rbase = 16);
1420
 
1421
            Write_Str ("16#0.");
1422
            Write_Str (UI_Image_Buffer (4 .. UI_Image_Length));
1423
 
1424
            --  For exponent, exclude 16# # and underscores from length
1425
 
1426
            UI_Image_Length := UI_Image_Length - 4;
1427
            UI_Image_Length := UI_Image_Length - UI_Image_Length / 5;
1428
 
1429
            Write_Char ('E');
1430
            UI_Write (Int (UI_Image_Length) - Val.Den, Decimal);
1431
 
1432
         elsif Val.Den = 1 then
1433
            UI_Write (Val.Num / 10, Decimal);
1434
            Write_Char ('.');
1435
            UI_Write (Val.Num mod 10, Decimal);
1436
 
1437
         elsif Val.Den = 2 then
1438
            UI_Write (Val.Num / 100, Decimal);
1439
            Write_Char ('.');
1440
            UI_Write (Val.Num / 10 mod 10, Decimal);
1441
            UI_Write (Val.Num mod 10, Decimal);
1442
 
1443
         --  Else use decimal exponential format
1444
 
1445
         else
1446
            --  Write decimal constants with a non-zero unit digit. This
1447
            --  matches usual scientific notation.
1448
 
1449
            UI_Image (Val.Num, Decimal);
1450
            Write_Char (UI_Image_Buffer (1));
1451
            Write_Char ('.');
1452
 
1453
            if UI_Image_Length = 1 then
1454
               Write_Char ('0');
1455
            else
1456
               Write_Str (UI_Image_Buffer (2 .. UI_Image_Length));
1457
            end if;
1458
 
1459
            Write_Char ('E');
1460
            UI_Write (Int (UI_Image_Length - 1) - Val.Den, Decimal);
1461
         end if;
1462
 
1463
      --  Constants in a base other than 10 can still be easily written in
1464
      --  normal Ada literal style if the numerator is one.
1465
 
1466
      elsif Val.Rbase /= 0 and then Val.Num = 1 then
1467
         Write_Int (Val.Rbase);
1468
         Write_Str ("#1.0#E");
1469
         UI_Write (-Val.Den);
1470
 
1471
      --  Other constants with a base other than 10 are written using one
1472
      --  of the following forms, depending on the sign of the number
1473
      --  and the sign of the exponent (= minus denominator value)
1474
 
1475
      --    numerator.0*base**exponent
1476
      --    numerator.0*base**-exponent
1477
 
1478
      --  And of course an exponent of 0 can be omitted
1479
 
1480
      elsif Val.Rbase /= 0 then
1481
         if Brackets then
1482
            Write_Char ('[');
1483
         end if;
1484
 
1485
         UI_Write (Val.Num, Decimal);
1486
         Write_Str (".0");
1487
 
1488
         if Val.Den /= 0 then
1489
            Write_Char ('*');
1490
            Write_Int (Val.Rbase);
1491
            Write_Str ("**");
1492
 
1493
            if Val.Den <= 0 then
1494
               UI_Write (-Val.Den, Decimal);
1495
            else
1496
               Write_Str ("(-");
1497
               UI_Write (Val.Den, Decimal);
1498
               Write_Char (')');
1499
            end if;
1500
         end if;
1501
 
1502
         if Brackets then
1503
            Write_Char (']');
1504
         end if;
1505
 
1506
      --  Rationals where numerator is divisible by denominator can be output
1507
      --  as literals after we do the division. This includes the common case
1508
      --  where the denominator is 1.
1509
 
1510
      elsif Val.Num mod Val.Den = 0 then
1511
         UI_Write (Val.Num / Val.Den, Decimal);
1512
         Write_Str (".0");
1513
 
1514
      --  Other non-based (rational) constants are written in num/den style
1515
 
1516
      else
1517
         if Brackets then
1518
            Write_Char ('[');
1519
         end if;
1520
 
1521
         UI_Write (Val.Num, Decimal);
1522
         Write_Str (".0/");
1523
         UI_Write (Val.Den, Decimal);
1524
         Write_Str (".0");
1525
 
1526
         if Brackets then
1527
            Write_Char (']');
1528
         end if;
1529
      end if;
1530
   end UR_Write;
1531
 
1532
   -------------
1533
   -- Ureal_0 --
1534
   -------------
1535
 
1536
   function Ureal_0 return Ureal is
1537
   begin
1538
      return UR_0;
1539
   end Ureal_0;
1540
 
1541
   -------------
1542
   -- Ureal_1 --
1543
   -------------
1544
 
1545
   function Ureal_1 return Ureal is
1546
   begin
1547
      return UR_1;
1548
   end Ureal_1;
1549
 
1550
   -------------
1551
   -- Ureal_2 --
1552
   -------------
1553
 
1554
   function Ureal_2 return Ureal is
1555
   begin
1556
      return UR_2;
1557
   end Ureal_2;
1558
 
1559
   --------------
1560
   -- Ureal_10 --
1561
   --------------
1562
 
1563
   function Ureal_10 return Ureal is
1564
   begin
1565
      return UR_10;
1566
   end Ureal_10;
1567
 
1568
   ---------------
1569
   -- Ureal_100 --
1570
   ---------------
1571
 
1572
   function Ureal_100 return Ureal is
1573
   begin
1574
      return UR_100;
1575
   end Ureal_100;
1576
 
1577
   -----------------
1578
   -- Ureal_10_36 --
1579
   -----------------
1580
 
1581
   function Ureal_10_36 return Ureal is
1582
   begin
1583
      return UR_10_36;
1584
   end Ureal_10_36;
1585
 
1586
   ----------------
1587
   -- Ureal_2_80 --
1588
   ----------------
1589
 
1590
   function Ureal_2_80 return Ureal is
1591
   begin
1592
      return UR_2_80;
1593
   end Ureal_2_80;
1594
 
1595
   -----------------
1596
   -- Ureal_2_128 --
1597
   -----------------
1598
 
1599
   function Ureal_2_128 return Ureal is
1600
   begin
1601
      return UR_2_128;
1602
   end Ureal_2_128;
1603
 
1604
   -------------------
1605
   -- Ureal_2_M_80 --
1606
   -------------------
1607
 
1608
   function Ureal_2_M_80 return Ureal is
1609
   begin
1610
      return UR_2_M_80;
1611
   end Ureal_2_M_80;
1612
 
1613
   -------------------
1614
   -- Ureal_2_M_128 --
1615
   -------------------
1616
 
1617
   function Ureal_2_M_128 return Ureal is
1618
   begin
1619
      return UR_2_M_128;
1620
   end Ureal_2_M_128;
1621
 
1622
   ----------------
1623
   -- Ureal_Half --
1624
   ----------------
1625
 
1626
   function Ureal_Half return Ureal is
1627
   begin
1628
      return UR_Half;
1629
   end Ureal_Half;
1630
 
1631
   ---------------
1632
   -- Ureal_M_0 --
1633
   ---------------
1634
 
1635
   function Ureal_M_0 return Ureal is
1636
   begin
1637
      return UR_M_0;
1638
   end Ureal_M_0;
1639
 
1640
   -------------------
1641
   -- Ureal_M_10_36 --
1642
   -------------------
1643
 
1644
   function Ureal_M_10_36 return Ureal is
1645
   begin
1646
      return UR_M_10_36;
1647
   end Ureal_M_10_36;
1648
 
1649
   -----------------
1650
   -- Ureal_Tenth --
1651
   -----------------
1652
 
1653
   function Ureal_Tenth return Ureal is
1654
   begin
1655
      return UR_Tenth;
1656
   end Ureal_Tenth;
1657
 
1658
end Urealp;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.