|
require 'matrix'
|
|
class Matrix
|
|
def det_bareiss
|
|
Matrix.Raise ErrDimensionMismatch unless square?
|
|
|
|
size = row_size
|
|
last = row_size - 1
|
|
a = to_a
|
|
|
|
det = 1
|
|
last_akk = 1
|
|
size.times do |k|
|
|
if (akk = a[k][k]) == 0
|
|
i = (k+1 ... size).find {|ii|
|
|
a[ii][k] != 0
|
|
}
|
|
return 0 if i.nil?
|
|
a[i], a[k] = a[k], a[i]
|
|
akk = a[k][k]
|
|
det = -det
|
|
end
|
|
|
|
(k+1).upto(last) do |ii|
|
|
last.downto(k) do |j|
|
|
a[ii][j] = (akk * a[ii][j] - a[ii][k] * a[k][j]) / last_akk
|
|
end
|
|
end
|
|
det = det / last_akk * akk
|
|
last_akk = akk
|
|
end
|
|
det
|
|
end
|
|
|
|
def det_b
|
|
raise '!error: not square!' unless square?
|
|
n=row_size
|
|
a=to_a
|
|
(0...n).inject(1) do |det,k|
|
|
i=a.transpose[k].slice(k...n).index{|e| e!=0}
|
|
return 0 if i.nil? #not full ranked
|
|
if i!=0 then
|
|
a[k],a[k+i]=a[k+i],a[k]
|
|
det*=-1
|
|
end
|
|
for i in (k+1)...n
|
|
for j in (k...n).to_a.reverse
|
|
a[i][j]=a[k][k]*a[i][j]-a[i][k]*a[k][j]
|
|
a[i][j]/=a[k-1][k-1] if k!=0
|
|
end
|
|
end
|
|
det/=a[k-1][k-1] if k!=0
|
|
det*a[k][k]
|
|
end
|
|
end
|
|
end
|
|
|
|
class Matrix
|
|
#
|
|
# Creates a matrix of +row_size+ x +column_size+.
|
|
# It fills the values by calling the given block,
|
|
# passing the current row and column.
|
|
#
|
|
# m = Matrix.build(2, 4) {|row, col| col - row }
|
|
# => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
|
|
# m = Matrix.build(3) { rand }
|
|
# => a 3x3 matrix with random elements
|
|
#
|
|
def self.build(row_size, column_size = row_size)
|
|
raise ArgumentError if row_size < 0 || column_size < 0
|
|
return to_enum :build, row_size, column_size unless block_given?
|
|
rows = row_size.times.map do |i|
|
|
column_size.times.map do |j|
|
|
yield i, j
|
|
end
|
|
end
|
|
new rows, column_size
|
|
end
|
|
end
|
|
|
|
# require 'benchmark'
|
|
#
|
|
# n = 5
|
|
# sz = 44
|
|
# methods = [
|
|
# :det,
|
|
# # :det_b,
|
|
# :det_bareiss
|
|
# ]
|
|
#
|
|
# types = {
|
|
# Fixnum => 100,
|
|
# # Bignum => 2 << 80,
|
|
# Float => nil
|
|
# }
|
|
#
|
|
# res = []
|
|
# Benchmark.bmbm do |x|
|
|
# types.each do |mode, r|
|
|
# matrices = n.times.map do
|
|
# Matrix.build(sz) { rand(r) }
|
|
# end
|
|
# methods.each do |test|
|
|
# x.report("#{mode}: #{test}") { res << matrices.map(&test) }
|
|
# end
|
|
# end
|
|
# end
|