~ubuntu-branches/ubuntu/karmic/asis/karmic

« back to all changes in this revision

Viewing changes to gnat/urealp.adb

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Quinot
  • Date: 2002-03-03 19:55:58 UTC
  • Revision ID: james.westby@ubuntu.com-20020303195558-g7dp4vaq1zdkf814
Tags: upstream-3.14p
ImportĀ upstreamĀ versionĀ 3.14p

Show diffs side-by-side

added added

removed removed

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