diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 5034c322..41a8fda5 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -42,6 +42,9 @@ jobs: - { os: windows-latest , ruby: "3.1" } - { os: windows-latest , ruby: "3.2" } + env: + BUNDLE_WITHOUT: sig + steps: - uses: actions/checkout@v6.0.2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 411d67d0..19da16bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,7 @@ jobs: env: BIGDECIMAL_USE_DECDIG_UINT16_T: ${{ matrix.decdig_bits == 16 }} BIGDECIMAL_USE_VP_TEST_METHODS: true + BUNDLE_WITHOUT: sig steps: - uses: actions/checkout@v6.0.2 diff --git a/.github/workflows/jruby_test.yml b/.github/workflows/jruby_test.yml index ffabbe6f..a75883b2 100644 --- a/.github/workflows/jruby_test.yml +++ b/.github/workflows/jruby_test.yml @@ -14,6 +14,10 @@ jobs: host: name: ${{ matrix.ruby }} runs-on: ubuntu-latest + + env: + BUNDLE_WITHOUT: sig + strategy: fail-fast: false matrix: diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index d108387a..959f92ea 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -17,6 +17,9 @@ jobs: name: rubygems.org url: https://rubygems.org/gems/bigdecimal + env: + BUNDLE_WITHOUT: sig + permissions: contents: write id-token: write diff --git a/.github/workflows/sig.yml b/.github/workflows/sig.yml new file mode 100644 index 00000000..7897bf01 --- /dev/null +++ b/.github/workflows/sig.yml @@ -0,0 +1,26 @@ +name: sig + +on: + push: + branches: + - master + pull_request: + types: + - opened + - synchronize + - reopened + +jobs: + sig: + runs-on: "ubuntu-latest" + env: + BUNDLE_WITH: sig + steps: + - uses: actions/checkout@v6.0.2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + ruby-version: ruby + - name: Run RBS test + run: bundle exec rake rbs:test diff --git a/Gemfile b/Gemfile index b0c551f7..b0ef9eac 100644 --- a/Gemfile +++ b/Gemfile @@ -10,3 +10,8 @@ gem "minitest", "< 5.0.0" gem "irb" gem "test-unit" gem "test-unit-ruby-core" + +group :sig do + gem "rbs" + gem "rdoc" +end diff --git a/Rakefile b/Rakefile index 314f83aa..6590a91d 100644 --- a/Rakefile +++ b/Rakefile @@ -77,3 +77,22 @@ namespace :dev do end end end + +namespace :rbs do + Rake::TestTask.new(test: :compile) do |t| + t.libs << 'test_sig' + t.ruby_opts << '-rtest_helper' + t.test_files = FileList['test_sig/test_big_*.rb'] + t.warning = true + end + + desc 'Update RBS comments' + task :annotate do + require "tmpdir" + + Dir.mktmpdir do |tmpdir| + sh("rdoc --ri --output #{tmpdir}/doc --root=. lib") + sh("rbs annotate --no-system --no-gems --no-site --no-home -d #{tmpdir}/doc sig") + end + end +end diff --git a/bigdecimal.gemspec b/bigdecimal.gemspec index 774fd223..8f279141 100644 --- a/bigdecimal.gemspec +++ b/bigdecimal.gemspec @@ -34,6 +34,8 @@ Gem::Specification.new do |s| sample/linear.rb sample/nlsolve.rb sample/pi.rb + sig/big_decimal.rbs + sig/big_math.rbs ] if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby' s.platform = 'java' diff --git a/sig/big_decimal.rbs b/sig/big_decimal.rbs new file mode 100644 index 00000000..a0d0e80c --- /dev/null +++ b/sig/big_decimal.rbs @@ -0,0 +1,1502 @@ +class BigDecimal < Numeric + # BigDecimal::ROUND_MODE + type round_mode = 256 + type round_mode_integer = 1 | 2 | 3 | 4 | 5 | 6 | 7 + type round_mode_symbol = :up | :down | :half_up | :half_down | :half_even | :ceiling | :floor | :truncate | :banker | :default + + # + # Internal method used to provide marshalling support. See the Marshal module. + # + def self._load: (String) -> BigDecimal + + # + # Returns the number of digits a Float object is allowed to have; the result is + # system-dependent: + # + # BigDecimal.double_fig # => 16 + # + def self.double_fig: () -> Integer + + # + # + def self.interpret_loosely: (string) -> BigDecimal + + # + # Limit the number of significant digits in newly created BigDecimal numbers to + # the specified value. Rounding is performed as necessary, as specified by + # BigDecimal.mode. + # + # A limit of 0, the default, means no upper limit. + # + # The limit specified by this method takes less priority over any limit + # specified to instance methods such as ceil, floor, truncate, or round. + # + def self.limit: (?Integer? digits) -> Integer + + # + # Returns an integer representing the mode settings for exception handling and + # rounding. + # + # These modes control exception handling: + # + # * BigDecimal::EXCEPTION_NaN. + # * BigDecimal::EXCEPTION_INFINITY. + # * BigDecimal::EXCEPTION_UNDERFLOW. + # * BigDecimal::EXCEPTION_OVERFLOW. + # * BigDecimal::EXCEPTION_ZERODIVIDE. + # * BigDecimal::EXCEPTION_ALL. + # + # Values for `setting` for exception handling: + # + # * `true`: sets the given `mode` to `true`. + # * `false`: sets the given `mode` to `false`. + # * `nil`: does not modify the mode settings. + # + # You can use method BigDecimal.save_exception_mode to temporarily change, and + # then automatically restore, exception modes. + # + # For clarity, some examples below begin by setting all exception modes to + # `false`. + # + # This mode controls the way rounding is to be performed: + # + # * BigDecimal::ROUND_MODE + # + # You can use method BigDecimal.save_rounding_mode to temporarily change, and + # then automatically restore, the rounding mode. + # + # **NaNs** + # + # Mode BigDecimal::EXCEPTION_NaN controls behavior when a BigDecimal NaN is + # created. + # + # Settings: + # + # * `false` (default): Returns `BigDecimal('NaN')`. + # * `true`: Raises FloatDomainError. + # + # Examples: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # BigDecimal('NaN') # => NaN + # BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2 + # BigDecimal('NaN') # Raises FloatDomainError + # + # **Infinities** + # + # Mode BigDecimal::EXCEPTION_INFINITY controls behavior when a BigDecimal + # Infinity or -Infinity is created. Settings: + # + # * `false` (default): Returns `BigDecimal('Infinity')` or + # `BigDecimal('-Infinity')`. + # * `true`: Raises FloatDomainError. + # + # Examples: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # BigDecimal('Infinity') # => Infinity + # BigDecimal('-Infinity') # => -Infinity + # BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1 + # BigDecimal('Infinity') # Raises FloatDomainError + # BigDecimal('-Infinity') # Raises FloatDomainError + # + # **Underflow** + # + # Mode BigDecimal::EXCEPTION_UNDERFLOW controls behavior when a BigDecimal + # underflow occurs. Settings: + # + # * `false` (default): Returns `BigDecimal('0')` or `BigDecimal('-Infinity')`. + # * `true`: Raises FloatDomainError. + # + # Examples: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # def flow_under + # x = BigDecimal('0.1') + # 100.times { x *= x } + # end + # flow_under # => 100 + # BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4 + # flow_under # Raises FloatDomainError + # + # **Overflow** + # + # Mode BigDecimal::EXCEPTION_OVERFLOW controls behavior when a BigDecimal + # overflow occurs. Settings: + # + # * `false` (default): Returns `BigDecimal('Infinity')` or + # `BigDecimal('-Infinity')`. + # * `true`: Raises FloatDomainError. + # + # Examples: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # def flow_over + # x = BigDecimal('10') + # 100.times { x *= x } + # end + # flow_over # => 100 + # BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1 + # flow_over # Raises FloatDomainError + # + # **Zero Division** + # + # Mode BigDecimal::EXCEPTION_ZERODIVIDE controls behavior when a zero-division + # occurs. Settings: + # + # * `false` (default): Returns `BigDecimal('Infinity')` or + # `BigDecimal('-Infinity')`. + # * `true`: Raises FloatDomainError. + # + # Examples: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # one = BigDecimal('1') + # zero = BigDecimal('0') + # one / zero # => Infinity + # BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16 + # one / zero # Raises FloatDomainError + # + # **All Exceptions** + # + # Mode BigDecimal::EXCEPTION_ALL controls all of the above: + # + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 + # BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23 + # + # **Rounding** + # + # Mode BigDecimal::ROUND_MODE controls the way rounding is to be performed; its + # `setting` values are: + # + # * `ROUND_UP`: Round away from zero. Aliased as `:up`. + # * `ROUND_DOWN`: Round toward zero. Aliased as `:down` and `:truncate`. + # * `ROUND_HALF_UP`: Round toward the nearest neighbor; if the neighbors are + # equidistant, round away from zero. Aliased as `:half_up` and `:default`. + # * `ROUND_HALF_DOWN`: Round toward the nearest neighbor; if the neighbors are + # equidistant, round toward zero. Aliased as `:half_down`. + # * `ROUND_HALF_EVEN` (Banker's rounding): Round toward the nearest neighbor; + # if the neighbors are equidistant, round toward the even neighbor. Aliased + # as `:half_even` and `:banker`. + # * `ROUND_CEILING`: Round toward positive infinity. Aliased as `:ceiling` and + # `:ceil`. + # * `ROUND_FLOOR`: Round toward negative infinity. Aliased as `:floor:`. + # + def self.mode: (round_mode, ?(round_mode_integer | round_mode_symbol)) -> Integer + | (Integer exception_mode, ?bool? setting) -> Integer + + # + # Execute the provided block, but preserve the exception mode + # + # BigDecimal.save_exception_mode do + # BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) + # BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) + # + # BigDecimal(BigDecimal('Infinity')) + # BigDecimal(BigDecimal('-Infinity')) + # BigDecimal(BigDecimal('NaN')) + # end + # + # For use with the BigDecimal::EXCEPTION_* + # + # See BigDecimal.mode + # + def self.save_exception_mode: () { (?nil) -> void } -> void + + # + # Execute the provided block, but preserve the precision limit + # + # BigDecimal.limit(100) + # puts BigDecimal.limit + # BigDecimal.save_limit do + # BigDecimal.limit(200) + # puts BigDecimal.limit + # end + # puts BigDecimal.limit + # + def self.save_limit: () { (?nil) -> void } -> void + + # + # Execute the provided block, but preserve the rounding mode + # + # BigDecimal.save_rounding_mode do + # BigDecimal.mode(BigDecimal::ROUND_MODE, :up) + # puts BigDecimal.mode(BigDecimal::ROUND_MODE) + # end + # + # For use with the BigDecimal::ROUND_* + # + # See BigDecimal.mode + # + def self.save_rounding_mode: () { (?nil) -> void } -> void + + # + # Returns the modulus from dividing by b. + # + # See BigDecimal#divmod. + # + def %: (real | BigDecimal) -> BigDecimal + + # + # + def *: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns the BigDecimal value of `self` raised to power `other`: + # + # b = BigDecimal('3.14') + # b ** 2 # => 0.98596e1 + # b ** 2.0 # => 0.98596e1 + # b ** Rational(2, 1) # => 0.98596e1 + # + # Related: BigDecimal#power. + # + def **: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns the BigDecimal sum of `self` and `value`: + # + # b = BigDecimal('111111.111') # => 0.111111111e6 + # b + 2 # => 0.111113111e6 + # b + 2.0 # => 0.111113111e6 + # b + Rational(2, 1) # => 0.111113111e6 + # b + Complex(2, 0) # => (0.111113111e6+0i) + # + # See the [Note About + # Precision](BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision). + # + def +: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns `self`: + # + # +BigDecimal(5) # => 0.5e1 + # +BigDecimal(-5) # => -0.5e1 + # + def +@: () -> BigDecimal + + # + # Returns the BigDecimal difference of `self` and `value`: + # + # b = BigDecimal('333333.333') # => 0.333333333e6 + # b - 2 # => 0.333331333e6 + # b - 2.0 # => 0.333331333e6 + # b - Rational(2, 1) # => 0.333331333e6 + # b - Complex(2, 0) # => (0.333331333e6+0i) + # + # See the [Note About + # Precision](BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision). + # + def -: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns the BigDecimal negation of self: + # + # b0 = BigDecimal('1.5') + # b1 = -b0 # => -0.15e1 + # b2 = -b1 # => 0.15e1 + # + def -@: () -> BigDecimal + + # + # Divide by the specified value. + # + # The result precision will be the precision of the larger operand, but its + # minimum is 2*Float::DIG. + # + # See BigDecimal#div. See BigDecimal#quo. + # + def /: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns `true` if `self` is less than `other`, `false` otherwise: + # + # b = BigDecimal('1.5') # => 0.15e1 + # b < 2 # => true + # b < 2.0 # => true + # b < Rational(2, 1) # => true + # b < 1.5 # => false + # + # Raises an exception if the comparison cannot be made. + # + def <: (real | BigDecimal) -> bool + + # + # Returns `true` if `self` is less or equal to than `other`, `false` otherwise: + # + # b = BigDecimal('1.5') # => 0.15e1 + # b <= 2 # => true + # b <= 2.0 # => true + # b <= Rational(2, 1) # => true + # b <= 1.5 # => true + # b < 1 # => false + # + # Raises an exception if the comparison cannot be made. + # + def <=: (real | BigDecimal) -> bool + + # + # The comparison operator. a <=> b is 0 if a == b, 1 if a > b, -1 if a < b. + # + def <=>: (untyped) -> Integer? + + # + # Tests for value equality; returns true if the values are equal. + # + # The == and === operators and the eql? method have the same implementation for + # BigDecimal. + # + # Values may be coerced to perform the comparison: + # + # BigDecimal('1.0') == 1.0 #=> true + # + def ==: (untyped) -> bool + + # + # Tests for value equality; returns true if the values are equal. + # + # The == and === operators and the eql? method have the same implementation for + # BigDecimal. + # + # Values may be coerced to perform the comparison: + # + # BigDecimal('1.0') == 1.0 #=> true + # + def ===: (untyped) -> bool + + # + # Returns `true` if `self` is greater than `other`, `false` otherwise: + # + # b = BigDecimal('1.5') + # b > 1 # => true + # b > 1.0 # => true + # b > Rational(1, 1) # => true + # b > 2 # => false + # + # Raises an exception if the comparison cannot be made. + # + def >: (real | BigDecimal) -> bool + + # + # Returns `true` if `self` is greater than or equal to `other`, `false` + # otherwise: + # + # b = BigDecimal('1.5') + # b >= 1 # => true + # b >= 1.0 # => true + # b >= Rational(1, 1) # => true + # b >= 1.5 # => true + # b > 2 # => false + # + # Raises an exception if the comparison cannot be made. + # + def >=: (real | BigDecimal) -> bool + + # + # Returns a string representing the marshalling of `self`. See module Marshal. + # + # inf = BigDecimal('Infinity') # => Infinity + # dumped = inf._dump # => "9:Infinity" + # BigDecimal._load(dumped) # => Infinity + # + def _dump: (?untyped) -> String + + # + # Returns the BigDecimal absolute value of `self`: + # + # BigDecimal('5').abs # => 0.5e1 + # BigDecimal('-3').abs # => 0.3e1 + # + def abs: () -> BigDecimal + + # + # Returns the BigDecimal sum of `self` and `value` with a precision of `ndigits` + # decimal digits. + # + # When `ndigits` is less than the number of significant digits in the sum, the + # sum is rounded to that number of digits, according to the current rounding + # mode; see BigDecimal.mode. + # + # Examples: + # + # # Set the rounding mode. + # BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) + # b = BigDecimal('111111.111') + # b.add(1, 0) # => 0.111112111e6 + # b.add(1, 3) # => 0.111e6 + # b.add(1, 6) # => 0.111112e6 + # b.add(1, 15) # => 0.111112111e6 + # b.add(1.0, 15) # => 0.111112111e6 + # b.add(Rational(1, 1), 15) # => 0.111112111e6 + # + def add: (real | BigDecimal value, Integer digits) -> BigDecimal + + # + # Return the smallest integer greater than or equal to the value, as a + # BigDecimal. + # + # BigDecimal('3.14159').ceil #=> 4 + # BigDecimal('-9.1').ceil #=> -9 + # + # If n is specified and positive, the fractional part of the result has no more + # than that many digits. + # + # If n is specified and negative, at least that many digits to the left of the + # decimal point will be 0 in the result. + # + # BigDecimal('3.14159').ceil(3) #=> 3.142 + # BigDecimal('13345.234').ceil(-2) #=> 13400.0 + # + def ceil: () -> Integer + | (int n) -> BigDecimal + + # + # + def clone: () -> self + + # + # The coerce method provides support for Ruby type coercion. It is not enabled + # by default. + # + # This means that binary operations like + * / or - can often be performed on a + # BigDecimal and an object of another type, if the other object can be coerced + # into a BigDecimal value. + # + # e.g. + # a = BigDecimal("1.0") + # b = a / 2.0 #=> 0.5 + # + # Note that coercing a String to a BigDecimal is not supported by default; it + # requires a special compile-time option when building Ruby. + # + def coerce: (Numeric) -> [ BigDecimal, BigDecimal ] + + # + # Divide by the specified value. + # + # digits + # : If specified and less than the number of significant digits of the result, + # the result is rounded to that number of digits, according to + # BigDecimal.mode. + # + # If digits is 0, the result is the same as for the / operator or #quo. + # + # If digits is not specified, the result is an integer, by analogy with + # Float#div; see also BigDecimal#divmod. + # + # + # See BigDecimal#/. See BigDecimal#quo. + # + # Examples: + # + # a = BigDecimal("4") + # b = BigDecimal("3") + # + # a.div(b, 3) # => 0.133e1 + # + # a.div(b, 0) # => 0.1333333333333333333e1 + # a / b # => 0.1333333333333333333e1 + # a.quo(b) # => 0.1333333333333333333e1 + # + # a.div(b) # => 1 + # + def div: (real | BigDecimal value) -> Integer + | (real | BigDecimal value, int digits) -> BigDecimal + + # + # Divides by the specified value, and returns the quotient and modulus as + # BigDecimal numbers. The quotient is rounded towards negative infinity. + # + # For example: + # + # require 'bigdecimal' + # + # a = BigDecimal("42") + # b = BigDecimal("9") + # + # q, m = a.divmod(b) + # + # c = q * b + m + # + # a == c #=> true + # + # The quotient q is (a/b).floor, and the modulus is the amount that must be + # added to q * b to get a. + # + def divmod: (real | BigDecimal) -> [ Integer, BigDecimal ] + + # + # + def dup: () -> self + + # + # Tests for value equality; returns true if the values are equal. + # + # The == and === operators and the eql? method have the same implementation for + # BigDecimal. + # + # Values may be coerced to perform the comparison: + # + # BigDecimal('1.0') == 1.0 #=> true + # + def eql?: (untyped) -> bool + + # + # Returns the exponent of the BigDecimal number, as an Integer. + # + # If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string of + # digits with no leading zeros, then n is the exponent. + # + def exponent: () -> Integer + + # + # Returns True if the value is finite (not NaN or infinite). + # + def finite?: () -> bool + + # + # Return the integer part of the number, as a BigDecimal. + # + def fix: () -> BigDecimal + + # + # Return the largest integer less than or equal to the value, as a BigDecimal. + # + # BigDecimal('3.14159').floor #=> 3 + # BigDecimal('-9.1').floor #=> -10 + # + # If n is specified and positive, the fractional part of the result has no more + # than that many digits. + # + # If n is specified and negative, at least that many digits to the left of the + # decimal point will be 0 in the result. + # + # BigDecimal('3.14159').floor(3) #=> 3.141 + # BigDecimal('13345.234').floor(-2) #=> 13300.0 + # + def floor: () -> Integer + | (int n) -> BigDecimal + + # + # Return the fractional part of the number, as a BigDecimal. + # + def frac: () -> BigDecimal + + # + # Returns the integer hash value for `self`. + # + # Two instances of BigDecimal have the same hash value if and only if they have + # equal: + # + # * Sign. + # * Fractional part. + # * Exponent. + # + def hash: () -> Integer + + # + # Returns nil, -1, or +1 depending on whether the value is finite, -Infinity, or + # +Infinity. + # + def infinite?: () -> Integer? + + # + # Returns a string representation of self. + # + # BigDecimal("1234.5678").inspect + # #=> "0.12345678e4" + # + def inspect: () -> String + + # + # Returns the modulus from dividing by b. + # + # See BigDecimal#divmod. + # + def modulo: (real | BigDecimal b) -> BigDecimal + + # + # Returns the BigDecimal product of `self` and `value` with a precision of + # `ndigits` decimal digits. + # + # When `ndigits` is less than the number of significant digits in the sum, the + # sum is rounded to that number of digits, according to the current rounding + # mode; see BigDecimal.mode. + # + # Examples: + # + # # Set the rounding mode. + # BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) + # b = BigDecimal('555555.555') + # b.mult(3, 0) # => 0.1666666665e7 + # b.mult(3, 3) # => 0.167e7 + # b.mult(3, 6) # => 0.166667e7 + # b.mult(3, 15) # => 0.1666666665e7 + # b.mult(3.0, 0) # => 0.1666666665e7 + # b.mult(Rational(3, 1), 0) # => 0.1666666665e7 + # b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i) + # + def mult: (real | BigDecimal value, int digits) -> BigDecimal + + # + # Returns True if the value is Not a Number. + # + def nan?: () -> bool + + # + # Returns self if the value is non-zero, nil otherwise. + # + def nonzero?: () -> self? + + # + # Returns the value raised to the power of n. + # + # Also available as the operator **. + # + def power: (real | BigDecimal n, ?int prec) -> BigDecimal + + # + # Divide by the specified value. + # + # digits + # : If specified and less than the number of significant digits of the result, + # the result is rounded to the given number of digits, according to the + # rounding mode indicated by BigDecimal.mode. + # + # If digits is 0 or omitted, the result is the same as for the / operator. + # + # + # See BigDecimal#/. See BigDecimal#div. + # + def quo: (real | BigDecimal) -> BigDecimal + | (Complex) -> Complex + + # + # Returns the remainder from dividing by the value. + # + # x.remainder(y) means x-y*(x/y).truncate + # + def remainder: (real | BigDecimal) -> BigDecimal + + # + # Round to the nearest integer (by default), returning the result as a + # BigDecimal if n is specified, or as an Integer if it isn't. + # + # BigDecimal('3.14159').round #=> 3 + # BigDecimal('8.7').round #=> 9 + # BigDecimal('-9.9').round #=> -10 + # + # BigDecimal('3.14159').round(2).class.name #=> "BigDecimal" + # BigDecimal('3.14159').round.class.name #=> "Integer" + # + # If n is specified and positive, the fractional part of the result has no more + # than that many digits. + # + # If n is specified and negative, at least that many digits to the left of the + # decimal point will be 0 in the result, and return value will be an Integer. + # + # BigDecimal('3.14159').round(3) #=> 3.142 + # BigDecimal('13345.234').round(-2) #=> 13300 + # + # The value of the optional mode argument can be used to determine how rounding + # is performed; see BigDecimal.mode. + # + def round: () -> Integer + | (int n) -> (Integer | BigDecimal) + | (int n, round_mode_integer | round_mode_symbol) -> BigDecimal + | (?int n, half: :up | :down | :even) -> BigDecimal + + # + # Returns the sign of the value. + # + # Returns a positive value if > 0, a negative value if < 0. It behaves the same + # with zeros - it returns a positive value for a positive zero (BigDecimal('0')) + # and a negative value for a negative zero (BigDecimal('-0')). + # + # The specific value returned indicates the type and sign of the BigDecimal, as + # follows: + # + # BigDecimal::SIGN_NaN + # : value is Not a Number + # + # BigDecimal::SIGN_POSITIVE_ZERO + # : value is +0 + # + # BigDecimal::SIGN_NEGATIVE_ZERO + # : value is -0 + # + # BigDecimal::SIGN_POSITIVE_INFINITE + # : value is +Infinity + # + # BigDecimal::SIGN_NEGATIVE_INFINITE + # : value is -Infinity + # + # BigDecimal::SIGN_POSITIVE_FINITE + # : value is positive + # + # BigDecimal::SIGN_NEGATIVE_FINITE + # : value is negative + # + def sign: () -> Integer + + # + # Splits a BigDecimal number into four parts, returned as an array of values. + # + # The first value represents the sign of the BigDecimal, and is -1 or 1, or 0 if + # the BigDecimal is Not a Number. + # + # The second value is a string representing the significant digits of the + # BigDecimal, with no leading zeros. + # + # The third value is the base used for arithmetic (currently always 10) as an + # Integer. + # + # The fourth value is an Integer exponent. + # + # If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the + # string of significant digits with no leading zeros, and n is the exponent. + # + # From these values, you can translate a BigDecimal to a float as follows: + # + # sign, significant_digits, base, exponent = a.split + # f = sign * "0.#{significant_digits}".to_f * (base ** exponent) + # + # (Note that the to_f method is provided as a more convenient way to translate a + # BigDecimal to a Float.) + # + def split: () -> [ Integer, String, Integer, Integer ] + + # + # Returns the square root of the value. + # + # Result has at least prec significant digits. + # + def sqrt: (int n) -> BigDecimal + + # + # Subtract the specified value. + # + # e.g. + # c = a.sub(b,n) + # + # digits + # : If specified and less than the number of significant digits of the result, + # the result is rounded to that number of digits, according to + # BigDecimal.mode. + # + def sub: (real | BigDecimal value, int digits) -> BigDecimal + + # + # Returns a new Float object having approximately the same value as the + # BigDecimal number. Normal accuracy limits and built-in errors of binary Float + # arithmetic apply. + # + def to_f: () -> Float + + # + # Returns the value as an Integer. + # + # If the BigDecimal is infinity or NaN, raises FloatDomainError. + # + def to_i: () -> Integer + + # + # Returns the value as an Integer. + # + # If the BigDecimal is infinity or NaN, raises FloatDomainError. + # + def to_int: () -> Integer + + # + # Converts a BigDecimal to a Rational. + # + def to_r: () -> Rational + + # + # Converts the value to a string. + # + # The default format looks like 0.xxxxEnn. + # + # The optional parameter s consists of either an integer; or an optional '+' or + # ' ', followed by an optional number, followed by an optional 'E' or 'F'. + # + # If there is a '+' at the start of s, positive values are returned with a + # leading '+'. + # + # A space at the start of s returns positive values with a leading space. + # + # If s contains a number, a space is inserted after each group of that many + # digits, starting from '.' and counting outwards. + # + # If s ends with an 'E', engineering notation (0.xxxxEnn) is used. + # + # If s ends with an 'F', conventional floating point notation is used. + # + # Examples: + # + # BigDecimal('-1234567890123.45678901234567890').to_s('5F') + # #=> '-123 45678 90123.45678 90123 45678 9' + # + # BigDecimal('1234567890123.45678901234567890').to_s('+8F') + # #=> '+12345 67890123.45678901 23456789' + # + # BigDecimal('1234567890123.45678901234567890').to_s(' F') + # #=> ' 1234567890123.4567890123456789' + # + def to_s: (?String | int s) -> String + + # + # Truncate to the nearest integer (by default), returning the result as a + # BigDecimal. + # + # BigDecimal('3.14159').truncate #=> 3 + # BigDecimal('8.7').truncate #=> 8 + # BigDecimal('-9.9').truncate #=> -9 + # + # If n is specified and positive, the fractional part of the result has no more + # than that many digits. + # + # If n is specified and negative, at least that many digits to the left of the + # decimal point will be 0 in the result. + # + # BigDecimal('3.14159').truncate(3) #=> 3.141 + # BigDecimal('13345.234').truncate(-2) #=> 13300.0 + # + def truncate: () -> Integer + | (int n) -> BigDecimal + + # + # Returns True if the value is zero. + # + def zero?: () -> bool + + private + + def initialize_copy: (self) -> self + + # + # Base value used in internal calculations. On a 32 bit system, BASE is 10000, + # indicating that calculation is done in groups of 4 digits. (If it were larger, + # BASE**2 wouldn't fit in 32 bits, so you couldn't guarantee that two groups + # could always be multiplied together without overflow.) + # + BASE: Integer + + # + # Determines whether overflow, underflow or zero divide result in an exception + # being thrown. See BigDecimal.mode. + # + EXCEPTION_ALL: Integer + + # + # Determines what happens when the result of a computation is infinity. See + # BigDecimal.mode. + # + EXCEPTION_INFINITY: Integer + + # + # Determines what happens when the result of a computation is not a number + # (NaN). See BigDecimal.mode. + # + EXCEPTION_NaN: Integer + + # + # Determines what happens when the result of a computation is an overflow (a + # result too large to be represented). See BigDecimal.mode. + # + EXCEPTION_OVERFLOW: Integer + + # + # Determines what happens when the result of a computation is an underflow (a + # result too small to be represented). See BigDecimal.mode. + # + EXCEPTION_UNDERFLOW: Integer + + # + # Determines what happens when a division by zero is performed. See + # BigDecimal.mode. + # + EXCEPTION_ZERODIVIDE: Integer + + # + # Special value constants + # + INFINITY: BigDecimal + + NAN: BigDecimal + + # + # Round towards +Infinity. See BigDecimal.mode. + # + ROUND_CEILING: Integer + + # + # Indicates that values should be rounded towards zero. See BigDecimal.mode. + # + ROUND_DOWN: Integer + + # + # Round towards -Infinity. See BigDecimal.mode. + # + ROUND_FLOOR: Integer + + # + # Indicates that digits >= 6 should be rounded up, others rounded down. See + # BigDecimal.mode. + # + ROUND_HALF_DOWN: Integer + + # + # Round towards the even neighbor. See BigDecimal.mode. + # + ROUND_HALF_EVEN: Integer + + # + # Indicates that digits >= 5 should be rounded up, others rounded down. See + # BigDecimal.mode. + # + ROUND_HALF_UP: Integer + + # + # Determines what happens when a result must be rounded in order to fit in the + # appropriate number of significant digits. See BigDecimal.mode. + # + ROUND_MODE: round_mode + + # + # Indicates that values should be rounded away from zero. See BigDecimal.mode. + # + ROUND_UP: Integer + + # + # Indicates that a value is negative and finite. See BigDecimal.sign. + # + SIGN_NEGATIVE_FINITE: Integer + + # + # Indicates that a value is negative and infinite. See BigDecimal.sign. + # + SIGN_NEGATIVE_INFINITE: Integer + + # + # Indicates that a value is -0. See BigDecimal.sign. + # + SIGN_NEGATIVE_ZERO: Integer + + # + # Indicates that a value is not a number. See BigDecimal.sign. + # + SIGN_NaN: Integer + + # + # Indicates that a value is positive and finite. See BigDecimal.sign. + # + SIGN_POSITIVE_FINITE: Integer + + # + # Indicates that a value is positive and infinite. See BigDecimal.sign. + # + SIGN_POSITIVE_INFINITE: Integer + + # + # Indicates that a value is +0. See BigDecimal.sign. + # + SIGN_POSITIVE_ZERO: Integer + + # + # The version of bigdecimal library + # + VERSION: String +end + +%a{annotate:rdoc:skip} +module Kernel + private + + # + # Returns the BigDecimal converted from `value` with a precision of `ndigits` + # decimal digits. + # + # When `ndigits` is less than the number of significant digits in the value, the + # result is rounded to that number of digits, according to the current rounding + # mode; see BigDecimal.mode. + # + # When `ndigits` is 0, the number of digits to correctly represent a float + # number is determined automatically. + # + # Returns `value` converted to a BigDecimal, depending on the type of `value`: + # + # * Integer, Float, Rational, Complex, or BigDecimal: converted directly: + # + # # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given. + # BigDecimal(2) # => 0.2e1 + # BigDecimal(Complex(2, 0)) # => 0.2e1 + # BigDecimal(BigDecimal(2)) # => 0.2e1 + # # Float or Rational value requires ndigits. + # BigDecimal(2.0, 0) # => 0.2e1 + # BigDecimal(Rational(2, 1), 0) # => 0.2e1 + # + # * String: converted by parsing if it contains an integer or floating-point + # literal; leading and trailing whitespace is ignored: + # + # # String does not require ndigits; ignored if given. + # BigDecimal('2') # => 0.2e1 + # BigDecimal('2.0') # => 0.2e1 + # BigDecimal('0.2e1') # => 0.2e1 + # BigDecimal(' 2.0 ') # => 0.2e1 + # + # * Other type that responds to method `:to_str`: first converted to a string, + # then converted to a BigDecimal, as above. + # + # * Other type: + # + # * Raises an exception if keyword argument `exception` is `true`. + # * Returns `nil` if keyword argument `exception` is `false`. + # + # Raises an exception if `value` evaluates to a Float and `digits` is larger + # than Float::DIG + 1. + # + def self?.BigDecimal: (real | string | BigDecimal initial, ?int digits, ?exception: bool) -> BigDecimal +end + +%a{annotate:rdoc:skip} +class Integer + # + # Performs division; for integer `numeric`, truncates the result to an integer: + # + # 4 / 3 # => 1 + # 4 / -3 # => -2 + # -4 / 3 # => -2 + # -4 / -3 # => 1 + # + # For other +numeric+, returns non-integer result: + # + # 4 / 3.0 # => 1.3333333333333333 + # 4 / Rational(3, 1) # => (4/3) + # 4 / Complex(3, 0) # => ((4/3)+0i) + # + def /: (BigDecimal) -> BigDecimal + | ... + + # + # Performs multiplication: + # + # 4 * 2 # => 8 + # 4 * -2 # => -8 + # -4 * 2 # => -8 + # 4 * 2.0 # => 8.0 + # 4 * Rational(1, 3) # => (4/3) + # 4 * Complex(2, 0) # => (8+0i) + # + def *: (BigDecimal) -> BigDecimal + | ... + + # + # Performs addition: + # + # 2 + 2 # => 4 + # -2 + 2 # => 0 + # -2 + -2 # => -4 + # 2 + 2.0 # => 4.0 + # 2 + Rational(2, 1) # => (4/1) + # 2 + Complex(2, 0) # => (4+0i) + # + def +: (BigDecimal) -> BigDecimal + | ... + + # + # Performs subtraction: + # + # 4 - 2 # => 2 + # -4 - 2 # => -6 + # -4 - -2 # => -2 + # 4 - 2.0 # => 2.0 + # 4 - Rational(2, 1) # => (2/1) + # 4 - Complex(2, 0) # => (2+0i) + # + def -: (BigDecimal) -> BigDecimal + | ... +end + +%a{annotate:rdoc:skip} +class Float + # + # Returns a new Float which is the result of dividing `self` by `other`: + # + # f = 3.14 + # f / 2 # => 1.57 + # f / 2.0 # => 1.57 + # f / Rational(2, 1) # => 1.57 + # f / Complex(2, 0) # => (1.57+0.0i) + # + def /: (BigDecimal) -> BigDecimal + | ... + + # + # Returns a new Float which is the product of `self` and `other`: + # + # f = 3.14 + # f * 2 # => 6.28 + # f * 2.0 # => 6.28 + # f * Rational(1, 2) # => 1.57 + # f * Complex(2, 0) # => (6.28+0.0i) + # + def *: (BigDecimal) -> BigDecimal + | ... + + # + # Returns a new Float which is the sum of `self` and `other`: + # + # f = 3.14 + # f + 1 # => 4.140000000000001 + # f + 1.0 # => 4.140000000000001 + # f + Rational(1, 1) # => 4.140000000000001 + # f + Complex(1, 0) # => (4.140000000000001+0i) + # + def +: (BigDecimal) -> BigDecimal + | ... + + # + # Returns a new Float which is the difference of `self` and `other`: + # + # f = 3.14 + # f - 1 # => 2.14 + # f - 1.0 # => 2.14 + # f - Rational(1, 1) # => 2.14 + # f - Complex(1, 0) # => (2.14+0i) + # + def -: (BigDecimal) -> BigDecimal + | ... +end + +%a{annotate:rdoc:skip} +class Rational + # + # Performs division. + # + # Rational(2, 3) / Rational(2, 3) #=> (1/1) + # Rational(900) / Rational(1) #=> (900/1) + # Rational(-2, 9) / Rational(-9, 2) #=> (4/81) + # Rational(9, 8) / 4 #=> (9/32) + # Rational(20, 9) / 9.8 #=> 0.22675736961451246 + # + def /: (BigDecimal) -> BigDecimal + | ... + + # + # Performs multiplication. + # + # Rational(2, 3) * Rational(2, 3) #=> (4/9) + # Rational(900) * Rational(1) #=> (900/1) + # Rational(-2, 9) * Rational(-9, 2) #=> (1/1) + # Rational(9, 8) * 4 #=> (9/2) + # Rational(20, 9) * 9.8 #=> 21.77777777777778 + # + def *: (BigDecimal) -> BigDecimal + | ... + + # + # Performs addition. + # + # Rational(2, 3) + Rational(2, 3) #=> (4/3) + # Rational(900) + Rational(1) #=> (901/1) + # Rational(-2, 9) + Rational(-9, 2) #=> (-85/18) + # Rational(9, 8) + 4 #=> (41/8) + # Rational(20, 9) + 9.8 #=> 12.022222222222222 + # + def +: (BigDecimal) -> BigDecimal + | ... + + # + # Performs subtraction. + # + # Rational(2, 3) - Rational(2, 3) #=> (0/1) + # Rational(900) - Rational(1) #=> (899/1) + # Rational(-2, 9) - Rational(-9, 2) #=> (77/18) + # Rational(9, 8) - 4 #=> (-23/8) + # Rational(20, 9) - 9.8 #=> -7.577777777777778 + # + def -: (BigDecimal) -> BigDecimal + | ... +end + +%a{annotate:rdoc:skip} +class Complex + # + # Returns the quotient of `self` and `numeric`: + # + # Complex.rect(2, 3) / Complex.rect(2, 3) # => (1+0i) + # Complex.rect(900) / Complex.rect(1) # => (900+0i) + # Complex.rect(-2, 9) / Complex.rect(-9, 2) # => ((36/85)-(77/85)*i) + # Complex.rect(9, 8) / 4 # => ((9/4)+2i) + # Complex.rect(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i) + # + def /: (BigDecimal) -> Complex + | ... + + # + # Returns the product of `self` and `numeric`: + # + # Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i) + # Complex.rect(900) * Complex.rect(1) # => (900+0i) + # Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i) + # Complex.rect(9, 8) * 4 # => (36+32i) + # Complex.rect(20, 9) * 9.8 # => (196.0+88.2i) + # + def *: (BigDecimal) -> Complex + | ... + + # + # Returns the sum of `self` and `numeric`: + # + # Complex.rect(2, 3) + Complex.rect(2, 3) # => (4+6i) + # Complex.rect(900) + Complex.rect(1) # => (901+0i) + # Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i) + # Complex.rect(9, 8) + 4 # => (13+8i) + # Complex.rect(20, 9) + 9.8 # => (29.8+9i) + # + def +: (BigDecimal) -> Complex + | ... + + # + # Returns the difference of `self` and `numeric`: + # + # Complex.rect(2, 3) - Complex.rect(2, 3) # => (0+0i) + # Complex.rect(900) - Complex.rect(1) # => (899+0i) + # Complex.rect(-2, 9) - Complex.rect(-9, 2) # => (7+7i) + # Complex.rect(9, 8) - 4 # => (5+8i) + # Complex.rect(20, 9) - 9.8 # => (10.2+9i) + # + def -: (BigDecimal) -> Complex + | ... +end diff --git a/sig/big_decimal_util.rbs b/sig/big_decimal_util.rbs new file mode 100644 index 00000000..4c5bfce2 --- /dev/null +++ b/sig/big_decimal_util.rbs @@ -0,0 +1,158 @@ +%a{annotate:rdoc:skip} +class Integer + # + # Returns the value of `int` as a BigDecimal. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # 42.to_d # => 0.42e2 + # + # See also Kernel.BigDecimal. + # + def to_d: () -> BigDecimal +end + +%a{annotate:rdoc:skip} +class Float + # + # Returns the value of `float` as a BigDecimal. The `precision` parameter is + # used to determine the number of significant digits for the result. When + # `precision` is set to `0`, the number of digits to represent the float being + # converted is determined automatically. The default `precision` is `0`. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # 0.5.to_d # => 0.5e0 + # 1.234.to_d # => 0.1234e1 + # 1.234.to_d(2) # => 0.12e1 + # + # See also Kernel.BigDecimal. + # + def to_d: (?Integer precision) -> BigDecimal +end + +%a{annotate:rdoc:skip} +class String + # + # Returns the result of interpreting leading characters in `str` as a + # BigDecimal. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # "0.5".to_d # => 0.5e0 + # "123.45e1".to_d # => 0.12345e4 + # "45.67 degrees".to_d # => 0.4567e2 + # + # See also Kernel.BigDecimal. + # + def to_d: () -> BigDecimal +end + +%a{annotate:rdoc:skip} +class BigDecimal + # + # Converts a BigDecimal to a String of the form "nnnnnn.mmm". This method is + # deprecated; use BigDecimal#to_s("F") instead. + # + # require 'bigdecimal/util' + # + # d = BigDecimal("3.14") + # d.to_digits # => "3.14" + # + def to_digits: () -> String + + # + # Returns self. + # + # require 'bigdecimal/util' + # + # d = BigDecimal("3.14") + # d.to_d # => 0.314e1 + # + def to_d: () -> BigDecimal +end + +%a{annotate:rdoc:skip} +class Rational + # + # Returns the value as a BigDecimal. + # + # The `precision` parameter is used to determine the number of significant + # digits for the result. When `precision` is set to `0`, the number of digits to + # represent the float being converted is determined automatically. The default + # `precision` is `0`. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # Rational(22, 7).to_d(3) # => 0.314e1 + # + # See also Kernel.BigDecimal. + # + def to_d: (Integer precision) -> BigDecimal +end + +%a{annotate:rdoc:skip} +class Complex + # + # Returns the value as a BigDecimal. If the imaginary part is not `0`, an error + # is raised + # + # The `precision` parameter is used to determine the number of significant + # digits for the result. When `precision` is set to `0`, the number of digits to + # represent the float being converted is determined automatically. The default + # `precision` is `0`. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # Complex(0.1234567, 0).to_d(4) # => 0.1235e0 + # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1 + # Complex(1, 1).to_d # raises ArgumentError + # + # See also Kernel.BigDecimal. + # + def to_d: (*untyped args) -> BigDecimal +end + +%a{annotate:rdoc:skip} +class NilClass + # + # Returns nil represented as a BigDecimal. + # + # require 'bigdecimal' + # require 'bigdecimal/util' + # + # nil.to_d # => 0.0 + # + def to_d: () -> BigDecimal +end diff --git a/sig/big_math.rbs b/sig/big_math.rbs new file mode 100644 index 00000000..6d9fc48c --- /dev/null +++ b/sig/big_math.rbs @@ -0,0 +1,423 @@ +# +# Core BigMath methods for BigDecimal (log, exp) are defined here. Other methods +# (sin, cos, atan) are defined in 'bigdecimal/math.rb'. +# +# +# Provides mathematical functions. +# +# Example: +# +# require "bigdecimal/math" +# +# include BigMath +# +# a = BigDecimal((PI(49)/2).to_s) +# puts sin(a,100) # => 0.9999999999...9999999986e0 +# +module BigMath + # + # Computes e (the base of natural logarithms) to the specified number of digits + # of precision, `numeric`. + # + # BigMath.E(32).to_s + # #=> "0.27182818284590452353602874713527e1" + # + def self?.E: (int prec) -> BigDecimal + + # + # Computes the value of pi to the specified number of digits of precision, + # `numeric`. + # + # BigMath.PI(32).to_s + # #=> "0.31415926535897932384626433832795e1" + # + def self?.PI: (int prec) -> BigDecimal + + # + # Computes the arccosine of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.acos(BigDecimal('0.5'), 32).to_s + # #=> "0.10471975511965977461542144610932e1" + # + def self?.acos: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the inverse hyperbolic cosine of `decimal` to the specified number of + # digits of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.acosh(BigDecimal('2'), 32).to_s + # #=> "0.1316957896924816708625046347308e1" + # + def self?.acosh: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the arcsine of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.asin(BigDecimal('0.5'), 32).to_s + # #=> "0.52359877559829887307710723054658e0" + # + def self?.asin: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the inverse hyperbolic sine of `decimal` to the specified number of + # digits of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.asinh(BigDecimal('1'), 32).to_s + # #=> "0.88137358701954302523260932497979e0" + # + def self?.asinh: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the arctangent of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.atan(BigDecimal('-1'), 32).to_s + # #=> "-0.78539816339744830961566084581988e0" + # + def self?.atan: (real | BigDecimal x, int prec) -> BigDecimal + + # + # Computes the arctangent of y and x to the specified number of digits of + # precision, `numeric`. + # + # BigMath.atan2(BigDecimal('-1'), BigDecimal('1'), 32).to_s + # #=> "-0.78539816339744830961566084581988e0" + # + def self?.atan2: (real | BigDecimal, real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the inverse hyperbolic tangent of `decimal` to the specified number + # of digits of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.atanh(BigDecimal('0.5'), 32).to_s + # #=> "0.54930614433405484569762261846126e0" + # + def self?.atanh: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the cube root of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # BigMath.cbrt(BigDecimal('2'), 32).to_s + # #=> "0.12599210498948731647672106072782e1" + # + def self?.cbrt: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the cosine of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is Infinity or NaN, returns NaN. + # + # BigMath.cos(BigMath.PI(16), 32).to_s + # #=> "-0.99999999999999999999999999999997e0" + # + def self?.cos: (real | BigDecimal x, int prec) -> BigDecimal + + # + # Computes the hyperbolic cosine of `decimal` to the specified number of digits + # of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.cosh(BigDecimal('1'), 32).to_s + # #=> "0.15430806348152437784779056207571e1" + # + def self?.cosh: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the error function of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.erf(BigDecimal('1'), 32).to_s + # #=> "0.84270079294971486934122063508261e0" + # + def self?.erf: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the complementary error function of `decimal` to the specified number + # of digits of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.erfc(BigDecimal('10'), 32).to_s + # #=> "0.20884875837625447570007862949578e-44" + # + def self?.erfc: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the value of e (the base of natural logarithms) raised to the power + # of `decimal`, to the specified number of digits of precision. + # + # If `decimal` is infinity, returns Infinity. + # + # If `decimal` is NaN, returns NaN. + # + def self?.exp: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes exp(decimal) - 1 to the specified number of digits of precision, + # `numeric`. + # + # BigMath.expm1(BigDecimal('0.1'), 32).to_s + # #=> "0.10517091807564762481170782649025e0" + # + def self?.expm1: (real | BigDecimal, int prec) -> BigDecimal + + # + # Decomposes `x` into a normalized fraction and an integral power of ten. + # + # BigMath.frexp(BigDecimal(123.456)) + # #=> [0.123456e0, 3] + # + def self?.frexp: (real | BigDecimal x) -> [ BigDecimal, Integer ] + + # + # Computes the gamma function of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # BigMath.gamma(BigDecimal('0.5'), 32).to_s + # #=> "0.17724538509055160272981674833411e1" + # + def self?.gamma: (real | BigDecimal, int prec) -> BigDecimal + + # + # Returns sqrt(x**2 + y**2) to the specified number of digits of precision, + # `numeric`. + # + # BigMath.hypot(BigDecimal('1'), BigDecimal('2'), 32).to_s + # #=> "0.22360679774997896964091736687313e1" + # + def self?.hypot: (real | BigDecimal, real | BigDecimal, int prec) -> BigDecimal + + # + # Inverse of `frexp`. Returns the value of fraction * 10**exponent. + # + # BigMath.ldexp(BigDecimal("0.123456e0"), 3) + # #=> 0.123456e3 + # + def self?.ldexp: (real | BigDecimal fraction, Integer exponent) -> BigDecimal + + # + # Computes the natural logarithm of the absolute value of the gamma function of + # `decimal` to the specified number of digits of precision, `numeric` and its + # sign. + # + # BigMath.lgamma(BigDecimal('0.5'), 32) + # #=> [0.57236494292470008707171367567653e0, 1] + # + def self?.lgamma: (real | BigDecimal, int prec) -> [ BigDecimal, Integer ] + + # + # Computes the natural logarithm of `decimal` to the specified number of digits + # of precision, `numeric`. + # + # If `decimal` is zero or negative, raises Math::DomainError. + # + # If `decimal` is positive infinity, returns Infinity. + # + # If `decimal` is NaN, returns NaN. + # + def self?.log: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the base 10 logarithm of `decimal` to the specified number of digits + # of precision, `numeric`. + # + # If `decimal` is zero or negative, raises Math::DomainError. + # + # If `decimal` is positive infinity, returns Infinity. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.log10(BigDecimal('3'), 32).to_s + # #=> "0.47712125471966243729502790325512e0" + # + def self?.log10: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes log(1 + decimal) to the specified number of digits of precision, + # `numeric`. + # + # BigMath.log1p(BigDecimal('0.1'), 32).to_s + # #=> "0.95310179804324860043952123280765e-1" + # + def self?.log1p: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the base 2 logarithm of `decimal` to the specified number of digits + # of precision, `numeric`. + # + # If `decimal` is zero or negative, raises Math::DomainError. + # + # If `decimal` is positive infinity, returns Infinity. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.log2(BigDecimal('3'), 32).to_s + # #=> "0.15849625007211561814537389439478e1" + # + def self?.log2: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the sine of `decimal` to the specified number of digits of precision, + # `numeric`. + # + # If `decimal` is Infinity or NaN, returns NaN. + # + # BigMath.sin(BigMath.PI(5)/4, 32).to_s + # #=> "0.70710807985947359435812921837984e0" + # + def self?.sin: (real | BigDecimal x, int prec) -> BigDecimal + + # + # Computes the hyperbolic sine of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.sinh(BigDecimal('1'), 32).to_s + # #=> "0.11752011936438014568823818505956e1" + # + def self?.sinh: (real | BigDecimal, int prec) -> BigDecimal + + # + # Computes the square root of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # BigMath.sqrt(BigDecimal('2'), 32).to_s + # #=> "0.14142135623730950488016887242097e1" + # + def self?.sqrt: (real | BigDecimal x, int prec) -> BigDecimal + + # + # Computes the tangent of `decimal` to the specified number of digits of + # precision, `numeric`. + # + # If `decimal` is Infinity or NaN, returns NaN. + # + # BigMath.tan(BigDecimal("0.0"), 4).to_s + # #=> "0.0" + # + # BigMath.tan(BigMath.PI(24) / 4, 32).to_s + # #=> "0.99999999999999999999999830836025e0" + # + def self?.tan: (real | BigDecimal x, int prec) -> BigDecimal + + # + # Computes the hyperbolic tangent of `decimal` to the specified number of digits + # of precision, `numeric`. + # + # If `decimal` is NaN, returns NaN. + # + # BigMath.tanh(BigDecimal('1'), 32).to_s + # #=> "0.76159415595576488811945828260479e0" + # + def self?.tanh: (real | BigDecimal, int prec) -> BigDecimal +end diff --git a/test_sig/test_big_decimal.rb b/test_sig/test_big_decimal.rb new file mode 100644 index 00000000..fba7d5a1 --- /dev/null +++ b/test_sig/test_big_decimal.rb @@ -0,0 +1,620 @@ +require "bigdecimal" +require 'test/unit' +require 'rbs/unit_test' +require_relative './test_helper' + +class BigDecimalSingletonTest < Test::Unit::TestCase + include TestHelper + library "bigdecimal" + testing "singleton(::BigDecimal)" + + def test__load + assert_send_type "(::String) -> ::BigDecimal", + BigDecimal, :_load, "18:0.123e1" + end + + def test_double_fig + assert_send_type "() -> ::Integer", + BigDecimal, :double_fig + end + + def test_interpret_loosely + assert_send_type "(String) -> BigDecimal", + BigDecimal, :interpret_loosely, "1.23" + assert_send_type "(_ToStr) -> BigDecimal", + BigDecimal, :interpret_loosely, ToStr.new("1.23") + end + + def test_limit + BigDecimal.save_limit do + assert_send_type "() -> ::Integer", + BigDecimal, :limit + assert_send_type "(nil) -> ::Integer", + BigDecimal, :limit, nil + assert_send_type "(::Integer digits) -> ::Integer", + BigDecimal, :limit, 5 + end + end + + def test_mode + BigDecimal.save_exception_mode do + assert_send_type "(::Integer mode) -> ::Integer", + BigDecimal, :mode, BigDecimal::EXCEPTION_ALL + assert_send_type "(::Integer mode, true setting) -> ::Integer", + BigDecimal, :mode, BigDecimal::EXCEPTION_ALL, true + assert_send_type "(::Integer mode, false setting) -> ::Integer", + BigDecimal, :mode, BigDecimal::EXCEPTION_ALL, false + assert_send_type "(::Integer mode, nil setting) -> ::Integer", + BigDecimal, :mode, BigDecimal::EXCEPTION_ALL, nil + end + + BigDecimal.save_rounding_mode do + assert_send_type "(::Integer mode) -> ::Integer", + BigDecimal, :mode, BigDecimal::ROUND_MODE + assert_send_type "(::Integer mode, ::Integer setting) -> ::Integer", + BigDecimal, :mode, BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN + assert_send_type "(::Integer mode, ::Symbol setting) -> ::Integer", + BigDecimal, :mode, BigDecimal::ROUND_MODE, :half_up + end + end + + # FIXME: 実装がブロックにnilを渡すため、型定義の() -> voidと一致しない + def test_save_exception_mode + assert_send_type "() { (nil) -> void } -> void", + BigDecimal, :save_exception_mode do end + end + + def test_save_limit + assert_send_type "() { (nil) -> void } -> void", + BigDecimal, :save_limit do end + end + + def test_save_rounding_mode + assert_send_type "() { (nil) -> void } -> void", + BigDecimal, :save_rounding_mode do end + end + + def test_kernel + assert_send_type "(::String) -> ::BigDecimal", + Kernel, :BigDecimal, "1.23" + assert_send_type "(::_ToStr) -> ::BigDecimal", + Kernel, :BigDecimal, ToStr.new("1.23") + assert_send_type "(::Integer) -> ::BigDecimal", + Kernel, :BigDecimal, 123 + assert_send_type "(::BigDecimal) -> ::BigDecimal", + Kernel, :BigDecimal, BigDecimal("1.23") + assert_send_type "(::Float, ::Integer) -> ::BigDecimal", + Kernel, :BigDecimal, 1.23, 1 + assert_send_type "(::Float, ::_ToInt) -> ::BigDecimal", + Kernel, :BigDecimal, 1.23, ToInt.new(1) + assert_send_type "(::Rational, ::Integer) -> ::BigDecimal", + Kernel, :BigDecimal, Rational(1.23), 1 + assert_send_type "(::String, exception: bool) -> ::BigDecimal", + Kernel, :BigDecimal, "1.23", exception: false + assert_send_type "(::Float, ::Integer, exception: bool) -> ::BigDecimal", + Kernel, :BigDecimal, 1.23, 1, exception: true + end + + def test_constants + assert_const_type 'Integer', 'BigDecimal::BASE' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_ALL' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_INFINITY' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_NaN' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_OVERFLOW' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_UNDERFLOW' + assert_const_type 'Integer', 'BigDecimal::EXCEPTION_ZERODIVIDE' + assert_const_type 'BigDecimal', 'BigDecimal::INFINITY' + assert_const_type 'BigDecimal', 'BigDecimal::NAN' + assert_const_type 'Integer', 'BigDecimal::ROUND_CEILING' + assert_const_type 'Integer', 'BigDecimal::ROUND_DOWN' + assert_const_type 'Integer', 'BigDecimal::ROUND_FLOOR' + assert_const_type 'Integer', 'BigDecimal::ROUND_HALF_DOWN' + assert_const_type 'Integer', 'BigDecimal::ROUND_HALF_EVEN' + assert_const_type 'Integer', 'BigDecimal::ROUND_HALF_UP' + assert_const_type 'Integer', 'BigDecimal::ROUND_MODE' + assert_const_type 'Integer', 'BigDecimal::ROUND_UP' + assert_const_type 'Integer', 'BigDecimal::SIGN_NEGATIVE_FINITE' + assert_const_type 'Integer', 'BigDecimal::SIGN_NEGATIVE_INFINITE' + assert_const_type 'Integer', 'BigDecimal::SIGN_NEGATIVE_ZERO' + assert_const_type 'Integer', 'BigDecimal::SIGN_NaN' + assert_const_type 'Integer', 'BigDecimal::SIGN_POSITIVE_FINITE' + assert_const_type 'Integer', 'BigDecimal::SIGN_POSITIVE_INFINITE' + assert_const_type 'Integer', 'BigDecimal::SIGN_POSITIVE_ZERO' + assert_const_type 'String', 'BigDecimal::VERSION' + end +end + +class BigDecimalTest < Test::Unit::TestCase + include TestHelper + library "bigdecimal" + testing "::BigDecimal" + + def test_double_equal + assert_send_type "(untyped) -> bool", + BigDecimal("1.23"), :==, BigDecimal("1.234") + end + + def test_spaceship + assert_send_type "(::Numeric) -> ::Integer?", + BigDecimal("1.23"), :<=>, BigDecimal("1.234") + end + + def test_triple_equal + assert_send_type "(untyped) -> bool", + BigDecimal("1.23"), :===, BigDecimal("1.234") + end + + def test_clone + assert_send_type "() -> BigDecimal", + BigDecimal("1.23"), :clone + end + + def test_dup + assert_send_type "() -> BigDecimal", + BigDecimal("1.23"), :dup + end + + def test_eql? + assert_send_type "(untyped) -> bool", + BigDecimal("1.23"), :eql?, BigDecimal("1.234") + end + + def test_hash + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :hash + end + + def test_inspect + assert_send_type "() -> ::String", + BigDecimal("1.23"), :inspect + end + + def test_to_s + assert_send_type "() -> ::String", + BigDecimal("1.23"), :to_s + assert_send_type "(::String s) -> ::String", + BigDecimal("1.23"), :to_s, "2F" + assert_send_type "(::int s) -> ::String", + BigDecimal("1.23"), :to_s, 2 + end + + def test_less_than + assert_send_type "(::BigDecimal) -> bool", + BigDecimal("1.23"), :<, BigDecimal("1.234") + with_real(1.234) do |real| + assert_send_type "(::real) -> bool", + BigDecimal("1.23"), :<, real + end + end + + def test_less_than_equal_to + assert_send_type "(::BigDecimal) -> bool", + BigDecimal("1.23"), :<=, BigDecimal("1.234") + with_real(1.234) do |real| + assert_send_type "(::real) -> bool", + BigDecimal("1.23"), :<=, real + end + end + + def test_greater_than + assert_send_type "(::BigDecimal) -> bool", + BigDecimal("1.23"), :>, BigDecimal("1.234") + with_real(1.234) do |real| + assert_send_type "(::real) -> bool", + BigDecimal("1.23"), :>, real + end + end + + def test_greater_than_equal_to + assert_send_type "(::BigDecimal) -> bool", + BigDecimal("1.23"), :>=, BigDecimal("1.234") + with_real(1.234) do |real| + assert_send_type "(::real) -> bool", + BigDecimal("1.23"), :>=, real + end + end + + def test_modulus + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("1.23"), :%, BigDecimal("1.234") + with_real(1.234) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("1.23"), :%, real + end + end + + def test_multiply + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("2"), :*, BigDecimal("3") + with_real(3) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("2"), :*, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("2"), :*, Complex(1, 2) + end + + def test_starstar + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("2"), :**, BigDecimal("3") + with_real(3) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("2"), :**, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("2"), :**, Complex(1, 0) + end + + def test_power + with_real(2) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("1.23"), :power, real + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigDecimal("1.23"), :power, real, 0 + end + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("1.23"), :power, BigDecimal("2") + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigDecimal("1.23"), :power, BigDecimal("1.23"), 0 + end + + def test_plus + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("1"), :+, BigDecimal("2") + with_real(2) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("1"), :+, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("1"), :+, Complex(2, 0) + end + + def test_minus + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("3"), :-, BigDecimal("1") + with_real(1) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("3"), :-, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("3"), :-, Complex(1, 0) + end + + def test_divide + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("6"), :/, BigDecimal("2") + with_real(2) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("6"), :/, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("6"), :/, Complex(2, 0) + end + + def test_unary_plus + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :+@ + end + + def test_unary_minus + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :-@ + end + + def test_abs + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :abs + end + + def test_ceil + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :ceil + assert_send_type "(::Integer n) -> ::BigDecimal", + BigDecimal("1.23"), :ceil, 2 + end + + def test_coerce + assert_send_type "(::BigDecimal) -> [ ::BigDecimal, ::BigDecimal ]", + BigDecimal("1.23"), :coerce, BigDecimal("1.234") + end + + def test_div + assert_send_type "(::BigDecimal value) -> ::Integer", + BigDecimal("5"), :div, BigDecimal("2") + with_real(2) do |real| + assert_send_type "(::real value) -> ::Integer", + BigDecimal("5"), :div, real + end + assert_send_type "(::BigDecimal value, ::int digits) -> ::BigDecimal", + BigDecimal("1.23"), :div, BigDecimal("2"), 3 + with_real(2) do |real| + assert_send_type "(::real value, ::int digits) -> ::BigDecimal", + BigDecimal("1.23"), :div, real, 3 + end + end + + def test_divmod + assert_send_type "(::BigDecimal) -> [ ::Integer, ::BigDecimal ]", + BigDecimal("5"), :divmod, BigDecimal("2") + with_real(2) do |real| + assert_send_type "(::real) -> [ ::Integer, ::BigDecimal ]", + BigDecimal("5"), :divmod, real + end + end + + def test_finite? + assert_send_type "() -> bool", + BigDecimal("1.23"), :finite? + end + + def test_floor + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :floor + assert_send_type "(::int n) -> ::BigDecimal", + BigDecimal("1.23"), :floor, 2 + end + + def test_infinite? + assert_send_type "() -> ::Integer?", + BigDecimal("1.23"), :infinite? + end + + def test_modulo + assert_send_type "(::BigDecimal b) -> ::BigDecimal", + BigDecimal("5"), :modulo, BigDecimal("3") + with_real(3) do |real| + assert_send_type "(::real b) -> ::BigDecimal", + BigDecimal("5"), :modulo, real + end + end + + def test_nonzero? + assert_send_type "() -> BigDecimal", + BigDecimal("1.23"), :nonzero? + end + + def test_quo + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("1.23"), :quo, BigDecimal("2") + with_real(2) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("1.23"), :quo, real + end + assert_send_type "(::Complex) -> ::Complex", + BigDecimal("2"), :quo, Complex(1, 2) + end + + def test_remainder + assert_send_type "(::BigDecimal) -> ::BigDecimal", + BigDecimal("5"), :remainder, BigDecimal("3") + with_real(3) do |real| + assert_send_type "(::real) -> ::BigDecimal", + BigDecimal("5"), :remainder, real + end + end + + def test_round + assert_send_type "() -> ::Integer", + BigDecimal("3.14"), :round + assert_send_type "(::Integer) -> ::Integer", + BigDecimal("3.14"), :round, 0 + assert_send_type "(::Integer) -> ::BigDecimal", + BigDecimal("3.14"), :round, 1 + assert_send_type "(::Integer, ::Integer) -> ::BigDecimal", + BigDecimal("3.14"), :round, 0, BigDecimal::ROUND_UP + assert_send_type "(::Integer, :half_up) -> ::BigDecimal", + BigDecimal("3.14"), :round, 0, :half_up + assert_send_type "(half: :up) -> ::BigDecimal", + BigDecimal("3.14"), :round, half: :up + assert_send_type "(::Integer, half: :even) -> ::BigDecimal", + BigDecimal("3.14"), :round, 0, half: :even + end + + def test_to_int + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :to_int + end + + def test_truncate + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :truncate + assert_send_type "(::int n) -> ::BigDecimal", + BigDecimal("1.23"), :truncate, 2 + end + + def test_zero? + assert_send_type "() -> bool", + BigDecimal("1.23"), :zero? + end + + + def test__dump + assert_send_type "(?untyped) -> String", + BigDecimal("1.23"), :_dump + end + + def test_add + assert_send_type "(::BigDecimal value, ::Integer digits) -> ::BigDecimal", + BigDecimal("1.23"), :add, BigDecimal("1.23"), 2 + with_real(1.23) do |real| + assert_send_type "(::real value, ::Integer digits) -> ::BigDecimal", + BigDecimal("1.23"), :add, real, 2 + end + end + + def test_exponent + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :exponent + end + + def test_fix + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :fix + end + + def test_frac + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :frac + end + + def test_mult + assert_send_type "(::BigDecimal value, ::int digits) -> ::BigDecimal", + BigDecimal("1.23"), :mult, BigDecimal("1.23"), 2 + with_real(1.23) do |real| + assert_send_type "(::real value, ::int digits) -> ::BigDecimal", + BigDecimal("1.23"), :mult, real, 2 + end + end + + def test_nan? + assert_send_type "() -> bool", + BigDecimal("1.23"), :nan? + end + + def test_sign + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :sign + end + + def test_split + assert_send_type "() -> [ ::Integer, ::String, ::Integer, ::Integer ]", + BigDecimal("1.23"), :split + end + + def test_sqrt + assert_send_type "(::int n) -> ::BigDecimal", + BigDecimal("1.23"), :sqrt, 2 + end + + def test_sub + assert_send_type "(::BigDecimal value, ::int digits) -> ::BigDecimal", + BigDecimal("5.123"), :sub, BigDecimal("1.5"), 3 + with_real(1.5) do |real| + assert_send_type "(::real value, ::int digits) -> ::BigDecimal", + BigDecimal("5.123"), :sub, real, 3 + end + end + + def test_to_f + assert_send_type "() -> ::Float", + BigDecimal("1.23"), :to_f + end + + def test_to_i + assert_send_type "() -> ::Integer", + BigDecimal("1.23"), :to_i + end + + def test_to_r + assert_send_type "() -> ::Rational", + BigDecimal("1.23"), :to_r + end +end + +class IntegerToBigDecimalTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Integer" + + def test_plus_with_integer + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123, :+, BigDecimal("1.23") + end + + def test_minus_with_integer + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123, :-, BigDecimal("1.23") + end + + def test_divide_with_integer + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123, :/, BigDecimal("1.23") + end + + def test_multiply_with_integer + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123, :*, BigDecimal("1.23") + end +end + +class FloatToBigDecimalTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Float" + + def test_plus_with_float + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 1.23, :+, BigDecimal("1.23") + end + + def test_minus_with_float + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 1.23, :-, BigDecimal("1.23") + end + + def test_divide_with_float + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 1.23, :/, BigDecimal("1.23") + end + + def test_multiply_with_float + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 1.23, :*, BigDecimal("1.23") + end +end + +class RationalToBigDecimalTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Rational" + + def test_plus_with_rational + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123r, :+, BigDecimal("1.23") + end + + def test_minus_with_rational + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123r, :-, BigDecimal("1.23") + end + + def test_divide_with_rational + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123r, :/, BigDecimal("1.23") + end + + def test_multiply_with_rational + assert_send_type "(::BigDecimal) -> ::BigDecimal", + 123r, :*, BigDecimal("1.23") + end +end + +class ComplexToBigDecimalTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Complex" + + def test_plus_with_complex + assert_send_type "(::BigDecimal) -> ::Complex", + Complex(0.1234567, 0), :+, BigDecimal("1.23") + end + + def test_minus_with_complex + assert_send_type "(::BigDecimal) -> ::Complex", + Complex(0.1234567, 0), :-, BigDecimal("1.23") + end + + def test_divide_with_complex + assert_send_type "(::BigDecimal) -> ::Complex", + Complex(0.1234567, 0), :/, BigDecimal("1.23") + end + + def test_multiply_with_complex + assert_send_type "(::BigDecimal) -> ::Complex", + Complex(0.1234567, 0), :*, BigDecimal("1.23") + end +end diff --git a/test_sig/test_big_decimal_util.rb b/test_sig/test_big_decimal_util.rb new file mode 100644 index 00000000..66e7f4ae --- /dev/null +++ b/test_sig/test_big_decimal_util.rb @@ -0,0 +1,87 @@ +require "bigdecimal" +require "bigdecimal/util" +require 'test/unit' +require 'rbs/unit_test' +require_relative './test_helper' + +class BigDecimalUtilTest < Test::Unit::TestCase + include TestHelper + library "bigdecimal" + testing "::BigDecimal" + + def test_to_digits + assert_send_type "() -> ::String", + BigDecimal("1.23"), :to_digits + end + + def test_to_d + assert_send_type "() -> ::BigDecimal", + BigDecimal("1.23"), :to_d + end +end + +class BigDecimalUtilIntegerTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Integer" + + def test_to_d_with_integer + assert_send_type "() -> ::BigDecimal", 123, :to_d + end +end + +class BigDecimalUtilFloatTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Float" + + def test_to_d_with_float + assert_send_type "() -> ::BigDecimal", 12.3, :to_d + end +end + +class BigDecimalUtilRationalTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Rational" + + def test_to_d_with_rational + assert_send_type "(Integer) -> ::BigDecimal", Rational(22, 7), :to_d, 3 + end +end + +class BigDecimalUtilComplexTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::Complex" + + def test_to_d_with_complex + assert_send_type "() -> ::BigDecimal", Complex(0.1234567, 0), :to_d + end +end + +class BigDecimalUtilStringTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::String" + + def test_to_d_with_string + assert_send_type "() -> ::BigDecimal", "123", :to_d + end +end + +class BigDecimalUtilNilClassTest < Test::Unit::TestCase + include TestHelper + + library "bigdecimal" + testing "::NilClass" + + def test_to_d_with_nil + assert_send_type "() -> ::BigDecimal", nil, :to_d + end +end diff --git a/test_sig/test_big_math.rb b/test_sig/test_big_math.rb new file mode 100644 index 00000000..6bb776e2 --- /dev/null +++ b/test_sig/test_big_math.rb @@ -0,0 +1,439 @@ +require "bigdecimal" +require "bigdecimal/math" +require 'test/unit' +require 'rbs/unit_test' +require_relative './test_helper' + +class BigMathSingletonTest < Test::Unit::TestCase + include TestHelper + library "bigdecimal" + testing "singleton(::BigMath)" + + def test_E + assert_send_type "(::Integer prec) -> ::BigDecimal", + BigMath, :E, 10 + end + + def test_PI + assert_send_type "(::Integer prec) -> ::BigDecimal", + BigMath, :PI, 10 + end + + def test_acos + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :acos, BigDecimal('0.5'), 32 + with_real(0.5) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :acos, real, 32 + end + end + + def test_acosh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :acosh, BigDecimal('2'), 32 + with_real(2) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :acosh, real, 32 + end + end + + def test_asin + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :asin, BigDecimal('0.5'), 32 + with_real(0.5) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :asin, real, 32 + end + end + + def test_asinh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :asinh, BigDecimal('1'), 32 + with_real(1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :asinh, real, 32 + end + end + + def test_atan + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + BigMath, :atan, BigDecimal('-1'), 32 + with_real(-1) do |real| + assert_send_type "(::real x, ::Integer prec) -> ::BigDecimal", + BigMath, :atan, real, 32 + end + end + + def test_atan2 + assert_send_type "(::BigDecimal, ::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :atan2, BigDecimal('-1'), BigDecimal('1'), 32 + with_real(-1) do |real_y| + with_real(1) do |real_x| + assert_send_type "(::real, ::real, ::Integer) -> ::BigDecimal", + BigMath, :atan2, real_y, real_x, 32 + end + end + end + + def test_atanh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :atanh, BigDecimal('0.5'), 32 + with_real(0.5) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :atanh, real, 32 + end + end + + def test_cbrt + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :cbrt, BigDecimal('2'), 32 + with_real(2) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :cbrt, real, 32 + end + end + + def test_cos + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + BigMath, :cos, BigMath.PI(16), 32 + with_real(1) do |real| + assert_send_type "(::real x, ::Integer prec) -> ::BigDecimal", + BigMath, :cos, real, 10 + end + end + + def test_cosh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :cosh, BigDecimal('1'), 32 + with_real(1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :cosh, real, 32 + end + end + + def test_erf + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :erf, BigDecimal('1'), 32 + with_real(1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :erf, real, 32 + end + end + + def test_erfc + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :erfc, BigDecimal('10'), 32 + with_real(10) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :erfc, real, 32 + end + end + + def test_exp + assert_send_type "(::BigDecimal, ::Integer prec) -> ::BigDecimal", + BigMath, :exp, BigDecimal('1'), 10 + with_real(1) do |real| + assert_send_type "(::real, ::Integer prec) -> ::BigDecimal", + BigMath, :exp, real, 10 + end + end + + def test_expm1 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :expm1, BigDecimal('0.1'), 32 + with_real(0.1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :expm1, real, 32 + end + end + + def test_frexp + assert_send_type "(::BigDecimal) -> [::BigDecimal, ::Integer]", + BigMath, :frexp, BigDecimal(123.456) + with_real(123.456) do |real| + assert_send_type "(::real) -> [::BigDecimal, ::Integer]", + BigMath, :frexp, real + end + end + + def test_gamma + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :gamma, BigDecimal('0.5'), 32 + with_real(2) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :gamma, real, 32 + end + end + + def test_hypot + assert_send_type "(::BigDecimal, ::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :hypot, BigDecimal('1'), BigDecimal('2'), 32 + with_real(1) do |real_x| + with_real(2) do |real_y| + assert_send_type "(::real, ::real, ::Integer) -> ::BigDecimal", + BigMath, :hypot, real_x, real_y, 32 + end + end + end + + def test_ldexp + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :ldexp, BigDecimal("0.123456e0"), 3 + with_real(0.123456) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :ldexp, real, 3 + end + end + + def test_lgamma + assert_send_type "(::BigDecimal, ::Integer) -> [::BigDecimal, ::Integer]", + BigMath, :lgamma, BigDecimal('0.5'), 32 + with_real(2) do |real| + assert_send_type "(::real, ::Integer) -> [::BigDecimal, ::Integer]", + BigMath, :lgamma, real, 32 + end + end + + def test_log + assert_send_type "(::BigDecimal, ::Integer prec) -> ::BigDecimal", + BigMath, :log, BigDecimal('1'), 10 + with_real(1) do |real| + assert_send_type "(::real, ::Integer prec) -> ::BigDecimal", + BigMath, :log, real, 10 + end + end + + def test_log10 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :log10, BigDecimal('3'), 32 + with_real(3) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :log10, real, 32 + end + end + + def test_log1p + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :log1p, BigDecimal('0.1'), 32 + with_real(0.1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :log1p, real, 32 + end + end + + def test_log2 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :log2, BigDecimal('3'), 32 + with_real(3) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :log2, real, 32 + end + end + + def test_sin + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + BigMath, :sin, BigMath.PI(5) / 4, 32 + with_real(1) do |real| + assert_send_type "(::real x, ::Integer prec) -> ::BigDecimal", + BigMath, :sin, real, 10 + end + end + + def test_sinh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :sinh, BigDecimal('1'), 32 + with_real(1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :sinh, real, 32 + end + end + + def test_sqrt + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :sqrt, BigDecimal('2'), 32 + with_real(2) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :sqrt, real, 32 + end + end + + def test_tan + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + BigMath, :tan, BigDecimal("0.0"), 4 + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + BigMath, :tan, BigMath.PI(24) / 4, 32 + with_real(1) do |real| + assert_send_type "(::real x, ::Integer prec) -> ::BigDecimal", + BigMath, :tan, real, 10 + end + end + + def test_tanh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + BigMath, :tanh, BigDecimal('1'), 32 + with_real(1) do |real| + assert_send_type "(::real, ::Integer) -> ::BigDecimal", + BigMath, :tanh, real, 32 + end + end +end + +class BigMathTest < Test::Unit::TestCase + include TestHelper + library "bigdecimal" + testing "::BigMath" + + class TestClass + include BigMath + end + + def test_E + assert_send_type "(::Integer prec) -> ::BigDecimal", + TestClass.new, :E, 10 + end + + def test_PI + assert_send_type "(::Integer prec) -> ::BigDecimal", + TestClass.new, :PI, 10 + end + + def test_acos + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :acos, BigDecimal('0.5'), 32 + end + + def test_acosh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :acosh, BigDecimal('2'), 32 + end + + def test_asin + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :asin, BigDecimal('0.5'), 32 + end + + def test_asinh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :asinh, BigDecimal('1'), 32 + end + + def test_atan + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + TestClass.new, :atan, BigDecimal('1.23'), 10 + end + + def test_atan2 + assert_send_type "(::BigDecimal, ::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :atan2, BigDecimal('-1'), BigDecimal('1'), 32 + end + + def test_atanh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :atanh, BigDecimal('0.5'), 32 + end + + def test_cbrt + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :cbrt, BigDecimal('2'), 32 + end + + def test_cos + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + TestClass.new, :cos, BigDecimal('1.23'), 10 + end + + def test_cosh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :cosh, BigDecimal('1'), 32 + end + + def test_erf + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :erf, BigDecimal('1'), 32 + end + + def test_erfc + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :erfc, BigDecimal('10'), 32 + end + + def test_exp + assert_send_type "(::BigDecimal, ::Integer prec) -> ::BigDecimal", + TestClass.new, :exp, BigDecimal('1.23'), 10 + end + + def test_expm1 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :expm1, BigDecimal('0.1'), 32 + end + + def test_frexp + assert_send_type "(::BigDecimal) -> [::BigDecimal, ::Integer]", + TestClass.new, :frexp, BigDecimal(123.456) + end + + def test_gamma + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :gamma, BigDecimal('0.5'), 32 + end + + def test_hypot + assert_send_type "(::BigDecimal, ::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :hypot, BigDecimal('1'), BigDecimal('2'), 32 + end + + def test_ldexp + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :ldexp, BigDecimal("0.123456e0"), 3 + end + + def test_lgamma + assert_send_type "(::BigDecimal, ::Integer) -> [::BigDecimal, ::Integer]", + TestClass.new, :lgamma, BigDecimal('0.5'), 32 + end + + def test_log + assert_send_type "(::BigDecimal, ::Integer prec) -> ::BigDecimal", + TestClass.new, :log, BigDecimal('1.23'), 10 + end + + def test_log10 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :log10, BigDecimal('3'), 32 + end + + def test_log1p + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :log1p, BigDecimal('0.1'), 32 + end + + def test_log2 + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :log2, BigDecimal('3'), 32 + end + + def test_sin + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + TestClass.new, :sin, BigDecimal('1.23'), 10 + end + + def test_sinh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :sinh, BigDecimal('1'), 32 + end + + def test_sqrt + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + TestClass.new, :sqrt, BigDecimal('1.23'), 10 + end + + def test_tan + assert_send_type "(::BigDecimal x, ::Integer prec) -> ::BigDecimal", + TestClass.new, :tan, BigDecimal("0.0"), 4 + end + + def test_tanh + assert_send_type "(::BigDecimal, ::Integer) -> ::BigDecimal", + TestClass.new, :tanh, BigDecimal('1'), 32 + end +end diff --git a/test_sig/test_helper.rb b/test_sig/test_helper.rb new file mode 100644 index 00000000..a9ce1a5c --- /dev/null +++ b/test_sig/test_helper.rb @@ -0,0 +1,16 @@ +require 'rbs/unit_test' + +module TestHelper + include RBS::UnitTest::TypeAssertions + include RBS::UnitTest::Convertibles + + def self.included(base) + base.extend RBS::UnitTest::TypeAssertions::ClassMethods + end + + def with_real(n) + yield n.to_i + yield n.to_f + yield n.to_r + end +end