ruby/lib/mathn.rb

314 строки
5.5 KiB
Ruby
Исходник Обычный вид История

#
# mathn.rb -
# $Release Version: 0.5 $
# $Revision: 1.1.1.1.4.1 $
# $Date: 1998/01/16 12:36:05 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# --
#
#
#
require "rational.rb"
require "complex.rb"
require "matrix.rb"
class Integer
def gcd2(int)
a = self.abs
b = int.abs
a, b = b, a if a < b
pd_a = a.prime_division
pd_b = b.prime_division
gcd = 1
for pair in pd_a
as = pd_b.assoc(pair[0])
if as
gcd *= as[0] ** [as[1], pair[1]].min
end
end
return gcd
end
def Integer.from_prime_division(pd)
value = 1
for prime, index in pd
value *= prime**index
end
value
end
def prime_division
ps = Prime.new
value = self
pv = []
for prime in ps
count = 0
while (value1, mod = value.divmod(prime)
mod) == 0
value = value1
count += 1
end
if count != 0
pv.push [prime, count]
end
break if prime * prime >= value
end
if value > 1
pv.push [value, 1]
end
return pv
end
end
class Prime
include Enumerable
def initialize
@seed = 1
@primes = []
@counts = []
end
def succ
i = -1
size = @primes.size
while i < size
if i == -1
@seed += 1
i += 1
else
while @seed > @counts[i]
@counts[i] += @primes[i]
end
if @seed != @counts[i]
i += 1
else
i = -1
end
end
end
@primes.push @seed
@counts.push @seed + @seed
return @seed
end
alias next succ
def each
loop do
yield succ
end
end
end
class Fixnum
alias divmod! divmod
alias / rdiv
def divmod(other)
a = self.div(other)
b = self % other
return a,b
end
end
class Bignum
alias divmod! divmod
alias / rdiv
end
class Rational
Unify = true
def inspect
format "%s/%s", @numerator.inspect, @denominator.inspect
end
alias power! **
def ** (other)
if other.kind_of?(Rational)
if self < 0
return Complex(self, 0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
return Rational(0,1)
elsif self == 1
return Rational(1,1)
end
npd = @numerator.prime_division
dpd = @denominator.prime_division
if other < 0
other = -other
npd, dpd = dpd, npd
end
for elm in npd
elm[1] = elm[1] * other
if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
return Float(self) ** other
end
elm[1] = elm[1].to_i
end
for elm in dpd
elm[1] = elm[1] * other
if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
return Float(self) ** other
end
elm[1] = elm[1].to_i
end
num = Integer.from_prime_division(npd)
den = Integer.from_prime_division(dpd)
Rational(num,den)
elsif other.kind_of?(Integer)
if other > 0
num = @numerator ** other
den = @denominator ** other
elsif other < 0
num = @denominator ** -other
den = @numerator ** -other
elsif other == 0
num = 1
den = 1
end
Rational.new!(num, den)
elsif other.kind_of?(Float)
Float(self) ** other
else
x , y = other.coerce(self)
x ** y
end
end
def power2(other)
if other.kind_of?(Rational)
if self < 0
return Complex(self, 0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
return Rational(0,1)
elsif self == 1
return Rational(1,1)
end
dem = nil
x = self.denominator.to_f.to_i
neard = self.denominator.to_f ** (1.0/other.denominator.to_f)
loop do
if (neard**other.denominator == self.denominator)
dem = neaed
break
end
end
nearn = self.numerator.to_f ** (1.0/other.denominator.to_f)
Rational(num,den)
elsif other.kind_of?(Integer)
if other > 0
num = @numerator ** other
den = @denominator ** other
elsif other < 0
num = @denominator ** -other
den = @numerator ** -other
elsif other == 0
num = 1
den = 1
end
Rational.new!(num, den)
elsif other.kind_of?(Float)
Float(self) ** other
else
x , y = other.coerce(self)
x ** y
end
end
end
module Math
def sqrt(a)
if a.kind_of?(Complex)
abs = sqrt(a.real*a.real + a.image*a.image)
# if not abs.kind_of?(Rational)
# return a**Rational(1,2)
# end
x = sqrt((a.real + abs)/Rational(2))
y = sqrt((-a.real + abs)/Rational(2))
# if !(x.kind_of?(Rational) and y.kind_of?(Rational))
# return a**Rational(1,2)
# end
if a.image >= 0
Complex(x, y)
else
Complex(x, -y)
end
elsif a >= 0
rsqrt(a)
else
Complex(0,rsqrt(-a))
end
end
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
module_function :sqrt
module_function :rsqrt
end
class Complex
Unify = true
end