Double/Float precision & speed

BlitzMax Forums/BlitzMax Programming/Double/Float precision & speed

Tom(Posted 2005) [#1]
Hi,

I know Mark posted about this recently but I can't find the thread, I think he said there's no real reason not to use Double precision because all math is done internaly at 80bit precision anyway, and there's not much of a speed sifference, if any, correct?

Anyway...I'm currently using Float matrices, when moving a child entity in World space along 1 Axis, I'm seeing a slight change in another axis

example, a child cubes world position before and after translating it in the world X axis:

x,y,z before
-2.12874985, 4.13780737, -2.39440322

after moving it about 4 units in world X+
2.13110280, 4.13774347, -2.39438939

100 units on world X+
100.084061, 4.13051128, -2.39216566

Errors slowly creeping in on Y & Z

Just looking for some clarification from you experts!
(Floyd is the resident number-meister right? :)

Cheers
Tom


FlameDuck(Posted 2005) [#2]
This is expected (kinda), although I'm not entirely sure it's supposed to go that fast.

What you're doing is accumulating FP inaccuracies. Typical workarounds would be to implement some sort of error diffusion algorythm to evenly distribute FP errors, or to use real-time translation.


Tom(Posted 2005) [#3]
I converted all I've done so far to work with Doubles, and the amount of error still looks the same to me.

I'm using pure matrix math so far for rotation/translations/hierarchy, would using a Quaternion system prove to be better?


tonyg(Posted 2005) [#4]
Are you talking about this post...
http://www.blitzbasic.com/Community/posts.php?topic=42130
?
Could it be the float bug causing the problem?
Shouldn't be affecting doubles though (unless that's a different problem).


Tom(Posted 2005) [#5]
For curositys sake, here's the Move method from my entity system, and the 2 matrix/vector functions it calls. Maybe it's inevitable that there will be 'some' precision loss as there's a fair amount of calculations going on.

	Method Move(px:Float,py:Float,pz:Float,world:Byte=False)
		If world=False Or Self.gparent=Null ' No parent means local=world position
			
			' Set this entitys Matrix as the current GL Matrix
			' Do the translation, then update the entitys Matrix
			Self.setGLMatrix()
			glTranslatef(px,py,pz)
			Self.getGLMatrix()
		
		Else
			Local v:Vec3=Vec3.Create(px,py,pz)
			Local tmat:Mat4=Mat4.Create()
			tmat.Copy(mat) ' Copy this entitys GL Matrix
			
			'If the entity has a parent, multiply it's Matrix
			'all the way up the parent chain
			Local pa:gEntity=Self.gparent
			While pa
				tmat.Multiply(pa.mat)
				pa=pa.gparent
			Wend
			
			'transform the movement vector into World space
			v.iMatMulV(tmat.m)

			'As per local, apply the movement/translation
			Self.setGLMatrix()
			glTranslatef(v.x,v.y,v.z)
			Self.getGLMatrix()
		End If
	End Method
	
	
	' From my Mat4 Type.........
	Method Multiply(mat:Mat4)
		Local Tempmat:Float[16]
		Tempmat[0] = m[0] * mat.m[0] + m[1] * mat.m[4] + m[2] * mat.m[8] + m[3] * mat.m[12]
		Tempmat[1] = m[0] * mat.m[1] + m[1] * mat.m[5] + m[2] * mat.m[9] + m[3] * mat.m[13]
		Tempmat[2] = m[0] * mat.m[2] + m[1] * mat.m[6] + m[2] * mat.m[10] + m[3] * mat.m[14]
		Tempmat[3] = m[0] * mat.m[3] + m[1] * mat.m[7] + m[2] * mat.m[11] + m[3] * mat.m[15]
	
		Tempmat[4] = m[4] * mat.m[0] + m[5] * mat.m[4] + m[6] * mat.m[8] + m[7] * mat.m[12]
		Tempmat[5] = m[4] * mat.m[1] + m[5] * mat.m[5] + m[6] * mat.m[9] + m[7] * mat.m[13]
		Tempmat[6] = m[4] * mat.m[2] + m[5] * mat.m[6] + m[6] * mat.m[10] + m[7] * mat.m[14]
		Tempmat[7] = m[4] * mat.m[3] + m[5] * mat.m[7] + m[6] * mat.m[11] + m[7] * mat.m[15]
	
		Tempmat[8] = m[8] * mat.m[0] + m[9] * mat.m[4] + m[10] * mat.m[8] + m[11] * mat.m[12]
		Tempmat[9] = m[8] * mat.m[1] + m[9] * mat.m[5] + m[10] * mat.m[9] + m[11] * mat.m[13]
		Tempmat[10] = m[8] * mat.m[2] + m[9] * mat.m[6] + m[10] * mat.m[10] + m[11] * mat.m[14]
		Tempmat[11] = m[8] * mat.m[3] + m[9] * mat.m[7] + m[10] * mat.m[11] + m[11] * mat.m[15]
	
		Tempmat[12] = m[12] * mat.m[0] + m[13] * mat.m[4] + m[14] * mat.m[8] + m[15] * mat.m[12]
		Tempmat[13] = m[12] * mat.m[1] + m[13] * mat.m[5] + m[14] * mat.m[9] + m[15] * mat.m[13]
		Tempmat[14] = m[12] * mat.m[2] + m[13] * mat.m[6] + m[14] * mat.m[10] + m[15] * mat.m[14]
		Tempmat[15] = m[12] * mat.m[3] + m[13] * mat.m[7] + m[14] * mat.m[11] + m[15] * mat.m[15]
		For Local i:Byte=0 To 15
			m[i]=Tempmat[i]
		Next
	End Method
	
	' From my Vec3 Type
	Method iMatMulV(m:Float[])
		Local tmp:Float[3]
		tmp[0] = x*m[0] + y*m[1] + z*m[2]
		tmp[1] = x*m[4] + y*m[5] + z*m[6]
		tmp[2] = x*m[8] + y*m[9] + z*m[10]

		x = tmp[0]
		y = tmp[1]
		z = tmp[2]
	End Method



Who was John Galt?(Posted 2005) [#6]
No experience with OpenGL, but I'm surprised to see that level of inaccuracy creeping in.

Doubles will be slightly slower because you are pushing more data around even though the processor handles them the same internally.


fredborg(Posted 2005) [#7]
Tom, you say you've converted it to use doubles?

You're not talking about the code you posted, right?


Tom(Posted 2005) [#8]
No :) that's the Float version

I jsut went back to floats for now because the same creeping was there with Doubles, and Mark uses Floats for B3D, so it can't be all that bad.


ImaginaryHuman(Posted 2005) [#9]
Isn't a float basically a 32-bit binary number, with some kind of exponent and so on? Or is it 64bit? (I thought doubles were 64-bit)?


jhague(Posted 2005) [#10]
In general, FP math is done at the internal precision of the FPU. "Float" and "double precision" only matter when loading and storing values. A float is promoted to a double upon loading. A double is demoted to a float upon storing. So there's no FPU performance difference for using one over the other.

What does matter, however, is that doubles are 64-bit, and floats are 32-bit. If you have lots of data, then you save a tremendous amount of space by using floats. It's not just space mind you, but speed as well, because the additional cache misses caused by accessing twice as much memory can be very expensive on modern processors.