From 17fa2ce73a4ff6ba67dc92da5148b65ba3e3eeb5 Mon Sep 17 00:00:00 2001 From: marcandre Date: Sun, 11 Apr 2010 20:10:43 +0000 Subject: * lib/matrix.rb: New method Matrix.build [ruby-core:28272] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 ++++ lib/matrix.rb | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 64ef75244f..f7b9c4f9cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Mon Apr 12 05:10:20 2010 Marc-Andre Lafortune + + * lib/matrix.rb: New method Matrix.build [ruby-core:28272] + Mon Apr 12 03:45:25 2010 Marc-Andre Lafortune * lib/matrix.rb: Deprecate elements_to_{f/i/r} diff --git a/lib/matrix.rb b/lib/matrix.rb index a2a3e16da4..0f4633212c 100644 --- a/lib/matrix.rb +++ b/lib/matrix.rb @@ -48,6 +48,7 @@ end # * Matrix.[](*rows) # * Matrix.rows(rows, copy = true) # * Matrix.columns(columns) +# * Matrix.build(row_size, column_size, &block) # * Matrix.diagonal(*values) # * Matrix.scalar(n, value) # * Matrix.identity(n) @@ -165,6 +166,30 @@ class Matrix Matrix.rows(columns, false).transpose end + # + # Creates a matrix of size +row_size+ x +column_size+. + # It fills the values by calling the given block, + # passing the current row and column. + # Returns an enumerator if no block is given. + # + # 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 Matrix.build(row_size, column_size = row_size) + row_size = CoercionHelper.coerce_to_int(row_size) + column_size = CoercionHelper.coerce_to_int(column_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 + # # Creates a matrix where the diagonal elements are composed of +values+. # Matrix.diagonal(9, 5, -3) @@ -1074,7 +1099,7 @@ class Matrix # Private helper module - module CoercionHelper + module CoercionHelper # :nodoc: def apply_through_coercion(obj, oper) coercion = obj.coerce(self) raise TypeError unless coercion.is_a?(Array) && coercion.length == 2 @@ -1083,6 +1108,27 @@ class Matrix raise TypeError, "#{obj.inspect} can't be coerced into #{self.class}" end private :apply_through_coercion + + # Helper method to coerce a value into a specific class. + # Raises a TypeError if the coercion fails or the returned value + # is not of the right class. + # (from Rubinius) + def self.coerce_to(obj, cls, meth) # :nodoc: + return obj if obj.kind_of?(cls) + + begin + ret = obj.__send__(meth) + rescue Exception => e + raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \ + "(#{e.message})" + end + raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls + ret + end + + def self.coerce_to_int(obj) + coerce_to(obj, Integer, :to_int) + end end include CoercionHelper -- cgit v1.2.3