mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
f9727c12cc
* [Feature #12005] Unify Fixnum and Bignum into Integer * include/ruby/ruby.h (rb_class_of): Return rb_cInteger for fixnums. * insns.def (INTEGER_REDEFINED_OP_FLAG): Unified from FIXNUM_REDEFINED_OP_FLAG and BIGNUM_REDEFINED_OP_FLAG. * vm_core.h: Ditto. * vm_insnhelper.c (opt_eq_func): Use INTEGER_REDEFINED_OP_FLAG instead of FIXNUM_REDEFINED_OP_FLAG. * vm.c (vm_redefinition_check_flag): Use rb_cInteger instead of rb_cFixnum and rb_cBignum. (C): Use Integer instead of Fixnum and Bignum. * numeric.c (fix_succ): Removed. (Init_Numeric): Define Fixnum as Integer. * bignum.c (bignew): Use rb_cInteger instead of Rb_cBignum. (rb_int_coerce): replaced from rb_big_coerce and return fixnums as-is. (Init_Bignum): Define Bignum as Integer. Don't define ===. * error.c (builtin_class_name): Return "Integer" for fixnums. * sprintf.c (ruby__sfvextra): Use rb_cInteger instead of rb_cFixnum. * ext/-test-/testutil: New directory to test. Currently it provides utilities for fixnum and bignum. * ext/json/generator/generator.c: Define mInteger_to_json. * lib/mathn.rb (Fixnum#/): Redefinition removed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55024 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
177 lines
3.6 KiB
Ruby
177 lines
3.6 KiB
Ruby
# frozen_string_literal: false
|
|
#--
|
|
# $Release Version: 0.5 $
|
|
# $Revision: 1.1.1.1.4.1 $
|
|
|
|
##
|
|
# = mathn
|
|
#
|
|
# mathn serves to make mathematical operations more precise in Ruby
|
|
# and to integrate other mathematical standard libraries.
|
|
#
|
|
# Without mathn:
|
|
#
|
|
# 3 / 2 => 1 # Integer
|
|
#
|
|
# With mathn:
|
|
#
|
|
# 3 / 2 => 3/2 # Rational
|
|
#
|
|
# mathn keeps value in exact terms.
|
|
#
|
|
# Without mathn:
|
|
#
|
|
# 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18
|
|
#
|
|
# With mathn:
|
|
#
|
|
# 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20
|
|
#
|
|
#
|
|
# When you require 'mathn', the libraries for Prime, CMath, Matrix and Vector
|
|
# are also loaded.
|
|
#
|
|
# == Copyright
|
|
#
|
|
# Author: Keiju ISHITSUKA (SHL Japan Inc.)
|
|
#--
|
|
# class Numeric follows to make this documentation findable in a reasonable
|
|
# location
|
|
|
|
warn('lib/mathn.rb is deprecated') if $VERBOSE
|
|
|
|
class Numeric; end
|
|
|
|
require "cmath.rb"
|
|
require "matrix.rb"
|
|
require "prime.rb"
|
|
|
|
require "mathn/rational"
|
|
require "mathn/complex"
|
|
|
|
unless defined?(Math.exp!)
|
|
Object.instance_eval{remove_const :Math}
|
|
Math = CMath # :nodoc:
|
|
end
|
|
|
|
##
|
|
# When mathn is required, Integer's division is enhanced to
|
|
# return more precise values from mathematical expressions.
|
|
#
|
|
# 2/3*3 # => 0
|
|
# require 'mathn'
|
|
# 2/3*3 # => 2
|
|
#
|
|
# (2**72) / ((2**70) * 3) # => 4/3
|
|
|
|
class Integer
|
|
remove_method :/
|
|
|
|
##
|
|
# +/+ defines the Rational division for Bignum.
|
|
#
|
|
# (2**72) / ((2**70) * 3) # => 4/3
|
|
|
|
alias / quo
|
|
end
|
|
|
|
##
|
|
# When mathn is required, the Math module changes as follows:
|
|
#
|
|
# Standard Math module behaviour:
|
|
# Math.sqrt(4/9) # => 0.0
|
|
# Math.sqrt(4.0/9.0) # => 0.666666666666667
|
|
# Math.sqrt(- 4/9) # => Errno::EDOM: Numerical argument out of domain - sqrt
|
|
#
|
|
# After require 'mathn', this is changed to:
|
|
#
|
|
# require 'mathn'
|
|
# Math.sqrt(4/9) # => 2/3
|
|
# Math.sqrt(4.0/9.0) # => 0.666666666666667
|
|
# Math.sqrt(- 4/9) # => Complex(0, 2/3)
|
|
|
|
module Math
|
|
remove_method(:sqrt)
|
|
|
|
##
|
|
# Computes the square root of +a+. It makes use of Complex and
|
|
# Rational to have no rounding errors if possible.
|
|
#
|
|
# Math.sqrt(4/9) # => 2/3
|
|
# Math.sqrt(- 4/9) # => Complex(0, 2/3)
|
|
# Math.sqrt(4.0/9.0) # => 0.666666666666667
|
|
|
|
def sqrt(a)
|
|
if a.kind_of?(Complex)
|
|
abs = sqrt(a.real*a.real + a.imag*a.imag)
|
|
x = sqrt((a.real + abs)/Rational(2))
|
|
y = sqrt((-a.real + abs)/Rational(2))
|
|
if a.imag >= 0
|
|
Complex(x, y)
|
|
else
|
|
Complex(x, -y)
|
|
end
|
|
elsif a.respond_to?(:nan?) and a.nan?
|
|
a
|
|
elsif a >= 0
|
|
rsqrt(a)
|
|
else
|
|
Complex(0,rsqrt(-a))
|
|
end
|
|
end
|
|
|
|
##
|
|
# Compute square root of a non negative number. This method is
|
|
# internally used by +Math.sqrt+.
|
|
|
|
def rsqrt(a)
|
|
if a.kind_of?(Float)
|
|
sqrt!(a)
|
|
elsif a.kind_of?(Rational)
|
|
rsqrt(a.numerator)/rsqrt(a.denominator)
|
|
else
|
|
src = a
|
|
max = 2 ** 32
|
|
byte_a = [src & 0xffffffff]
|
|
# ruby's bug
|
|
while (src >= max) and (src >>= 32)
|
|
byte_a.unshift src & 0xffffffff
|
|
end
|
|
|
|
answer = 0
|
|
main = 0
|
|
side = 0
|
|
for elm in byte_a
|
|
main = (main << 32) + elm
|
|
side <<= 16
|
|
if answer != 0
|
|
if main * 4 < side * side
|
|
applo = main.div(side)
|
|
else
|
|
applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1
|
|
end
|
|
else
|
|
applo = sqrt!(main).to_i + 1
|
|
end
|
|
|
|
while (x = (side + applo) * applo) > main
|
|
applo -= 1
|
|
end
|
|
main -= x
|
|
answer = (answer << 16) + applo
|
|
side += applo * 2
|
|
end
|
|
if main == 0
|
|
answer
|
|
else
|
|
sqrt!(a)
|
|
end
|
|
end
|
|
end
|
|
|
|
class << self
|
|
remove_method(:sqrt)
|
|
end
|
|
module_function :sqrt
|
|
module_function :rsqrt
|
|
end
|