Skip to content

Instantly share code, notes, and snippets.

@wfarr
Created March 4, 2009 10:28
Show Gist options
  • Select an option

  • Save wfarr/73786 to your computer and use it in GitHub Desktop.

Select an option

Save wfarr/73786 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'mathn'
def sign(x)
return 1 if x > 0
return -1 if x < 0
return 0
end
def prettify(matr)
return matr.map do |i|
if i <= 0.00001 && i >= -0.00001
"0"
else
"%.3f" % i
end
end
end
if ARGV[0].empty?
puts "Usage: ruby householder.rb '[[1,2,3],[4,5,6],[7,8,9]]'"
end
A = Matrix.rows(eval(ARGV[0]))
if A.column_size == 2 and A.row_size == 2
size = 2
elsif A.column_size == 3 and A.row_size == 3
size = 3
else
puts "Needs to be a 2x2 or 3x3 matrix."
end
a1 = A.column(0)
if size == 2
u = Vector[a1[0] + sign(a1[0]) * a1.r, a1[1]]
else
u = Vector[a1[0] + sign(a1[0]) * a1.r, a1[1], a1[2]]
end
norm_u_sqrd = u.r**2
if size == 2
h1 = Matrix.identity(2) - (u.covector.transpose * u.covector) * (2 / norm_u_sqrd)
else
h1 = Matrix.identity(3) - (u.covector.transpose * u.covector) * (2 / norm_u_sqrd)
end
big_a_1 = h1 * A
a2 = big_a_1.column(1)
if size == 2
a2 = Vector[ a2[1] ]
u2 = Vector[a2[0] + sign(a2[0]) * a2.r]
else
a2 = Vector[ a2[1], a2[2]]
u2 = Vector[a2[0] + sign(a2[0]) * a2.r, a2[1]]
end
norm_u2_sqrd = u2.r**2
if size == 2
h2 = Matrix.identity(1) - (u2.covector.transpose * u2.covector) * (2 / norm_u2_sqrd)
h2 = Matrix[ [1, 0], [0, h2[0,0]] ]
else
h2 = Matrix.identity(2) - (u2.covector.transpose * u2.covector) * (2 / norm_u2_sqrd)
h2 = Matrix[ [1, 0, 0], [0, h2[0,0], h2[0,1]], [0, h2[1,0], h2[1,1]] ]
end
big_a_2 = h2 * big_a_1
r = big_a_2
q = h1 * h2
qr = q * r
puts "A = #{A}\n= #{prettify(q)} * #{prettify(r)}\n= #{qr.map do |i| i.round end}"
## tex
preamble = <<-eos
\\documentclass[11pt,letterpaper]{article}
\\begin{document}
\\[A =
eos
closing = <<-eos
\\end{document}
eos
open_matr = "\\left[ \\begin{array}{#{size == 2 ? "cc" : "ccc"}}"
close_matr = "\\end{array} \\right]"
initial = ""
A.row_vectors.each do |v|
v.each2(v) do |i|
initial += "#{i}"
if i == v[-1] && v != A.row_vectors[-1]
initial += "\\\\"
elsif i != v[-1]
initial += "&"
end
end
end
q_tex = ""
q.row_vectors.each do |v|
v.each2(v) do |i|
q_tex += "%.3f" % i
if i == v[-1] && v != q.row_vectors[-1]
q_tex += "\\\\"
elsif i != v[-1]
q_tex += "&"
end
end
end
r_tex = ""
r.row_vectors.each do |v|
v.each2(v) do |i|
r_tex += "%.3f" % i
if i == v[-1] && v != r.row_vectors[-1]
r_tex += "\\\\"
elsif i != v[-1]
r_tex += "&"
end
end
end
qr_tex = ""
qr.row_vectors.each do |v|
v.each2(v) do |i|
qr_tex += "#{i.round}"
if i == v[-1] && v != qr.row_vectors[-1]
qr_tex += "\\\\"
else
qr_tex += "&"
end
end
end
content = [initial,q_tex,r_tex].map! {|str| open_matr + str + close_matr }.join('') + "\\]"
verify = "Verification: \\[" + open_matr + qr_tex + close_matr + "\\]"
to_write = preamble + content + verify + closing
f = File.new(ENV['HOME'] + '/householder.tex', 'w+')
f.write(to_write)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment