T
Todd S.
Please forgive the longish post, I've tried to boil down a bug to its
minimum and my hair is now nearly entirely pulled out.
The below code should be executable and requires only the "matrix.rb"
library that comes with a standard ruby install (At least I think it
does).
Under certain conditions, if I add a veriable to the script and never
use it the result of the procedure is changed. I cannot determin why.
minimum and my hair is now nearly entirely pulled out.
The below code should be executable and requires only the "matrix.rb"
library that comes with a standard ruby install (At least I think it
does).
Under certain conditions, if I add a veriable to the script and never
use it the result of the procedure is changed. I cannot determin why.
Code:
#!/usr/bin/env ruby
#=Synopsis
#Executable Script for debugging potential ruby floating point and/or
matrix error
require "matrix"
#Expand the Vector class from Matrix.rb to include:
# normalize, sum, delta, dot, cross, effectively_equal
#Defaults to a triplet but can contain an n-deminsional vector
# Currently most of these functions only operate on a 3-deminsional
vector.
class Vector
attr :elements, true
def normalize()
divisor = 0
@elements.each do |elem|
divisor += elem*elem
end
if divisor != 0
divisor = Math.sqrt(divisor);
i = 0
@elements.each do |elem|
@elements[i] /= divisor
i += 1
end
end
end
def Vector.normalize(v)
divisor = 0
v.elements.each do |elem|
divisor += elem*elem
end
if divisor != 0
divisor = Math.sqrt(divisor);
i = 0
v.elements.each do |elem|
v.elements[i] /= divisor
i += 1
end
end
v
end
def Vector.sum(u, v)
newVector = Vector[0,0,0]
i=0
u.elements.each do |uElem|
newVector.elements[i] = uElem.to_f + v.elements[i].to_f
i += 1
end
newVector
end
def Vector.delta(u, v)
newVector = Vector[0,0,0]
i=0
# puts "U: #{u} V: #{v}"
u.elements.each do |uElem|
newVector.elements[i] = uElem.to_f - v.elements[i].to_f
i += 1
end
newVector
end
def Vector.dot(u, v)
value = 0
i=0
u.elements.each do |uElem|
value += uElem.to_f * v.elements[i].to_f
i += 1
end
value
end
def Vector.cross(u, v)
n = Vector[0,0,0]
n.elements[0] = u.elements[1].to_f * v.elements[2].to_f -
u.elements[2].to_f * v.elements[1].to_f
n.elements[1] = u.elements[2].to_f * v.elements[0].to_f -
u.elements[0].to_f * v.elements[2].to_f
n.elements[2] = u.elements[0].to_f * v.elements[1].to_f -
u.elements[1].to_f * v.elements[0].to_f
n
end
def Vector.effectively_equal(u, v, epsilon = 0.000001)
i = 0
eq = TRUE
u.elements.each do |uElem|
if uElem.to_f - v.elements[i].to_f > epsilon
eq = FALSE
end
break if not eq
i += 1
end
eq
end
end # Vector class expansion
# Note, This error occurs when delta of curVert and prevVert have an
axis of zero.
# and have a resonably high percision.
curVert = Vector[0.015525, -0.284744, 0.532219]
prevVert = Vector[-0.007794, -0.283622, 0.532219]
nextVert = Vector[0.017021, -0.256189, 0.52561]
puts "-----------"
puts "prevVert \t#{prevVert}"
puts "curVert \t#{curVert}"
puts "nextVert \t#{nextVert}"
a = Vector.delta(prevVert,curVert)
puts "a: \t\t#{a}"
b0 = Vector.delta(nextVert,curVert)
puts "b0: \t\t#{b0}"
l = Vector.cross(a,b0)
puts "l: \t\t#{l}"
l = Vector.normalize(l)
puts "l normalized: \t#{l}"
a = Vector.normalize(a)
puts "a normalized: \t#{a}"
b1 = Vector.cross(l,a)
puts "b1: \t\t#{b1}"
# With b2 uncommented, even though it is not used in any function,
# it changes the output of mInverse by a factor of 2
# - Comment out the two lines below and rerun to see the change in
mInverse
#--------------v------------
b2 = Vector.normalize(b1)
puts "b2: \t\t#{b2}"
#--------------^------------
m = Matrix[l.elements,b1.elements,a.elements]
mInverse = m.inverse
puts "matrix: \t#{m}"
puts "mInverse: \t#{mInverse}\n\n"