From: "Todd S." Date: 2006-01-27T06:04:39+09:00 Subject: Need a ruby math genius - potential ruby bug. 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. [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" [/code] -- Posted via http://www.ruby-forum.com/.