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:
|
||