mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/matrix.rb: Add hstack & vstack methods.
Based on a patch by creasywuqiong. [Fix GH-344] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47769 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f59098d118
commit
5b46b07bf3
4 changed files with 115 additions and 0 deletions
|
@ -1,3 +1,8 @@
|
|||
Fri Oct 3 12:42:15 2014 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
|
||||
|
||||
* lib/matrix.rb: Add hstack & vstack methods.
|
||||
Based on a patch by creasywuqiong. [Fix GH-344]
|
||||
|
||||
Fri Oct 3 12:37:48 2014 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
|
||||
|
||||
* lib/matrix.rb: Fix Matrix.rows copy bug.
|
||||
|
|
2
NEWS
2
NEWS
|
@ -78,6 +78,8 @@ with all sufficient information, see the ChangeLog file.
|
|||
by deleting the specified row and column.
|
||||
* Matrix#cofactor(row, column) returns the (row, column) cofactor
|
||||
which is obtained by multiplying the first minor by (-1)**(row + column).
|
||||
* hstack and vstack are new instance and class methods to stack matrices
|
||||
horizontally and vertically.
|
||||
|
||||
* Method
|
||||
* New methods:
|
||||
|
|
|
@ -45,6 +45,8 @@ end
|
|||
# * Matrix.zero(n)
|
||||
# * Matrix.row_vector(row)
|
||||
# * Matrix.column_vector(column)
|
||||
# * Matrix.hstack(*matrices)
|
||||
# * Matrix.vstack(*matrices)
|
||||
#
|
||||
# To access Matrix elements/columns/rows/submatrices/properties:
|
||||
# * #[](i, j)
|
||||
|
@ -90,12 +92,14 @@ end
|
|||
# Matrix functions:
|
||||
# * #determinant
|
||||
# * #det
|
||||
# * #hstack(*matrices)
|
||||
# * #rank
|
||||
# * #round
|
||||
# * #trace
|
||||
# * #tr
|
||||
# * #transpose
|
||||
# * #t
|
||||
# * #vstack(*matrices)
|
||||
#
|
||||
# Matrix decompositions:
|
||||
# * #eigen
|
||||
|
@ -295,6 +299,51 @@ class Matrix
|
|||
new([[]]*row_count, column_count)
|
||||
end
|
||||
|
||||
#
|
||||
# Create a matrix by stacking matrices vertically
|
||||
#
|
||||
# x = Matrix[[1, 2], [3, 4]]
|
||||
# y = Matrix[[5, 6], [7, 8]]
|
||||
# Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
|
||||
#
|
||||
def Matrix.vstack(x, *matrices)
|
||||
raise TypeError, "Expected a Matrix, got a #{x.class}" unless x.is_a?(Matrix)
|
||||
result = x.send(:rows).map(&:dup)
|
||||
matrices.each do |m|
|
||||
raise TypeError, "Expected a Matrix, got a #{m.class}" unless m.is_a?(Matrix)
|
||||
if m.column_count != x.column_count
|
||||
raise ErrDimensionMismatch, "The given matrices must have #{x.column_count} columns, but one has #{m.column_count}"
|
||||
end
|
||||
result.concat(m.send(:rows))
|
||||
end
|
||||
new result, x.column_count
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Create a matrix by stacking matrices horizontally
|
||||
#
|
||||
# x = Matrix[[1, 2], [3, 4]]
|
||||
# y = Matrix[[5, 6], [7, 8]]
|
||||
# Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
|
||||
#
|
||||
def Matrix.hstack(x, *matrices)
|
||||
raise TypeError, "Expected a Matrix, got a #{x.class}" unless x.is_a?(Matrix)
|
||||
result = x.send(:rows).map(&:dup)
|
||||
total_column_count = x.column_count
|
||||
matrices.each do |m|
|
||||
raise TypeError, "Expected a Matrix, got a #{m.class}" unless m.is_a?(Matrix)
|
||||
if m.row_count != x.row_count
|
||||
raise ErrDimensionMismatch, "The given matrices must have #{x.row_count} rows, but one has #{m.row_count}"
|
||||
end
|
||||
result.each_with_index do |row, i|
|
||||
row.concat m.send(:rows)[i]
|
||||
end
|
||||
total_column_count += m.column_count
|
||||
end
|
||||
new result, total_column_count
|
||||
end
|
||||
|
||||
#
|
||||
# Matrix.new is private; use Matrix.rows, columns, [], etc... to create.
|
||||
#
|
||||
|
@ -1142,6 +1191,18 @@ class Matrix
|
|||
end
|
||||
alias det_e determinant_e
|
||||
|
||||
#
|
||||
# Returns a new matrix resulting by stacking horizontally
|
||||
# the receiver with the given matrices
|
||||
#
|
||||
# x = Matrix[[1, 2], [3, 4]]
|
||||
# y = Matrix[[5, 6], [7, 8]]
|
||||
# x.hstack(y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
|
||||
#
|
||||
def hstack(*matrices)
|
||||
self.class.hstack(self, *matrices)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the rank of the matrix.
|
||||
# Beware that using Float values can yield erroneous results
|
||||
|
@ -1223,6 +1284,18 @@ class Matrix
|
|||
end
|
||||
alias t transpose
|
||||
|
||||
#
|
||||
# Returns a new matrix resulting by stacking vertically
|
||||
# the receiver with the given matrices
|
||||
#
|
||||
# x = Matrix[[1, 2], [3, 4]]
|
||||
# y = Matrix[[5, 6], [7, 8]]
|
||||
# x.vstack(y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
|
||||
#
|
||||
def vstack(*matrices)
|
||||
self.class.vstack(self, *matrices)
|
||||
end
|
||||
|
||||
#--
|
||||
# DECOMPOSITIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
#++
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
require 'test/unit'
|
||||
require 'matrix'
|
||||
|
||||
class SubMatrix < Matrix
|
||||
end
|
||||
|
||||
class TestMatrix < Test::Unit::TestCase
|
||||
def setup
|
||||
@m1 = Matrix[[1,2,3], [4,5,6]]
|
||||
|
@ -9,6 +12,8 @@ class TestMatrix < Test::Unit::TestCase
|
|||
@m4 = Matrix[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
|
||||
@n1 = Matrix[[2,3,4], [5,6,7]]
|
||||
@c1 = Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
|
||||
@e1 = Matrix.empty(2,0)
|
||||
@e2 = Matrix.empty(0,3)
|
||||
end
|
||||
|
||||
def test_matrix
|
||||
|
@ -499,4 +504,34 @@ class TestMatrix < Test::Unit::TestCase
|
|||
end
|
||||
assert_equal(1, s1 ** o)
|
||||
end
|
||||
|
||||
def test_hstack
|
||||
assert_equal Matrix[[1,2,3,2,3,4,1,2,3], [4,5,6,5,6,7,4,5,6]],
|
||||
@m1.hstack(@n1, @m1)
|
||||
# Error checking:
|
||||
assert_raise(TypeError) { @m1.hstack(42) }
|
||||
assert_raise(TypeError) { Matrix.hstack(42, @m1) }
|
||||
assert_raise(Matrix::ErrDimensionMismatch) { @m1.hstack(Matrix.identity(3)) }
|
||||
assert_raise(Matrix::ErrDimensionMismatch) { @e1.hstack(@e2) }
|
||||
# Corner cases:
|
||||
assert_equal @m1, @m1.hstack
|
||||
assert_equal @e1, @e1.hstack(@e1)
|
||||
assert_equal Matrix.empty(0,6), @e2.hstack(@e2)
|
||||
assert_equal SubMatrix, SubMatrix.hstack(@e1).class
|
||||
end
|
||||
|
||||
def test_vstack
|
||||
assert_equal Matrix[[1,2,3], [4,5,6], [2,3,4], [5,6,7], [1,2,3], [4,5,6]],
|
||||
@m1.vstack(@n1, @m1)
|
||||
# Error checking:
|
||||
assert_raise(TypeError) { @m1.vstack(42) }
|
||||
assert_raise(TypeError) { Matrix.vstack(42, @m1) }
|
||||
assert_raise(Matrix::ErrDimensionMismatch) { @m1.vstack(Matrix.identity(2)) }
|
||||
assert_raise(Matrix::ErrDimensionMismatch) { @e1.vstack(@e2) }
|
||||
# Corner cases:
|
||||
assert_equal @m1, @m1.vstack
|
||||
assert_equal Matrix.empty(4,0), @e1.vstack(@e1)
|
||||
assert_equal @e2, @e2.vstack(@e2)
|
||||
assert_equal SubMatrix, SubMatrix.vstack(@e1).class
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue