[前][次][番号順一覧][スレッド一覧]

ruby-changes:35687

From: marcandre <ko1@a...>
Date: Fri, 3 Oct 2014 12:44:26 +0900 (JST)
Subject: [ruby-changes:35687] marcandRe: r47769 (trunk): * lib/matrix.rb: Add hstack & vstack methods.

marcandre	2014-10-03 12:44:20 +0900 (Fri, 03 Oct 2014)

  New Revision: 47769

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47769

  Log:
    * lib/matrix.rb: Add hstack & vstack methods.
      Based on a patch by creasywuqiong. [Fix GH-344]

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/lib/matrix.rb
    trunk/test/matrix/test_matrix.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 47768)
+++ ChangeLog	(revision 47769)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Oct  3 12:42:15 2014  Marc-Andre Lafortune  <ruby-core@m...>
+
+	* 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@m...>
 
 	* lib/matrix.rb: Fix Matrix.rows copy bug.
Index: lib/matrix.rb
===================================================================
--- lib/matrix.rb	(revision 47768)
+++ lib/matrix.rb	(revision 47769)
@@ -45,6 +45,8 @@ end https://github.com/ruby/ruby/blob/trunk/lib/matrix.rb#L45
 # * 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 https://github.com/ruby/ruby/blob/trunk/lib/matrix.rb#L92
 # Matrix functions:
 # * #determinant
 # * #det
+# * #hstack(*matrices)
 # * #rank
 # * #round
 # * #trace
 # * #tr
 # * #transpose
 # * #t
+# * #vstack(*matrices)
 #
 # Matrix decompositions:
 # * #eigen
@@ -296,6 +300,51 @@ class Matrix https://github.com/ruby/ruby/blob/trunk/lib/matrix.rb#L300
   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.
   #
   def initialize(rows, column_count = rows[0].size)
@@ -1143,6 +1192,18 @@ class Matrix https://github.com/ruby/ruby/blob/trunk/lib/matrix.rb#L1192
   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
   # because of their lack of precision.
@@ -1223,6 +1284,18 @@ class Matrix https://github.com/ruby/ruby/blob/trunk/lib/matrix.rb#L1284
   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 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
   #++
Index: NEWS
===================================================================
--- NEWS	(revision 47768)
+++ NEWS	(revision 47769)
@@ -78,6 +78,8 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L78
       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:
Index: test/matrix/test_matrix.rb
===================================================================
--- test/matrix/test_matrix.rb	(revision 47768)
+++ test/matrix/test_matrix.rb	(revision 47769)
@@ -1,6 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/test/matrix/test_matrix.rb#L1
 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 https://github.com/ruby/ruby/blob/trunk/test/matrix/test_matrix.rb#L12
     @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 https://github.com/ruby/ruby/blob/trunk/test/matrix/test_matrix.rb#L504
     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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]