summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--lib/matrix.rb173
2 files changed, 66 insertions, 111 deletions
diff --git a/ChangeLog b/ChangeLog
index 76949b93ea..eae7d53930 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Sep 16 13:30:20 2009 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
+
+ * lib/matrix.rb: trivial optimizations
+
Tue Sep 15 15:32:16 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/Makefile.sub (RDOCTARGET): the meaning of this macro was changed
diff --git a/lib/matrix.rb b/lib/matrix.rb
index 90b9587efe..8c4ea07bcc 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -142,10 +142,8 @@ class Matrix
#
#
def Matrix.columns(columns)
- rows = (0 .. columns[0].size - 1).collect {
- |i|
- (0 .. columns.size - 1).collect {
- |j|
+ rows = (0 ... columns[0].size).collect {|i|
+ (0 ... columns.size).collect {|j|
columns[j][i]
}
}
@@ -161,8 +159,7 @@ class Matrix
#
def Matrix.diagonal(*values)
size = values.size
- rows = (0 .. size - 1).collect {
- |j|
+ rows = (0 ... size).collect {|j|
row = Array.new(size).fill(0, 0, size)
row[j] = values[j]
row
@@ -287,11 +284,9 @@ class Matrix
# Returns row vector number +i+ of the matrix as a Vector (starting at 0 like
# an array). When a block is given, the elements of that vector are iterated.
#
- def row(i) # :yield: e
+ def row(i, &block) # :yield: e
if block_given?
- for e in @rows[i]
- yield e
- end
+ @rows[i].each(&block)
else
Vector.elements(@rows[i])
end
@@ -304,13 +299,11 @@ class Matrix
#
def column(j) # :yield: e
if block_given?
- 0.upto(row_size - 1) do
- |i|
+ row_size.times do |i|
yield @rows[i][j]
end
else
- col = (0 .. row_size - 1).collect {
- |i|
+ col = (0 ... row_size).collect {|i|
@rows[i][j]
}
Vector.elements(col, false)
@@ -349,10 +342,7 @@ class Matrix
size_col = param[1].end - from_col
size_col += 1 unless param[1].exclude_end?
when 4
- from_row = param[0]
- size_row = param[1]
- from_col = param[2]
- size_col = param[3]
+ from_row, size_row, from_col, size_col = param
else
Matrix.Raise ArgumentError, param.inspect
end
@@ -413,9 +403,8 @@ class Matrix
#
def compare_by_row_vectors(rows, comparison = :==)
return false unless @rows.size == rows.size
-
- 0.upto(@rows.size - 1) do
- |i|
+
+ @rows.size.times do |i|
return false unless @rows[i].send(comparison, rows[i])
end
true
@@ -433,13 +422,7 @@ class Matrix
# Returns a hash-code for the matrix.
#
def hash
- value = 0
- for row in @rows
- for e in row
- value ^= e.hash
- end
- end
- return value
+ @rows.hash
end
#--
@@ -469,14 +452,11 @@ class Matrix
return r.column(0)
when Matrix
Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
-
- rows = (0 .. row_size - 1).collect {
- |i|
- (0 .. m.column_size - 1).collect {
- |j|
+
+ rows = (0 ... row_size).collect {|i|
+ (0 ... m.column_size).collect {|j|
vij = 0
- 0.upto(column_size - 1) do
- |k|
+ column_size.times do |k|
vij += self[i, k] * m[k, j]
end
vij
@@ -508,11 +488,9 @@ class Matrix
end
Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
-
- rows = (0 .. row_size - 1).collect {
- |i|
- (0 .. column_size - 1).collect {
- |j|
+
+ rows = (0 ... row_size).collect {|i|
+ (0 ... column_size).collect {|j|
self[i, j] + m[i, j]
}
}
@@ -538,11 +516,9 @@ class Matrix
end
Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
-
- rows = (0 .. row_size - 1).collect {
- |i|
- (0 .. column_size - 1).collect {
- |j|
+
+ rows = (0 ... row_size).collect {|i|
+ (0 ... column_size).collect {|j|
self[i, j] - m[i, j]
}
}
@@ -590,13 +566,13 @@ class Matrix
# Not for public consumption?
#
def inverse_from(src)
- size = row_size - 1
+ size = row_size
a = src.to_a
-
- for k in 0..size
+
+ size.times do |k|
i = k
akk = a[k][k].abs
- for j in (k+1)..size
+ (k+1 ... size).each do |j|
v = a[j][k].abs
if v > akk
i = j
@@ -609,28 +585,24 @@ class Matrix
@rows[i], @rows[k] = @rows[k], @rows[i]
end
akk = a[k][k]
-
- for i in 0 .. size
+
+ size.times do |i|
next if i == k
q = a[i][k] / akk
a[i][k] = 0
-
- (k + 1).upto(size) do
- |j|
+
+ (k + 1 ... size).each do |j|
a[i][j] -= a[k][j] * q
end
- 0.upto(size) do
- |j|
+ size.times do |j|
@rows[i][j] -= @rows[k][j] * q
end
end
-
- (k + 1).upto(size) do
- |j|
+
+ (k + 1 ... size).each do |j|
a[k][j] /= akk
end
- 0.upto(size) do
- |j|
+ size.times do |j|
@rows[k][j] /= akk
end
end
@@ -684,13 +656,12 @@ class Matrix
#
def determinant
return 0 unless square?
-
- size = row_size - 1
+
+ size = row_size
a = to_a
det = 1
- k = 0
- begin
+ size.times do |k|
if (akk = a[k][k]) == 0
i = k
begin
@@ -700,20 +671,19 @@ class Matrix
akk = a[k][k]
det *= -1
end
- (k + 1).upto(size) do
- |i|
+
+ (k + 1 ... size).each do |i|
q = a[i][k] / akk
- (k + 1).upto(size) do
- |j|
+ (k + 1 ... size).each do |j|
a[i][j] -= a[k][j] * q
end
end
det *= akk
- end while (k += 1) <= size
+ end
det
end
alias det determinant
-
+
#
# Returns the rank of the matrix. Beware that using Float values, with their
# usual lack of precision, can affect the value returned by this method. Use
@@ -732,17 +702,17 @@ class Matrix
a_row_size = row_size
end
rank = 0
- k = 0
- begin
+ a_column_size.times do |k|
if (akk = a[k][k]) == 0
i = k
exists = true
- begin
- if (i += 1) > a_column_size - 1
+ loop do
+ if (i += 1) >= a_column_size
exists = false
break
end
- end while a[i][k] == 0
+ break unless a[i][k] == 0
+ end
if exists
a[i], a[k] = a[k], a[i]
akk = a[k][k]
@@ -756,8 +726,7 @@ class Matrix
end
end while a[k][i] == 0
if exists
- k.upto(a_column_size - 1) do
- |j|
+ (k ... a_column_size).each do |j|
a[j][k], a[j][i] = a[j][i], a[j][k]
end
akk = a[k][k]
@@ -766,16 +735,15 @@ class Matrix
end
end
end
- (k + 1).upto(a_row_size - 1) do
- |i|
+
+ (k + 1 ... a_row_size).each do |i|
q = a[i][k] / akk
- (k + 1).upto(a_column_size - 1) do
- |j|
+ (k + 1... a_column_size).each do |j|
a[i][j] -= a[k][j] * q
end
end
rank += 1
- end while (k += 1) <= a_column_size - 1
+ end
return rank
end
@@ -786,8 +754,7 @@ class Matrix
#
def trace
tr = 0
- 0.upto(column_size - 1) do
- |i|
+ column_size.times do |i|
tr += @rows[i][i]
end
tr
@@ -829,29 +796,25 @@ class Matrix
# Returns an array of the row vectors of the matrix. See Vector.
#
def row_vectors
- rows = (0 .. row_size - 1).collect {
- |i|
+ (0 ... row_size).collect {|i|
row(i)
}
- rows
end
#
# Returns an array of the column vectors of the matrix. See Vector.
#
def column_vectors
- columns = (0 .. column_size - 1).collect {
- |i|
+ (0 ... column_size).collect {|i|
column(i)
}
- columns
end
#
# Returns an array of arrays that describe the rows of the matrix.
#
def to_a
- @rows.collect{|row| row.collect{|e| e}}
+ @rows.collect{|row| row.dup}
end
#--
@@ -1061,8 +1024,7 @@ class Vector
#
def each2(v) # :yield: e1, e2
Vector.Raise ErrDimensionMismatch if size != v.size
- 0.upto(size - 1) do
- |i|
+ size.times do |i|
yield @elements[i], v[i]
end
end
@@ -1073,8 +1035,7 @@ class Vector
#
def collect2(v) # :yield: e1, e2
Vector.Raise ErrDimensionMismatch if size != v.size
- (0 .. size - 1).collect do
- |i|
+ (0 ... size).collect do |i|
yield @elements[i], v[i]
end
end
@@ -1200,11 +1161,8 @@ class Vector
#
# Like Array#collect.
#
- def collect # :yield: e
- els = @elements.collect {
- |v|
- yield v
- }
+ def collect(&block) # :yield: e
+ els = @elements.collect(&block)
Vector.elements(els, false)
end
alias map collect
@@ -1212,11 +1170,8 @@ class Vector
#
# Like Vector#collect2, but returns a Vector instead of an Array.
#
- def map2(v) # :yield: e1, e2
- els = collect2(v) {
- |v1, v2|
- yield v1, v2
- }
+ def map2(v, &block) # :yield: e1, e2
+ els = collect2(v, &block)
Vector.elements(els, false)
end
@@ -1225,11 +1180,7 @@ class Vector
# Vector[5,8,2].r => 9.643650761
#
def r
- v = 0
- for e in @elements
- v += e*e
- end
- return Math.sqrt(v)
+ Math.sqrt(@elements.inject(0) {|v, e| v + e*e})
end
#--