Horde3D

Next-Generation Graphics Engine
It is currently 22.11.2024, 00:30

All times are UTC + 1 hour




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: 04.06.2008, 23:43 
Offline

Joined: 15.05.2008, 05:32
Posts: 46
Location: California
These come in handy from time to time...

Code:
   bool operator == (const Matrix4f& rhs) const
   {
      for( int i=0; i<sizeof(x)/sizeof(x[0]); ++i )
      {
         if( x[i]!=rhs.x[i] ) return false;
      }
      return true;
   }

   bool operator != (const Matrix4f& rhs) const
   {
      return !(*this==rhs);
   }


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 02:44 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
roarflolo wrote:
These come in handy from time to time...
Maybe, as long as you don't actually use them for anything ;)

Floating point comparisons are useless, so it would be quicker to do a memcmp() on the whole matrix (the results will be identical most of the time, and equally invalid).

All either one will tell you is whether the 2 matrices are in fact bitwise copies of the same matrix - even if you just multiply and then divide by 2, floating point errors will break the comparison.

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 02:56 
Offline

Joined: 18.05.2008, 17:47
Posts: 96
hate float
but the code will work fine most of the time
use a delta value maybe
if( abs(x[i] - rhs.x[i]) < delta ) yey();
else boo();


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 03:07 
Offline

Joined: 15.05.2008, 05:32
Posts: 46
Location: California
I know that, you know that, everyone who has worked with floats for 30 seconds knows that :roll:

I guess the point is that the operators are missing from the matrix class which isn't encapsulated (not that any of the other code is either) so you end up with a lot of different stabs at the same 'problem', some loop through the array, some use memcmp, some do some epsilon variation...

But whatever...


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 03:18 
Offline

Joined: 18.05.2008, 17:47
Posts: 96
you are right those operators only exist for vec3f
maybe duplicate the behavior for matrix4f
edit:
another method :P
m=m1-m2;
for(i=1;i<16;i++) m.x[0]+=m.x[i];
return m.x[0]<0.001f&&m.x[0]>-0.001f;


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 04:11 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
"Incorrect" float == operators are still useful on occasion. The rule with floats isn't "dont use ==", it's "make sure you know the pitfalls when using ==".
Code:
const static Matrix4f matIdentity...

Matrix4f myMat = matIdentity;
if( ... )
   myMat *= ...

bool wasModified = myMat != matIdentity;
Of course, with my simple example there are other solutions... just trying to point out that float's == does have it's uses :wink:


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 04:20 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
DarkAngel wrote:
"Incorrect" float == operators are still useful on occasion. The rule with floats isn't "dont use ==", it's "make sure you know the pitfalls when using ==".
Code:
const static Matrix4f matIdentity...

Matrix4f myMat = matIdentity;
if( ... )
   myMat *= ...

bool wasModified = myMat != matIdentity;
Of course, with my simple example there are other solutions... just trying to point out that float's == does have it's uses :wink:
Even if your 'if' clause multiplied myMat by the unit matrix, there is still a good chance that it absorbed some error, so the best you are able to tell is whether or not the if condition was true (which is obviously already known, inside the if statement). [edit: nm, you pointed that out yourself]

My point is that if comparison operators are placed in the core, they will be used - more often than not incorrectly. A comparison function that takes a delta as an argument would make perfect sense, but I don't think that operator == is a good candidate (the same goes for the vector class).

I do wonder how useful an operation matrix comparison is in general - apart from armature simplification, nothing springs to mind that couldn't be accomplished in other ways.

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 04:30 
Offline

Joined: 15.05.2008, 05:32
Posts: 46
Location: California
Since I started this: I'm using the == operator to compare sampled node matrices to see if there is actually some movement going on. In this case the input data and the code used to generate the matrices are the same so the result will be equal bit-by-bit.


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 05:04 
Offline

Joined: 08.11.2006, 03:10
Posts: 384
Location: Australia
roarflolo wrote:
In this case the input data and the code used to generate the matrices are the same so the result will be equal bit-by-bit.

Even if the code and input is the same, the bit-wise results depends on other factors outside of your control, such as how how many CPU context switches occurred and at what times. -- Even moving a float from a CPU register to memory and then back to the register again can introduce small discrepancies.


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 09:33 
Offline

Joined: 15.05.2008, 05:32
Posts: 46
Location: California
Really? What exactly isn't stored/restored? Which operating systems?


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 10:50 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
Really funny is this code:
Code:
double a = 1.0;
a /= 10.0;
double b = a;

// do something else here
// ...

if(a == b)
{
    printf("ok\n");
}
else
{
    printf("fail\n");
}

On my Athlon 64 X2, 64 bit Linux I always get "ok" independent of compiler options when using gcc 3.4 or 4.2. But on a 32 system with a Pentium 4 I get on some optimization settings "fail". This also depends on how much code is executed between the if and the comparison. The comparison fails when exactly one of a and b is written to memory and the other one is not - under the condition that the register precision is higher than 64bit. But this problam can be solved :)
Different implementations of the math library complicate this since the math library may take different code paths depending on the CPU and other conditions if you use sin, cos, ...

So avoid using == and !=. Even using an epsilon is often problematic if you don't know how to choose a good one since it often depends on the input values.


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 13:34 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
roarflolo wrote:
Really? What exactly isn't stored/restored? Which operating systems?
The IEEE specification doesn't fully specify all bits in a float for all values. Many architectures/implementations have multiple different representations of zero (and often many for -0 as well), INF and NAN are also quite badly defined.

Also remember that x86 and newer actually deal with 80-bit floats, and truncate before storing in a 32-bit memory location, which can cause problems of its own.

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
PostPosted: 05.06.2008, 14:07 
Offline

Joined: 14.04.2008, 15:06
Posts: 183
Location: Germany
swiftcoder wrote:
The IEEE specification doesn't fully specify all bits in a float for all values. Many architectures/implementations have multiple different representations of zero (and often many for -0 as well), INF and NAN are also quite badly defined.

As long as IEEE754 is implemented correctly (for example the math on Cell BE is not IEEE754 compliant) all results but NANs are bit identical - when using the same modes like rounding and number of bits. The meaning of NAN, quiet or signaling, is exactly defined - only the bit pattern may vary between architectures. But as long as you check the meaning on the same architecture as the value was produced you get identical results.
x86 FPU and SSE differ in regard to subnormal numbers, I assume the FPU is non-compliant in this regard since PowerPC yields the same results as SSE in my tests.

That does not mean that one gets the same results on two different architectures (even if both are x86) without special precautions.

swiftcoder wrote:
Also remember that x86 and newer actually deal with 80-bit floats, and truncate before storing in a 32-bit memory location, which can cause problems of its own.

When you are using SSE that's not true. Then it's depending on the instruction 32 bit / 64 bit.
x86_64 by default uses 64 bit registers instead of the old FPU registers to do math.


Most of the time you can ignore these problems, but it explains why comparing two floats using == or != is a bad idea. If you are writing a lock-stepped simulation like an RTS then you have to take care of these issues. Another case would be a replay system when you are storing only inputs to drive the simulation.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 19 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group