Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Need a ruby math genius - potential ruby bug.

Reply
Thread Tools

Need a ruby math genius - potential ruby bug.

 
 
Todd S.
Guest
Posts: n/a
 
      01-26-2006
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"
--
Posted via http://www.ruby-forum.com/.


 
Reply With Quote
 
 
 
 
Todd S.
Guest
Posts: n/a
 
      01-26-2006
I should have included the results...

with the script run as is here is the output:

-----------
prevVert Vector[-0.007794, -0.283622, 0.532219]
curVert Vector[0.015525, -0.284744, 0.532219]
nextVert Vector[0.017021, -0.256189, 0.52561]
a: Vector[-0.023319, 0.00112200000000001, 0.0]
b0: Vector[0.001496, 0.028555, -0.00660899999999998]
l: Vector[-7.41529800000005e-06,
-0.000154115270999999, -0.000667552557]
l normalized: Vector[-0.0108228549457685, -0.224935966560048,
-0.97431343866259]
a normalized: Vector[-0.99884446633489, 0.0480596719939859, 0.0]
b1: Vector[0.0468251842814566, 0.973187586683846,
-0.225196188336926]
b2: Vector[0.0468251842814566, 0.973187586683846,
-0.225196188336926]
matrix: Matrix[[-0.0108228549457685, -0.224935966560048,
-0.97431343866259], [0.0468251842814566, 0.973187586683846,
-0.225196188336926], [-0.99884446633489, 0.0480596719939859, 0.0]]
mInverse: Matrix[[-128.0, -32.0, -0.99884446633489], [0.0, 2.0,
0.0480596719939859], [-0.97431343866259, -0.225196188336926,
-1.20157827529705e-18]]


With the variable "b2" commented out this is the ouput. Note the change
in mInverse...

-----------
prevVert Vector[-0.007794, -0.283622, 0.532219]
curVert Vector[0.015525, -0.284744, 0.532219]
nextVert Vector[0.017021, -0.256189, 0.52561]
a: Vector[-0.023319, 0.00112200000000001, 0.0]
b0: Vector[0.001496, 0.028555, -0.00660899999999998]
l: Vector[-7.41529800000005e-06,
-0.000154115270999999, -0.000667552557]
l normalized: Vector[-0.0108228549457685, -0.224935966560048,
-0.97431343866259]
a normalized: Vector[-0.99884446633489, 0.0480596719939859, 0.0]
b1: Vector[0.0468251842814566, 0.973187586683846,
-0.225196188336926]
matrix: Matrix[[-0.0108228549457685, -0.224935966560048,
-0.97431343866259], [0.0468251842814566, 0.973187586683846,
-0.225196188336926], [-0.99884446633489, 0.0480596719939859, 0.0]]
mInverse: Matrix[[-64.0, -16.0, -0.99884446633489], [0.0, 1.0,
0.0480596719939859], [-0.97431343866259, -0.225196188336926,
-2.40315655059409e-18]]


incidentally, I believe both of these results are incorrect.

--
Posted via http://www.ruby-forum.com/.


 
Reply With Quote
 
 
 
 
Andrew Dudzik
Guest
Posts: n/a
 
      01-26-2006
------=_Part_465_7687169.1138311364578
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

For starters, Vector#normalize(v) both changes v and returns it--you should
make a copy. Certainly doesn't explain the behavior, at least not in my
mind, but you should try it.

I'll give a shot at a more detailed analysis, but at the moment I can't get
the code to compile. It would help if you could post a .rb file.

On 1/26/06, Todd S. <(E-Mail Removed)> wrote:
>
> I should have included the results...
>
> with the script run as is here is the output:
>


------=_Part_465_7687169.1138311364578--


 
Reply With Quote
 
Matthew Moss
Guest
Posts: n/a
 
      01-26-2006
I think (offhand, didn't actually run your code) your problem is not
math but pass-by-reference vs. pass-by-value issues. Look at your
Vector.normalize function:

> def Vector.normalize(v)
> divisor =3D 0
> v.elements.each do |elem|
> divisor +=3D elem*elem
> end
>
> if divisor !=3D 0
> divisor =3D Math.sqrt(divisor);
> i =3D 0
> v.elements.each do |elem|
> v.elements[i] /=3D divisor
> i +=3D 1
> end
> end
> v
> end


v is not a copy of the parameter passed in but a reference to it. And
you are changing the elements of v directly.

> l =3D Vector.normalize(l)
> a =3D Vector.normalize(a)


In these two cases here, you don't notice the destructive behaviour,
since you assign the result to the parameter. But here:

> b2 =3D Vector.normalize(b1)


You are assigning the result to a different variable, but you've
actually changed b1 as well because it's not pass-by-value.


I would write a Vector normalize like such:

class Vector
def normalize
div =3D inner_product(self)
if div.zero?
self
else
self * (1 / Math.sqrt(div))
end
end

def Vector.normalize(v)
v.normalize
end
end


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Math.random() and Math.round(Math.random()) and Math.floor(Math.random()*2) VK Javascript 15 05-02-2010 03:43 PM
need help of regular expression genius GHUM Python 6 08-03-2006 12:21 PM
Wanted: Ruby/Rails Genius. Offered: The Opportunity to Develop an App That Matters! steve.jovanovic@gmail.com Ruby 0 01-22-2006 07:34 AM
Re: Is still math.h the C++ math library ? AciD_X C++ 4 04-01-2004 07:29 PM
Why can I not use: Math a=new Math(); chirs Java 18 03-02-2004 06:00 PM



Advertisments