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