Project

General

Profile

Feature #2772 » bareiss_test.rb

Performance test file - marcandre (Marc-Andre Lafortune), 02/21/2010 06:16 AM

 
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
(2-2/3)