# Jordan Canonical Forms
#
# by Shin-ichiro Hara
#
# Version 1.00 (2001.11.01)
require "algebra/matrix-algebra"
module Algebra
class MatrixAlgebra
def jordan_form
Algebra::JordanForm.decompose(self).first
end
def jordan_form_info
Algebra::JordanForm.decompose(self)
end
end
class JordanForm
def initialize(body)
@body = body
end
def to_matrix(ring = Integer)
mat = nil
@body.each do |x, n|
if mat
mat = mat.dsum(jordan_block_u(ring, x, n))
else
mat = jordan_block_u(ring, x, n)
end
end
mat
end
alias to_matrix_u to_matrix
def to_matrix_l
to_matrix_u.transpose
end
def jordan_block_u(ring, x, n)
a = Algebra.SquareMatrix(ring, n)
a.matrix{|i, j|
if i == j
x
elsif i == j-1
ring.unity
else
ring.zero
end
}
end
def jordan_block_l(ring, x, n)
jordan_block_u(ring, x, n).transpose
end
def self.construct(elem_divs, facts, field, pfield)
a = []
elem_divs.each do |e|
facts.each do |f, n|
next if f.deg.zero? || n.zero?
f = f.convert_to(pfield)
g = e.convert_to(pfield)
raise "insufficient decomposition" unless f.deg <= 1
k = 0
while true
q, r = g.divmod f
break unless r.zero?
g = q
k += 1
end
a.push [-f[0], k] if k > 0
end
end
Algebra::JordanForm.new(a).to_matrix(field)
end
def self.decompose(m)
base_ring = m.ground
base_pring = Algebra.Polynomial(base_ring, "x")
base_alg = Algebra.SquareMatrix(base_pring, m.size)
me = m._char_matrix(base_alg).to_quint.e_diagonalize
elem_divs = me.body.diag
facts = Algebra::ElementaryDivisor.factorize(elem_divs)
dl = facts.last
field, modulus, facts, roots, elms = dl.pi.decompose(dl)
pfield = Algebra.Polynomial(field, "x")
pfm_alg = Algebra.SquareMatrix(pfield, m.size)
jm = Algebra::JordanForm.construct(elem_divs, facts, field, pfield)
jme = jm._char_matrix(pfm_alg).to_quint.e_diagonalize
mebody = pfm_alg.convert_from(me.body)
meright = pfm_alg.convert_from(me.right)
meleft = pfm_alg.convert_from(me.left)
sR = (meright * jme.righti).i2o.evaluateR(jm)
tL = (jme.lefti * meleft).i2o.evaluateL(jm)
[jm, tL, sR, field, modulus]
end
end
end
if $0 == __FILE__
j = Algebra::JordanForm.new([[2, 3], [-1, 2]])
j.to_matrix.display
end
syntax highlighted by Code2HTML, v. 0.9.1