Test questions: defining test structures as global variables and quick floating point reference
Misha Koshelev
misha680 at gmail.com
Thu Jul 15 09:09:01 CDT 2010
Dear All:
Thank you again for all your help.
To remind you, I am working on fixing:
http://bugs.winehq.org/show_bug.cgi?id=22918
And, as we are currently in code freeze, I have a GitHub repo here in
which I am making relevant changes:
http://github.com/misha680/wine/commits/master
I am going over my patches and had a few questions with which I'd
appreciate your help. Specifically, I'd like to know the answers, if
possible, sooner rather than later, so that in case things come up later
when I submit patches, I can simply reference the relevant wine-devel
discussions.
My questions are as follows.
1) In some tests, I need to declare global variables to store test data.
For example, in this patch:
http://github.com/misha680/wine/commit/17d2bb17d5868bd533dba6f1e1f9d8e6753b3f59
I declare these structures:
#define MAX_CYLINDER_VERTICES 1000 /* arbitrary */
D3DXVECTOR3 cylinder_test_vertex_data[MAX_CYLINDER_VERTICES];
1a) Is this kosher? The other option would be to dynamically allocate,
but this seems like a lot of overhead for a test. If I declare such
structures _within_ functions, I seem to have problems with memory
access to these structures (perhaps they are too big for stack)?
1b) I utilize similar structures in other tests. Currently, I declare a
separate structure for each test? Is it preferable to:
i) _declare a separate structure for each test, say:
#define MAX_CYLINDER_VERTICES 1000 /* arbitrary */
D3DXVECTOR3 cylinder_test_vertex_data[MAX_CYLINDER_VERTICES];
#define MAX_SPHERE_VERTICES 1000 /* arbitrary */
D3DXVECTOR3 sphere_test_vertex_data[MAX_CYLINDER_VERTICES];
or
ii) _declare a common structure for _all_ tests
#define MAX_ALL_TEST_VERTICES 1000 /* arbitrary */
D3DXVECTOR3 all_test_vertex_data[MAX_CYLINDER_VERTICES];
and use such a structure in all my tests?
2) Finally, as you have noticed, per Dan's advice, I have implemented
this function:
/*
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
* "I think the answer is 10,000 but since floating point math is
imperfect I’ll accept the maxUlps floats above and the maxUlps floats
below that value." */
static BOOLEAN AlmostEqual2sComplement(float A, float B, int maxUlps)
{
int aInt, bInt, intDiff;
/* Make sure maxUlps is non-negative and small enough that the
* default NAN won't compare as equal to anything. */
assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
aInt= *(int*)&A;
/* Make aInt lexicographically ordered as a twos-complement int */
if (aInt < 0)
aInt = 0x80000000 - aInt;
/* Make bInt lexicographically ordered as a twos-complement int */
bInt = *(int*)&B;
if (bInt < 0)
bInt = 0x80000000 - bInt;
intDiff = abs(aInt - bInt);
if (intDiff <= maxUlps)
return TRUE;
return FALSE;
}
It works very nicely, and is most accurate.
However, I have since noticed that mesh.c has the following functions
defined:
#define admitted_error 0.0001f
#define compare_vertex_sizes(type, exp) \
got=D3DXGetFVFVertexSize(type); \
ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
static BOOL compare(FLOAT u, FLOAT v)
{
return (fabs(u-v) < admitted_error);
}
static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
{
return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z,
v.z) );
}
These seem, if anything, much simpler, and, I have noticed in the case
of very complicated test data, more accurate.
I am going to change my code to use these latter functions, even though
they are not technically as good comparators as my current ones.
If there are any objections/comments re this, please let me know.
Thank you
Misha
More information about the wine-devel
mailing list