Bug #1532 » a_matrix_creation.diff
lib/matrix.rb | ||
---|---|---|
# arithmetically and algebraically, and determining their mathematical properties (trace, rank,
|
||
# inverse, determinant).
|
||
#
|
||
# Note that although matrices should theoretically be rectangular, this is not
|
||
# enforced by the class.
|
||
# Note that matrices must be rectangular, otherwise an ErrDimensionMismatch is raised.
|
||
#
|
||
# Also note that the determinant of integer matrices may be incorrectly calculated unless you
|
||
# Also note that the determinant of integer matrices may be approximated unless you
|
||
# also <tt>require 'mathn'</tt>. This may be fixed in the future.
|
||
#
|
||
# == Method Catalogue
|
||
... | ... | |
# instance creations
|
||
private_class_method :new
|
||
attr_reader :rows
|
||
protected :rows
|
||
#
|
||
# Creates a matrix where each argument is a row.
|
||
... | ... | |
# -1 66
|
||
#
|
||
def Matrix.[](*rows)
|
||
new(:init_rows, rows, false)
|
||
Matrix.rows(rows, false)
|
||
end
|
||
#
|
||
... | ... | |
# -1 66
|
||
#
|
||
def Matrix.rows(rows, copy = true)
|
||
new(:init_rows, rows, copy)
|
||
rows = Matrix.convert_to_array(rows)
|
||
rows.map! do |row|
|
||
Matrix.convert_to_array(row, copy)
|
||
end
|
||
size = (rows[0] || []).size
|
||
rows.each do |row|
|
||
Matrix.Raise ErrDimensionMismatch, "element size differs (#{row.size} should be #{size})" unless row.size == size
|
||
end
|
||
new rows
|
||
end
|
||
#
|
||
... | ... | |
# 93 66
|
||
#
|
||
def Matrix.columns(columns)
|
||
rows = (0 ... columns[0].size).collect {|i|
|
||
(0 ... columns.size).collect {|j|
|
||
columns[j][i]
|
||
}
|
||
}
|
||
Matrix.rows(rows, false)
|
||
Matrix.rows(columns, false).transpose
|
||
end
|
||
#
|
||
... | ... | |
row[j] = values[j]
|
||
row
|
||
}
|
||
rows(rows, false)
|
||
new rows
|
||
end
|
||
#
|
||
... | ... | |
# => 4 5 6
|
||
#
|
||
def Matrix.row_vector(row)
|
||
case row
|
||
when Vector
|
||
Matrix.rows([row.to_a], false)
|
||
when Array
|
||
Matrix.rows([row.dup], false)
|
||
else
|
||
Matrix.rows([[row]], false)
|
||
end
|
||
row = Matrix.convert_to_array(row)
|
||
new [row]
|
||
end
|
||
#
|
||
... | ... | |
# 6
|
||
#
|
||
def Matrix.column_vector(column)
|
||
case column
|
||
when Vector
|
||
Matrix.columns([column.to_a])
|
||
when Array
|
||
Matrix.columns([column])
|
||
else
|
||
Matrix.columns([[column]])
|
||
end
|
||
column = Matrix.convert_to_array(column)
|
||
new [column].transpose
|
||
end
|
||
#
|
||
# This method is used by the other methods that create matrices, and is of no
|
||
# use to general users.
|
||
# Matrix.new is private; use Matrix.rows, columns, [], etc... to create.
|
||
#
|
||
def initialize(init_method, *argv)
|
||
self.send(init_method, *argv)
|
||
def initialize(rows)
|
||
# No checking is done at this point. rows must be an Array of Arrays.
|
||
@rows = rows
|
||
end
|
||
def init_rows(rows, copy)
|
||
if copy
|
||
@rows = rows.collect{|row| row.dup}
|
||
else
|
||
@rows = rows
|
||
end
|
||
self
|
||
def new(rows) # :nodoc:
|
||
Matrix.send(:new, rows) # bypass privacy of Matrix.new
|
||
end
|
||
private :init_rows
|
||
private :new
|
||
#
|
||
# Returns element (+i+,+j+) of the matrix. That is: row +i+, column +j+.
|
||
... | ... | |
end
|
||
#
|
||
# Returns the number of columns. Note that it is possible to construct a
|
||
# matrix with uneven columns (e.g. Matrix[ [1,2,3], [4,5] ]), but this is
|
||
# mathematically unsound. This method uses the first row to determine the
|
||
# result.
|
||
# Returns the number of columns.
|
||
#
|
||
def column_size
|
||
@rows[0].size
|
||
... | ... | |
#
|
||
def collect(&block) # :yield: e
|
||
rows = @rows.collect{|row| row.collect(&block)}
|
||
Matrix.rows(rows, false)
|
||
new(rows)
|
||
end
|
||
alias map collect
|
||
... | ... | |
rows = @rows[from_row, size_row].collect{|row|
|
||
row[from_col, size_col]
|
||
}
|
||
Matrix.rows(rows, false)
|
||
new(rows)
|
||
end
|
||
#--
|
||
... | ... | |
end
|
||
#
|
||
# Returns +true+ is this is a square matrix. See note in column_size about this
|
||
# being unreliable, though.
|
||
# Returns +true+ is this is a square matrix.
|
||
#
|
||
def square?
|
||
column_size == row_size
|
||
... | ... | |
#
|
||
# Returns a clone of the matrix, so that the contents of each do not reference
|
||
# identical objects.
|
||
# There should be no good reason to do this since Matrices are immutable.
|
||
#
|
||
def clone
|
||
Matrix.rows(@rows)
|
||
new(@rows.map{|row| row.dup})
|
||
end
|
||
#
|
||
... | ... | |
e * m
|
||
}
|
||
}
|
||
return Matrix.rows(rows, false)
|
||
return new(rows)
|
||
when Vector
|
||
m = Matrix.column_vector(m)
|
||
r = self * m
|
||
... | ... | |
end
|
||
}
|
||
}
|
||
return Matrix.rows(rows, false)
|
||
return new(rows)
|
||
else
|
||
x, y = m.coerce(self)
|
||
return x * y
|
||
... | ... | |
self[i, j] + m[i, j]
|
||
}
|
||
}
|
||
Matrix.rows(rows, false)
|
||
new(rows)
|
||
end
|
||
#
|
||
... | ... | |
self[i, j] - m[i, j]
|
||
}
|
||
}
|
||
Matrix.rows(rows, false)
|
||
new(rows)
|
||
end
|
||
#
|
||
... | ... | |
e / other
|
||
}
|
||
}
|
||
return Matrix.rows(rows, false)
|
||
return new(rows)
|
||
when Matrix
|
||
return self * other.inverse
|
||
else
|
||
... | ... | |
# 2 4 6
|
||
#
|
||
def transpose
|
||
Matrix.columns(@rows)
|
||
new @rows.transpose
|
||
end
|
||
alias t transpose
|
||
... | ... | |
"Matrix"+@rows.inspect
|
||
end
|
||
#
|
||
# Converts the obj to an Array. If copy is set to true
|
||
# a copy of obj will be made if necessary.
|
||
#
|
||
def Matrix.convert_to_array(obj, copy = false)
|
||
case obj
|
||
when Array
|
||
copy ? obj.dup : obj
|
||
when Vector
|
||
obj.to_a
|
||
else
|
||
begin
|
||
converted = obj.to_ary
|
||
rescue Exception => e
|
||
raise TypeError, "can't convert #{obj.class} into an Array (#{e.message})"
|
||
end
|
||
raise TypeError, "#{obj.class}#to_ary should return an Array" unless converted.is_a? Array
|
||
converted
|
||
end
|
||
end
|
||
# Private CLASS
|
||
class Scalar < Numeric # :nodoc:
|