diff options
author | marcandre <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-04-11 20:10:43 +0000 |
---|---|---|
committer | marcandre <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-04-11 20:10:43 +0000 |
commit | 17fa2ce73a4ff6ba67dc92da5148b65ba3e3eeb5 (patch) | |
tree | ece414f76852dfbf5706a32494e483dfcf59a618 | |
parent | 3a1c0be67fac516822d83c1fe628a32c7782a4a8 (diff) | |
download | ruby-17fa2ce73a4ff6ba67dc92da5148b65ba3e3eeb5.tar.gz |
* 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
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | lib/matrix.rb | 48 |
2 files changed, 51 insertions, 1 deletions
@@ -1,3 +1,7 @@ +Mon Apr 12 05:10:20 2010 Marc-Andre Lafortune <ruby-core@marc-andre.ca> + + * lib/matrix.rb: New method Matrix.build [ruby-core:28272] + Mon Apr 12 03:45:25 2010 Marc-Andre Lafortune <ruby-core@marc-andre.ca> * 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 # * <tt> Matrix.[](*rows) </tt> # * <tt> Matrix.rows(rows, copy = true) </tt> # * <tt> Matrix.columns(columns) </tt> +# * <tt> Matrix.build(row_size, column_size, &block) </tt> # * <tt> Matrix.diagonal(*values) </tt> # * <tt> Matrix.scalar(n, value) </tt> # * <tt> Matrix.identity(n) </tt> @@ -166,6 +167,30 @@ class Matrix 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) # => 9 0 0 @@ -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 |