Feature #2772 » matrix_bareiss.diff
lib/matrix.rb | ||
---|---|---|
#++
|
||
#
|
||
# Returns the determinant of the matrix. If the matrix is not square, the
|
||
# result is 0. This method's algorithm is Gaussian elimination method
|
||
# and using Numeric#quo(). Beware that using Float values, with their
|
||
# usual lack of precision, can affect the value returned by this method. Use
|
||
# Rational values or Matrix#det_e instead if this is important to you.
|
||
# Returns the determinant of the matrix.
|
||
# This method's algorithm is Bareiss algorithm, which has the nice properties
|
||
# of being exact for integers and minimizing the rounding error for floats.
|
||
#
|
||
# Matrix[[7,6], [3,9]].determinant
|
||
# => 45.0
|
||
# => 45
|
||
#
|
||
def determinant
|
||
return 0 unless square?
|
||
Matrix.Raise ErrDimensionMismatch unless square?
|
||
size = row_size
|
||
last = row_size - 1
|
||
a = to_a
|
||
det = 1
|
||
last_akk = 1
|
||
size.times do |k|
|
||
if (akk = a[k][k]) == 0
|
||
i = (k+1 ... size).find {|ii|
|
||
... | ... | |
return 0 if i.nil?
|
||
a[i], a[k] = a[k], a[i]
|
||
akk = a[k][k]
|
||
det *= -1
|
||
det = -det
|
||
end
|
||
(k + 1 ... size).each do |ii|
|
||
q = a[ii][k].quo(akk)
|
||
(k + 1 ... size).each do |j|
|
||
a[ii][j] -= a[k][j] * q
|
||
(k+1).upto(last) do |ii|
|
||
last.downto(k) do |j|
|
||
a[ii][j] = (akk * a[ii][j] - a[ii][k] * a[k][j]) / last_akk
|
||
end
|
||
end
|
||
det *= akk
|
||
det = det / last_akk * akk
|
||
last_akk = akk
|
||
end
|
||
det
|
||
end
|