PageRenderTime 29ms CodeModel.GetById 11ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/numeric/number.e

http://github.com/tybor/Liberty
Specman e | 1062 lines | 832 code | 107 blank | 123 comment | 17 complexity | 8af2d76fedaae0ba076f8897b9049957 MD5 | raw file
   1-- This file is part of a Liberty Eiffel library.
   2-- See the full copyright at the end.
   3--
   4deferred class NUMBER
   5   --
   6   -- This abstract definition of a NUMBER is intended to be the unique
   7   -- view of the client (do not use sub-classes names at all in the
   8   -- client code). In order to create NUMBERs without using concrete
   9   -- class name, the client code can inherit NUMBER_TOOLS. (See directory
  10   -- tutorial/number for examples.)
  11   --
  12
  13inherit
  14   HASHABLE
  15      redefine fill_tagged_out_memory, out_in_tagged_out_memory
  16      end
  17   COMPARABLE
  18      undefine is_equal
  19      redefine infix ">", infix "<=", infix ">=", in_range, compare, three_way_comparison, min, max, fill_tagged_out_memory,
  20         out_in_tagged_out_memory
  21      end
  22   NUMERIC
  23      redefine fill_tagged_out_memory, out_in_tagged_out_memory
  24      end
  25
  26insert
  27   PLATFORM
  28      undefine is_equal
  29      redefine fill_tagged_out_memory, out_in_tagged_out_memory
  30      end
  31
  32feature {ANY} -- Binary operators for two NUMBERs:
  33   infix "+" (other: NUMBER): NUMBER
  34         -- Sum of `Current' and `other'.
  35      require
  36         other /= Void
  37      deferred
  38      ensure
  39         (Result - other).is_equal(Current)
  40      end
  41
  42   infix "-" (other: NUMBER): NUMBER
  43         -- Difference of `Current' and `other'.
  44      require
  45         other /= Void
  46      do
  47         Result := Current + -other
  48      ensure
  49         (Result + other).is_equal(Current)
  50      end
  51
  52   infix "*" (other: NUMBER): NUMBER
  53         -- Product of `Current' and `other'.
  54      require
  55         other /= Void
  56      deferred
  57      ensure
  58         Result /= Void
  59      end
  60
  61   infix "/" (other: NUMBER): NUMBER
  62         -- Quotient of `Current' and `other'.
  63      do
  64         Result := Current * other.inverse
  65      ensure
  66         Result /= Void
  67      end
  68
  69   infix "//" (other: NUMBER): NUMBER
  70         -- Divide `Current' by `other' (Integer division).
  71      require
  72         is_integer_general_number
  73         other.is_integer_general_number
  74         divisible(other)
  75      deferred
  76      ensure
  77         Result.is_integer_general_number
  78         Current.is_equal(Result * other + Current \\ other)
  79      end
  80
  81   infix "\\" (other: NUMBER): NUMBER
  82         -- Remainder of division of `Current' by `other'.
  83      require
  84         is_integer_general_number
  85         other.is_integer_general_number
  86         divisible(other)
  87      deferred
  88      ensure
  89         Result.is_integer_general_number
  90         not Result.is_negative and Result < other.abs
  91      end
  92
  93   infix "^" (exp: NUMBER): NUMBER
  94         -- `Current' raised to `exp'-th power.
  95      require
  96         exp.is_integer_general_number
  97         is_zero implies exp @> 0
  98      local
  99         e: NUMBER; factor: NUMBER
 100      do
 101         Result := one
 102         factor := Current
 103         from
 104            e := exp.abs
 105         until
 106            e.is_zero
 107         loop
 108            if e.is_odd then
 109               Result := Result * factor
 110            end
 111            e := e @// 2
 112            factor := factor * factor
 113         end
 114         if exp @< 0 then
 115            Result := Result.inverse
 116         end
 117      ensure
 118         Result /= Void
 119         exp.is_zero implies Result.is_one
 120      end
 121
 122   infix "<" (other: NUMBER): BOOLEAN
 123         -- Is `Current' strictly less than `other'?
 124      deferred
 125      end
 126
 127   infix "<=" (other: NUMBER): BOOLEAN
 128         -- Is `Current' less or equal than `other'?
 129      do
 130         Result := not (other < Current)
 131      end
 132
 133   infix ">" (other: NUMBER): BOOLEAN
 134         -- Is `Current' strictly greater than `other'?
 135      do
 136         Result := other < Current
 137      end
 138
 139   infix ">=" (other: NUMBER): BOOLEAN
 140         -- Is `Current' greater or equal than `other'?
 141      do
 142         Result := not (Current < other)
 143      end
 144
 145   gcd (other: NUMBER): INTEGER_GENERAL_NUMBER
 146         -- Great Common Divisor of `Current' and `other'.
 147      require
 148         other.is_integer_general_number
 149         is_integer_general_number
 150      deferred
 151      ensure
 152         not Result.is_negative
 153         Result.is_zero implies Current.is_zero and other.is_zero
 154         not Result.is_zero implies (Current / Result).gcd(other / Result).is_one
 155      end
 156
 157feature {ANY} -- Unary operators for two NUMBERs:
 158   frozen prefix "+": NUMBER
 159         -- Unary plus of `Current'.
 160      do
 161         Result := Current
 162      ensure
 163         Result = Current
 164      end
 165
 166   prefix "-": NUMBER
 167         -- Opposite of `Current'.
 168      deferred
 169      ensure
 170         Result /= Void
 171      end
 172
 173feature {ANY} -- To know more about a NUMBER:
 174   frozen is_integer_8: BOOLEAN
 175         -- Does `Current' value fit on an INTEGER_8?
 176      local
 177         integer_64_number: INTEGER_64_NUMBER
 178      do
 179         if integer_64_number ?:= Current then
 180            integer_64_number ::= Current
 181            Result := integer_64_number.value.fit_integer_8
 182         end
 183      ensure
 184         Result implies is_integer_general_number
 185      end
 186
 187   frozen is_integer_16: BOOLEAN
 188         -- Does `Current' value fit on an INTEGER_16?
 189      local
 190         integer_64_number: INTEGER_64_NUMBER
 191      do
 192         if integer_64_number ?:= Current then
 193            integer_64_number ::= Current
 194            Result := integer_64_number.value.fit_integer_16
 195         end
 196      ensure
 197         Result implies is_integer_general_number
 198      end
 199
 200   frozen is_integer_32: BOOLEAN
 201         -- Does `Current' value fit on an INTEGER?
 202      local
 203         integer_64_number: INTEGER_64_NUMBER
 204      do
 205         if integer_64_number ?:= Current then
 206            integer_64_number ::= Current
 207            Result := integer_64_number.value.fit_integer_32
 208         end
 209      ensure
 210         Result implies is_integer_general_number
 211      end
 212
 213   frozen is_integer_64: BOOLEAN
 214         -- Does `Current' value fit on an INTEGER_64?
 215      local
 216         integer_64_number: INTEGER_64_NUMBER
 217      do
 218         Result := integer_64_number ?:= Current
 219      ensure
 220         Result implies is_integer_general_number
 221      end
 222
 223   frozen is_natural_64: BOOLEAN
 224         -- Does `Current' value fit on a NATURAL_64?
 225      local
 226         big_integer_number: BIG_INTEGER_NUMBER
 227      do
 228         if is_negative then
 229            check
 230               not Result
 231            end
 232         elseif is_integer_64 then
 233            Result := True
 234         else
 235            big_integer_number ::= Current
 236            Result := big_integer_number.is_natural_64_
 237         end
 238      ensure
 239         Result implies is_integer_general_number
 240      end
 241
 242   in_range (lower, upper: NUMBER): BOOLEAN
 243         -- Return True if `Current' is in range [`lower'..`upper']
 244      do
 245         Result := Current >= lower and then Current <= upper
 246      end
 247
 248   compare, three_way_comparison (other: NUMBER): INTEGER
 249         -- Compare `Current' with `other'.
 250         -- `<'  <==> `Result < 0'
 251         -- `>'  <==> `Result > 0'
 252         -- Otherwise `Result = 0'.
 253      do
 254         if Current < other then
 255            Result := -1
 256         elseif other < Current then
 257            Result := 1
 258         end
 259      end
 260
 261   min (other: NUMBER): NUMBER
 262         -- Minimum of `Current' and `other'.
 263      do
 264         if Current < other then
 265            Result := Current
 266         else
 267            Result := other
 268         end
 269      end
 270
 271   max (other: NUMBER): NUMBER
 272         -- Maximum of `Current' and `other'.
 273      do
 274         if other < Current then
 275            Result := Current
 276         else
 277            Result := other
 278         end
 279      end
 280
 281   is_zero: BOOLEAN
 282         -- Is it 0 ?
 283      deferred
 284      ensure
 285         Result = Current @= 0
 286      end
 287
 288   is_one: BOOLEAN
 289         -- Is it 1 ?
 290      deferred
 291      ensure
 292         Result = Current @= 1
 293      end
 294
 295   is_positive: BOOLEAN
 296         -- Is `Current' > 0 ?
 297      deferred
 298      ensure
 299         Result = Current @> 0
 300      end
 301
 302   is_negative: BOOLEAN
 303         -- Is `Current' < 0 ?
 304      deferred
 305      ensure
 306         Result = Current @< 0
 307      end
 308
 309   is_odd: BOOLEAN
 310         -- Is `odd' ?
 311      require
 312         is_integer_general_number
 313      do
 314         Result := (Current @\\ 2).is_one
 315      end
 316
 317   is_even: BOOLEAN
 318         -- Is `even' ?
 319      require
 320         is_integer_general_number
 321      do
 322         Result := (Current @\\ 2).is_zero
 323      end
 324
 325   is_equal (other: NUMBER): BOOLEAN
 326      deferred
 327      end
 328
 329   frozen is_integer_general_number: BOOLEAN
 330      local
 331         integer_general_number: INTEGER_GENERAL_NUMBER
 332      do
 333         Result := integer_general_number ?:= Current
 334      end
 335
 336   frozen is_fraction_general_number: BOOLEAN
 337      local
 338         fraction_general_number: FRACTION_GENERAL_NUMBER
 339      do
 340         Result := fraction_general_number ?:= Current
 341      end
 342
 343   frozen fit_real: BOOLEAN
 344      do
 345         if Current #>= Minimum_real then
 346            Result := Current #<= Maximum_real
 347         end
 348      end
 349
 350feature {ANY} -- Conversions and printing:
 351   frozen to_integer_8: INTEGER_8
 352         -- Conversion of `Current' in an INTEGER_8.
 353      require
 354         is_integer_8
 355      local
 356         integer_64_number: INTEGER_64_NUMBER
 357      do
 358         integer_64_number ::= Current
 359         Result := integer_64_number.value.to_integer_8
 360      end
 361
 362   frozen to_integer_16: INTEGER_16
 363         -- Conversion of `Current' in an INTEGER_16.
 364      require
 365         is_integer_16
 366      local
 367         integer_64_number: INTEGER_64_NUMBER
 368      do
 369         integer_64_number ::= Current
 370         Result := integer_64_number.value.to_integer_16
 371      end
 372
 373   frozen to_integer_32: INTEGER
 374         -- Conversion of `Current' in an INTEGER_32.
 375      require
 376         is_integer_32
 377      local
 378         integer_64_number: INTEGER_64_NUMBER
 379      do
 380         integer_64_number ::= Current
 381         Result := integer_64_number.value.to_integer_32
 382      end
 383
 384   frozen to_integer_64: INTEGER_64
 385         -- Conversion of `Current' in an INTEGER.
 386      require
 387         is_integer_64
 388      local
 389         integer_64_number: INTEGER_64_NUMBER
 390      do
 391         integer_64_number ::= Current
 392         Result := integer_64_number.value
 393      end
 394
 395   frozen to_natural_64: NATURAL_64
 396         -- Conversion of `Current' in a NATURAL_64.
 397      require
 398         is_natural_64
 399      local
 400         integer_64_number: INTEGER_64_NUMBER; big_integer_number: BIG_INTEGER_NUMBER
 401      do
 402         if {INTEGER_64_NUMBER} ?:= Current then
 403            integer_64_number ::= Current
 404            Result := integer_64_number.value.to_natural_64
 405         else
 406            big_integer_number ::= Current
 407            Result := big_integer_number.to_natural_64_
 408         end
 409      end
 410
 411   force_to_real_64: REAL_64
 412         -- Conversion of `Current' in a REAL_64.
 413      require
 414         fit_real
 415      deferred
 416      end
 417
 418   frozen to_string: STRING
 419         -- Convert the NUMBER into a new allocated STRING.
 420         -- Note: see also `append_in' to save memory.
 421      do
 422         string_buffer.clear_count
 423         append_in(string_buffer)
 424         Result := string_buffer.twin
 425      end
 426
 427   frozen to_unicode_string: UNICODE_STRING
 428         -- Convert the NUMBER into a new allocated UNICODE_STRING.
 429         -- Note: see also `append_in_unicode' to save memory.
 430      do
 431         unicode_string_buffer.clear_count
 432         append_in_unicode(unicode_string_buffer)
 433         Result := unicode_string_buffer.twin
 434      end
 435
 436   append_in (buffer: STRING)
 437         -- Append the equivalent of `to_string' at the end of `buffer'.
 438         -- Thus you can save memory because no other STRING is allocated
 439         -- for the job.
 440      require
 441         buffer /= Void
 442      deferred
 443      end
 444
 445   append_in_unicode (buffer: UNICODE_STRING)
 446         -- Append the equivalent of `to_unicode_string' at the end of `buffer'.
 447         -- Thus you can save memory because no other UNICODE_STRING is allocated
 448         -- for the job.
 449      require
 450         buffer /= Void
 451      deferred
 452      end
 453
 454   frozen to_string_format (s: INTEGER): STRING
 455         -- Same as `to_string' but the result is on `s' character and the
 456         -- number is right aligned.
 457         -- Note: see `append_in_format' to save memory.
 458      require
 459         to_string.count <= s
 460      local
 461         i: INTEGER
 462      do
 463         string_buffer.clear_count
 464         append_in(string_buffer)
 465         from
 466            create Result.make(string_buffer.count.max(s))
 467            i := s - string_buffer.count
 468         until
 469            i <= 0
 470         loop
 471            Result.extend(' ')
 472            i := i - 1
 473         end
 474         Result.append(string_buffer)
 475      ensure
 476         Result.count = s
 477      end
 478
 479   frozen to_unicode_string_format (s: INTEGER): UNICODE_STRING
 480         -- Same as `to_unicode_string' but the result is on `s' character and
 481         -- the number is right aligned.
 482         -- Note: see `append_in_unicode_format' to save memory.
 483      require
 484         to_string.count <= s
 485      local
 486         i: INTEGER
 487      do
 488         unicode_string_buffer.clear_count
 489         append_in_unicode(unicode_string_buffer)
 490         from
 491            create Result.make(unicode_string_buffer.count.max(s))
 492            i := s - unicode_string_buffer.count
 493         until
 494            i <= 0
 495         loop
 496            Result.extend(' '.code)
 497            i := i - 1
 498         end
 499         Result.append(unicode_string_buffer)
 500      ensure
 501         Result.count = s
 502      end
 503
 504   frozen append_in_format (str: STRING; s: INTEGER)
 505         -- Append the equivalent of `to_string_format' at the end of
 506         -- `str'. Thus you can save memory because no other
 507         -- STRING is allocated for the job.
 508      require
 509         to_string.count <= s
 510      local
 511         i: INTEGER
 512      do
 513         string_buffer.clear_count
 514         append_in(string_buffer)
 515         from
 516            i := s - string_buffer.count
 517         until
 518            i <= 0
 519         loop
 520            str.extend(' ')
 521            i := i - 1
 522         end
 523         str.append(string_buffer)
 524      ensure
 525         str.count >= old str.count + s
 526      end
 527
 528   frozen append_in_unicode_format (str: UNICODE_STRING; s: INTEGER)
 529         -- Append the equivalent of `to_unicode_string_format' at the end of
 530         -- `str'. Thus you can save memory because no other
 531         -- UNICODE_STRING is allocated for the job.
 532      require
 533         to_string.count <= s
 534      local
 535         i: INTEGER
 536      do
 537         unicode_string_buffer.clear_count
 538         append_in_unicode(unicode_string_buffer)
 539         from
 540            i := s - unicode_string_buffer.count
 541         until
 542            i <= 0
 543         loop
 544            str.extend(' '.code)
 545            i := i - 1
 546         end
 547         str.append(unicode_string_buffer)
 548      ensure
 549         str.count >= old str.count + s
 550      end
 551
 552   frozen to_decimal (digits: INTEGER; all_digits: BOOLEAN): STRING
 553         -- Convert `Current' into its decimal view. A maximum of decimal
 554         -- `digits' places will be used for the decimal part. If the
 555         -- `all_digits' flag is True insignificant digits will be included
 556         -- as well. (See also `decimal_in' to save memory.)
 557      require
 558         non_negative_digits: digits >= 0
 559      do
 560         Result := once "This is a local STRING buffer ...."
 561         Result.clear_count
 562         append_decimal_in(Result, digits, all_digits)
 563         Result := Result.twin
 564      ensure
 565         not Result.is_empty
 566      end
 567
 568   append_decimal_in (buffer: STRING; digits: INTEGER; all_digits: BOOLEAN)
 569         -- Append the equivalent of `to_decimal' at the end of `buffer'. Thus
 570         -- you can save memory because no other STRING is allocated.
 571      require
 572         non_negative_digits: digits >= 0
 573      deferred
 574      end
 575
 576   frozen decimal_digit, digit: CHARACTER
 577         -- Gives the corresponding CHARACTER for range 0..9.
 578      require
 579         to_integer_32.in_range(0, 9)
 580      do
 581         Result := to_integer_32.decimal_digit
 582      ensure
 583         (once "0123456789").has(Result)
 584         Current @= Result.value
 585      end
 586
 587feature {ANY} -- To mimic NUMERIC:
 588   divisible (other: NUMBER): BOOLEAN
 589         -- Is `other' a valid divisor for `Current' ?
 590      do
 591         Result := not other.is_zero
 592      end
 593
 594   one: NUMBER
 595         -- The neutral element of multiplication.
 596      once
 597         create {INTEGER_64_NUMBER} Result.make(1)
 598      ensure
 599         neutral_element:
 600            -- Result is the neutral element of
 601            -- multiplication.
 602      end
 603
 604   zero: NUMBER
 605         -- The neutral element of addition.
 606      once
 607         create {INTEGER_64_NUMBER} Result.make(0)
 608      ensure
 609         neutral_element:
 610            -- Result is the neutral element of
 611            -- addition.
 612      end
 613
 614   frozen sign: INTEGER_8
 615         -- Sign of `Current' (0 or -1 or 1).
 616      do
 617         if is_positive then
 618            Result := 1
 619         elseif is_negative then
 620            Result := -1
 621         end
 622      ensure then
 623         Result = 1 implies is_positive
 624         Result = 0 implies is_zero
 625         Result = -1 implies is_negative
 626      end
 627
 628   sqrt: REAL_64
 629         -- Compute the square routine.
 630      require
 631         fit_real
 632      do
 633         Result := force_to_real_64.sqrt
 634      end
 635
 636   frozen log: REAL_64
 637      require
 638         fit_real
 639      do
 640         Result := force_to_real_64.log
 641      end
 642
 643   abs: NUMBER
 644      do
 645         if is_negative then
 646            Result := -Current
 647         else
 648            Result := Current
 649         end
 650      ensure
 651         not Result.is_negative
 652      end
 653
 654feature {ANY} -- To mix NUMBER and INTEGER_64:
 655   infix "@+" (other: INTEGER_64): NUMBER
 656         -- Sum of `Current' and `other'.
 657      deferred
 658      ensure
 659         Result /= Void
 660      end
 661
 662   infix "@-" (other: INTEGER_64): NUMBER
 663         -- Difference of `Current' and `other'.
 664      do
 665         if other = Minimum_integer_64 then
 666            Result := Current @+ 1
 667            Result := Result @+ Maximum_integer_64
 668         else
 669            Result := Current @+ -other
 670         end
 671      ensure
 672         Result /= Void
 673      end
 674
 675   infix "@*" (other: INTEGER_64): NUMBER
 676      deferred
 677      ensure
 678         Result /= Void
 679      end
 680
 681   infix "@/" (other: INTEGER_64): NUMBER
 682         -- Quotient of `Current' and `other'.
 683      require
 684         other /= 0
 685      deferred
 686      ensure
 687         Result /= Void
 688      end
 689
 690   infix "@//" (other: INTEGER_64): NUMBER
 691         -- Divide `Current' by `other' (Integer division).
 692      require
 693         is_integer_general_number
 694         other /= 0
 695      deferred
 696      ensure
 697         Result.is_integer_general_number
 698      end
 699
 700   infix "@\\" (other: INTEGER_64): NUMBER
 701         -- Remainder of division of `Current' by `other'.
 702      require
 703         is_integer_general_number
 704         other /= 0
 705      deferred
 706      ensure
 707         Result.is_integer_general_number
 708      end
 709
 710   infix "@^" (exp: INTEGER_64): NUMBER
 711      require
 712         is_zero implies exp > 0
 713      local
 714         int: INTEGER_64; other: NUMBER
 715      do
 716         int := exp.abs
 717         inspect
 718            int
 719         when 0 then
 720            create {INTEGER_64_NUMBER} Result.make(1)
 721         when 1 then
 722            Result := Current
 723         else
 724            from
 725               int := int - 1
 726               other := Current
 727               Result := Current
 728            until
 729               int < 2
 730            loop
 731               if int.is_odd then
 732                  Result := Result * other
 733               end
 734               other := other * other -- method sqrt : ^2
 735               int := int #// 2
 736            end
 737            Result := Result * other
 738         end
 739         if exp < 0 then
 740            Result := Result.inverse
 741         end
 742      ensure
 743         Result /= Void
 744         --|*** Bad assertion (Vincent Croizier, 01/06/04) ***
 745         --| Result /= Current implies (exp /= 1 or else not is_zero)
 746      end
 747
 748   infix "@=" (other: INTEGER_64): BOOLEAN
 749         -- Is `Current' equal `other' ?
 750      deferred
 751      end
 752
 753   infix "@<" (other: INTEGER_64): BOOLEAN
 754         -- Is `Current' strictly less than `other'?
 755      deferred
 756      ensure
 757         Result = not (Current @>= other)
 758      end
 759
 760   infix "@<=" (other: INTEGER_64): BOOLEAN
 761         -- Is `Current' less or equal `other'?
 762      deferred
 763      ensure
 764         Result = not (Current @> other)
 765      end
 766
 767   infix "@>" (other: INTEGER_64): BOOLEAN
 768         -- Is `Current' strictly greater than `other'?
 769      deferred
 770      ensure
 771         Result = not (Current @<= other)
 772      end
 773
 774   infix "@>=" (other: INTEGER_64): BOOLEAN
 775         -- Is `Current' greater or equal than `other'?
 776      deferred
 777      ensure
 778         Result = not (Current @< other)
 779      end
 780
 781feature {ANY} -- To mix NUMBER and REAL_64:
 782   infix "#=" (other: REAL_64): BOOLEAN
 783         -- Is `Current' equal `other'?
 784      deferred
 785      end
 786
 787   infix "#<" (other: REAL_64): BOOLEAN
 788         -- Is `Current' strictly less than `other'?
 789      deferred
 790      ensure
 791         Result implies not (Current #>= other)
 792      end
 793
 794   infix "#<=" (other: REAL_64): BOOLEAN
 795         -- Is `Current' less or equal `other'?
 796      deferred
 797      ensure
 798         Result = not (Current #> other)
 799      end
 800
 801   infix "#>" (other: REAL_64): BOOLEAN
 802         -- Is `Current' strictly greater than `other'?
 803      deferred
 804      ensure
 805         Result = not (Current #<= other)
 806      end
 807
 808   infix "#>=" (other: REAL_64): BOOLEAN
 809         -- Is `Current' greater or equal than `other'?
 810      deferred
 811      ensure
 812         Result = not (Current #< other)
 813      end
 814
 815feature {ANY} -- Misc:
 816   out_in_tagged_out_memory, fill_tagged_out_memory
 817      do
 818         append_in(tagged_out_memory)
 819      end
 820
 821   hash_code: INTEGER
 822      deferred
 823      end
 824
 825   inverse: NUMBER
 826      require
 827         divisible(Current)
 828      deferred
 829      ensure
 830         Result /= Void
 831      end
 832
 833   factorial: NUMBER
 834      require
 835         is_integer_general_number
 836         not is_negative
 837      deferred
 838      ensure
 839         Result.is_integer_general_number
 840         Result.is_positive
 841      end
 842
 843   numerator: INTEGER_GENERAL_NUMBER
 844      deferred
 845      end
 846
 847   denominator: INTEGER_GENERAL_NUMBER
 848      deferred
 849      end
 850
 851feature {NUMBER} -- Implementation:
 852   frozen add_with_integer_64_number (other: INTEGER_64_NUMBER): NUMBER
 853      require
 854         other /= Void
 855      do
 856         Result := Current @+ other.to_integer_32
 857      ensure
 858         Result /= Void
 859      end
 860
 861   add_with_big_integer_number (other: BIG_INTEGER_NUMBER): NUMBER
 862      require
 863         other /= Void
 864      deferred
 865      ensure
 866         Result /= Void
 867      end
 868
 869   add_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): NUMBER
 870      require
 871         other /= Void
 872      deferred
 873      ensure
 874         Result /= Void
 875      end
 876
 877   multiply_with_integer_64_number (other: INTEGER_64_NUMBER): NUMBER
 878      require
 879         other /= Void
 880      do
 881         Result := Current @* other.to_integer_32
 882      ensure
 883         Result /= Void
 884      end
 885
 886   multiply_with_big_integer_number (other: BIG_INTEGER_NUMBER): NUMBER
 887      require
 888         other /= Void
 889      deferred
 890      ensure
 891         Result /= Void
 892      end
 893
 894   multiply_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): NUMBER
 895      require
 896         other /= Void
 897      deferred
 898      ensure
 899         Result /= Void
 900      end
 901
 902   greater_with_integer_64_number (other: INTEGER_64_NUMBER): BOOLEAN
 903      require
 904         other /= Void
 905      do
 906         Result := Current @> other.to_integer_32
 907      end
 908
 909   greater_with_big_integer_number (other: BIG_INTEGER_NUMBER): BOOLEAN
 910      require
 911         other /= Void
 912      deferred
 913      end
 914
 915   greater_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): BOOLEAN
 916      require
 917         other /= Void
 918      deferred
 919      end
 920
 921   gcd_with_integer_64_number (other: INTEGER_64_NUMBER): INTEGER_GENERAL_NUMBER
 922      require
 923         other /= Void
 924      deferred
 925      end
 926
 927   gcd_with_big_integer_number (other: BIG_INTEGER_NUMBER): INTEGER_GENERAL_NUMBER
 928      require
 929         other /= Void
 930      deferred
 931      end
 932
 933feature {NUMBER, NUMBER_TOOLS}
 934   max_double: NUMBER
 935      local
 936         nt: NUMBER_TOOLS; tmp: STRING
 937      once
 938         tmp := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
 939         tmp.clear_count
 940         Maximum_real_64.append_in_format(tmp, 0)
 941         Result := nt.from_string(tmp)
 942      end
 943
 944   min_double: NUMBER
 945      local
 946         nt: NUMBER_TOOLS; tmp: STRING
 947      once
 948         tmp := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
 949         tmp.clear_count
 950         Minimum_real_64.append_in_format(tmp, 0)
 951         Result := nt.from_string(tmp)
 952      end
 953
 954feature {NUMBER} -- To implement efficient calculus
 955   mutable_register1: MUTABLE_BIG_INTEGER
 956      once
 957         create Result.from_integer_64(0)
 958      end
 959
 960   mutable_register2: MUTABLE_BIG_INTEGER
 961      once
 962         create Result.from_integer_64(0)
 963      end
 964
 965   mutable_register3: MUTABLE_BIG_INTEGER
 966      once
 967         create Result.from_integer_64(0)
 968      end
 969
 970   mutable_register4: MUTABLE_BIG_INTEGER
 971      once
 972         create Result.from_integer_64(0)
 973      end
 974
 975feature {}
 976   string_buffer: STRING
 977      once
 978         create Result.make(128)
 979      end
 980
 981   unicode_string_buffer: UNICODE_STRING
 982      once
 983         create Result.make(128)
 984      end
 985
 986feature {} -- To create fractions
 987   from_two_integer (n, d: INTEGER_64): NUMBER
 988      require
 989         d /= 0
 990      local
 991         n_number, d_number: INTEGER_64_NUMBER
 992      do
 993         create n_number.make(n)
 994         create d_number.make(d)
 995         Result := from_two_integer_general_number(n_number, d_number)
 996      ensure
 997         Result @* d @= n
 998      end
 999
1000   from_two_integer_general_number (n, d: INTEGER_GENERAL_NUMBER): NUMBER
1001      require
1002         n /= Void
1003         d /= Void
1004         not d.is_zero
1005      do
1006         if (n \\ d).is_zero then
1007            Result := n // d
1008         else
1009            create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make(n, d)
1010         end
1011      ensure
1012         n.is_equal(Result * d)
1013      end
1014
1015   from_integer_and_integer_general_number (n: INTEGER_64; d: INTEGER_GENERAL_NUMBER): NUMBER
1016      require
1017         d /= Void
1018         not d.is_zero
1019      local
1020         n_number: INTEGER_64_NUMBER
1021      do
1022         create n_number.make(n)
1023         Result := from_two_integer_general_number(n_number, d)
1024      end
1025
1026   from_integer_general_number_and_integer (n: INTEGER_GENERAL_NUMBER; d: INTEGER_64): NUMBER
1027      require
1028         n /= Void
1029         d /= 0
1030      local
1031         d_number: INTEGER_64_NUMBER
1032      do
1033         create d_number.make(d)
1034         Result := from_two_integer_general_number(n, d_number)
1035      end
1036
1037invariant
1038   denominator.is_positive
1039   is_integer_general_number implies denominator.is_one
1040   not is_integer_general_number implies numerator.gcd(denominator) @= 1
1041
1042end -- class NUMBER
1043--
1044-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
1045--
1046-- Permission is hereby granted, free of charge, to any person obtaining a copy
1047-- of this software and associated documentation files (the "Software"), to deal
1048-- in the Software without restriction, including without limitation the rights
1049-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1050-- copies of the Software, and to permit persons to whom the Software is
1051-- furnished to do so, subject to the following conditions:
1052--
1053-- The above copyright notice and this permission notice shall be included in
1054-- all copies or substantial portions of the Software.
1055--
1056-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1057-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1058-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1059-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1060-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1061-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1062-- THE SOFTWARE.