d3dx9: Implement D3DXFloat32To16Array and D3DXFloat16To32Array. (try 2)

Misha Koshelev misha680 at gmail.com
Sat Feb 26 19:50:02 CST 2011


On Sat, Feb 26, 2011 at 4:48 PM, Juan Lang <juan.lang at gmail.com> wrote:
> Hi Misha,
>
>> My own (very unhelpful) diagnosis of the pattern is that, for the
>> mantissa values:
>>
>> 2018.5 should round to 2018
>> 2019.5 should round to 2020
>
> The pattern appears to be "round half to even", which you may read
> about on Wikipedia:
> http://en.wikipedia.org/wiki/Rounding#Round_half_to_even
> --Juan
>

Thanks Juan. I have implemented this in the patch.

I am, unfortunately, still pretty stumped. There are quite a few cases
per Matteo's wonderful rounding code for truncation of very small (?)
numbers where rounding should _not_ occur.

I have included relevant output from running make math.ok for those cases.

Note, that it is not the specific mantissa #'s per se (I checked), not
even combinations of mantissa #'s and exp's, and not mantissa #'s and
exp's and <= 0.25f difference between ((unsigned int) tmp) and
(((unsigned int) tmp) & 0x3ff) - I checked all these.

There is apparently some pattern in the original single #'s themselves
that I am not seeing.

If anyone has a keener eye than I let me know.

Also, I am assuming a stub of this function would actually not be
accepted into Wine (can't return E_NOTIMPL, e.g.).

If I am _incorrect_ about this please let me know.

Thank you. Have a great Saturday!

Misha
-------------- next part --------------
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index f91f962..28259bc 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -130,8 +130,8 @@
 @ stub D3DXFillVolumeTextureTX
 @ stdcall D3DXFilterTexture(ptr ptr long long)
 @ stdcall D3DXFindShaderComment(ptr long ptr ptr)
-@ stub D3DXFloat16To32Array
-@ stub D3DXFloat32To16Array
+@ stdcall D3DXFloat16To32Array(ptr ptr long)
+@ stdcall D3DXFloat32To16Array(ptr ptr long)
 @ stub D3DXFrameAppendChild
 @ stub D3DXFrameCalculateBoundingSphere
 @ stub D3DXFrameDestroy
diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c
index fdb5f92..6f8a71d 100644
--- a/dlls/d3dx9_36/math.c
+++ b/dlls/d3dx9_36/math.c
@@ -1769,3 +1769,123 @@ D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4* out, UINT outstride, CON
     }
     return out;
 }
+
+static inline unsigned short float_32_to_16(const float in)
+{
+    int exp = 0, origexp;
+    float tmp = fabs(in);
+    int sign = signbit(in);
+    unsigned int mantissa;
+    unsigned short ret;
+
+    /* Deal with special numbers */
+    if (isinf(in)) return (sign ? 0xffff : 0x7fff);
+    if (isnan(in)) return (sign ? 0xffff : 0x7fff);
+    if (in == 0.0f) return (sign ? 0x8000 : 0x0000);
+
+    if (tmp < powf(2, 10))
+    {
+        do
+        {
+            tmp = tmp * 2.0f;
+            exp--;
+        } while (tmp < powf(2, 10));
+    }
+    else if (tmp >= powf(2, 11))
+    {
+        do
+        {
+            tmp /= 2.0f;
+            exp++;
+        } while (tmp >= powf(2, 11));
+    }
+
+    exp += 10;  /* Normalize the mantissa */
+    exp += 15;  /* Exponent is encoded with excess 15 */
+
+    origexp = exp;
+
+    mantissa = (unsigned int) tmp;
+    if ((tmp - mantissa == 0.5f && mantissa % 2 == 1) || /* round half to even */
+	(tmp - mantissa > 0.5f)) mantissa++; /* round to nearest, away from zero */
+    if (mantissa == 2048)
+    {
+        mantissa = 1024;
+        exp++;
+    }
+
+    if (exp > 31)
+    {
+        /* too big */
+        ret = 0x7fff; /* INF */
+    }
+    else if (exp <= 0)
+    {
+        unsigned int rounding = 0;
+
+        exp = origexp;
+
+        /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
+        mantissa = (unsigned int) tmp;
+        mantissa &= 0x3ff;
+	mantissa |= 0x400; /* explicit the first bit */
+        while (exp <= 0)
+        {
+	    rounding = mantissa & 1;
+            mantissa >>= 1;
+            exp++;
+        }
+        ret = mantissa + rounding;
+    }
+    else
+    {
+        ret = (exp << 10) | (mantissa & 0x3ff);
+    }
+
+    ret |= ((sign ? 1 : 0) << 15); /* Add the sign */
+    return ret;
+}
+
+D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n)
+{
+    unsigned int i;
+
+    for (i = 0; i < n; ++i)
+    {
+        pout[i].value = float_32_to_16(pin[i]);
+    }
+
+    return pout;
+}
+
+/* Native d3dx9's D3DXFloat16to32Array lacks support for NaN and Inf. Specifically, e = 16 is treated as a
+ * regular number - e.g., 0x7fff is converted to 131008.0 and 0xffff to -131008.0. */
+static inline float float_16_to_32(const unsigned short in)
+{
+    const unsigned short s = (in & 0x8000);
+    const unsigned short e = (in & 0x7C00) >> 10;
+    const unsigned short m = in & 0x3FF;
+    const float sgn = (s ? -1.0f : 1.0f);
+
+    if (e == 0)
+    {
+        if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */
+        else return sgn * powf(2, -14.0f) * ((float)m / 1024.0f);
+    }
+    else
+    {
+        return sgn * powf(2, (float)e - 15.0f) * (1.0f + ((float)m / 1024.0f));
+    }
+}
+
+FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, CONST D3DXFLOAT16 *pin, UINT n)
+{
+    unsigned int i;
+
+    for (i = 0; i < n; ++i)
+    {
+        pout[i] = float_16_to_32(pin[i].value);
+    }
+
+    return pout;
+}
diff --git a/dlls/d3dx9_36/tests/math.c b/dlls/d3dx9_36/tests/math.c
index 5ad1924..8a79893 100644
--- a/dlls/d3dx9_36/tests/math.c
+++ b/dlls/d3dx9_36/tests/math.c
@@ -21,6 +21,7 @@
 
 #include "wine/test.h"
 #include "d3dx9.h"
+#include <math.h>
 
 #define ARRAY_SIZE 5
 
@@ -2215,6 +2216,337 @@ static void test_D3DXVec_Array(void)
     compare_planes(exp_plane, out_plane);
 }
 
+#define  INT16_TYPE          short
+#define UINT16_TYPE unsigned short
+#define  INT32_TYPE          long
+#define UINT32_TYPE unsigned long
+
+int singles2halfp(void *target, void *source, int numel)
+{
+    UINT16_TYPE *hp = (UINT16_TYPE *) target; // Type pun output as an unsigned 16-bit int
+    UINT32_TYPE *xp = (UINT32_TYPE *) source; // Type pun input as an unsigned 32-bit int
+    UINT16_TYPE    hs, he, hm;
+    UINT32_TYPE x, xs, xe, xm;
+    int hes;
+    static int next;  // Little Endian adjustment
+    static int checkieee = 0;  // Flag to check for IEEE754, Endian, and word size
+    double one = 1.0; // Used for checking IEEE754 floating point format
+    UINT32_TYPE *ip; // Used for checking IEEE754 floating point format
+    
+    if( checkieee ) { // 1st call, so check for IEEE754, Endian, and word size
+        ip = (UINT32_TYPE *) &one;
+        if( *ip ) { // If Big Endian, then no adjustment
+            next = 0;
+        } else { // If Little Endian, then adjustment will be necessary
+            next = 1;
+            ip++;
+        }
+        if( *ip != 0x3FF00000u ) { // Check for exact IEEE 754 bit pattern of 1.0
+            return 1;  // Floating point bit pattern is not IEEE 754
+        }
+        if( sizeof(INT16_TYPE) != 2 || sizeof(INT32_TYPE) != 4 ) {
+            return 1;  // short is not 16-bits, or long is not 32-bits.
+        }
+        checkieee = 0; // Everything checks out OK
+    }
+    
+    if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real)
+        return 0;
+    }
+    
+    while( numel-- ) {
+        x = *xp++;
+        if( (x & 0x7FFFFFFFu) == 0 ) {  // Signed zero
+            *hp++ = (UINT16_TYPE) (x >> 16);  // Return the signed zero
+        } else { // Not zero
+            xs = x & 0x80000000u;  // Pick off sign bit
+            xe = x & 0x7F800000u;  // Pick off exponent bits
+            xm = x & 0x007FFFFFu;  // Pick off mantissa bits
+            if( xe == 0 ) {  // Denormal will underflow, return a signed zero
+                *hp++ = (UINT16_TYPE) (xs >> 16);
+            } else if( xe == 0x7F800000u ) {  // Inf or NaN (all the exponent bits are set)
+                if( xm == 0 ) { // If mantissa is zero ...
+                    *hp++ = (UINT16_TYPE) ((xs >> 16) | 0x7fffu); // Signed Inf
+                } else {
+                    *hp++ = (UINT16_TYPE) 0xFfffu; // NaN, only 1st mantissa bit set
+                }
+            } else { // Normalized number
+                hs = (UINT16_TYPE) (xs >> 16); // Sign bit
+                hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp
+                if( hes >= 0x1F ) {  // Overflow
+                    *hp++ = (UINT16_TYPE) ((xs >> 16) | 0x7fffu); // Signed Inf
+                } else if( hes <= 0 ) {  // Underflow
+                    if( (14 - hes) > 24 ) {  // Mantissa shifted all the way off & no rounding possibility
+                        hm = (UINT16_TYPE) 0u;  // Set mantissa to zero
+                    } else {
+                        xm |= 0x00800000u;  // Add the hidden leading bit
+                        hm = (UINT16_TYPE) (xm >> (14 - hes)); // Mantissa
+                        if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding
+                            hm += (UINT16_TYPE) 1u; // Round, might overflow into exp bit, but this is OK
+                    }
+                    *hp++ = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero
+                } else {
+                    he = (UINT16_TYPE) (hes << 10); // Exponent
+                    hm = (UINT16_TYPE) (xm >> 13); // Mantissa
+                    if( xm & 0x00001000u ) // Check for rounding
+                        *hp++ = (hs | he | hm) + (UINT16_TYPE) 1u; // Round, might overflow to inf, this is OK
+                    else
+                        *hp++ = (hs | he | hm);  // No rounding
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+const char *int_to_binary
+(
+    int x
+ )
+{
+    static char b[100];
+    int i = 0;
+    b[0] = '\0';
+
+    int z;
+    for (z = 32768; z > 0; z >>= 1, i++)
+	{
+	    strcat(b, ((x & z) == z) ? "1" : "0");
+	}
+
+    return b;
+}
+
+static inline unsigned short float_32_to_16(const float in)
+{
+    int exp = 0, origexp;
+    float tmp = fabs(in);
+    int sign = signbit(in);
+    unsigned int mantissa;
+    unsigned short ret;
+
+    /* Deal with special numbers */
+    if (isinf(in)) return (sign ? 0xffff : 0x7fff);
+    if (isnan(in)) return (sign ? 0xffff : 0x7fff);
+    if (in == 0.0f) return (sign ? 0x8000 : 0x0000);
+
+    if (tmp < powf(2, 10))
+    {
+        do
+        {
+            tmp = tmp * 2.0f;
+            exp--;
+        } while (tmp < powf(2, 10));
+    }
+    else if (tmp >= powf(2, 11))
+    {
+        do
+        {
+            tmp /= 2.0f;
+            exp++;
+        } while (tmp >= powf(2, 11));
+    }
+
+    exp += 10;  /* Normalize the mantissa */
+    exp += 15;  /* Exponent is encoded with excess 15 */
+
+    origexp = exp;
+
+    mantissa = (unsigned int) tmp;
+    if ((tmp - mantissa == 0.5f && mantissa % 2 == 1) || /* round half to even */
+	(tmp - mantissa > 0.5f)) mantissa++; /* round to nearest, away from zero */
+    if (mantissa == 2048)
+    {
+        mantissa = 1024;
+        exp++;
+    }
+
+    if (exp > 31)
+    {
+        /* too big */
+        ret = 0x7fff; /* INF */
+    }
+    else if (exp <= 0)
+    {
+        unsigned int rounding = 0;
+
+        exp = origexp;
+
+        /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
+	printf("\ttmp = %f\n", tmp);
+        mantissa = (unsigned int) tmp;
+	printf("\tmantissa = %u %s\n", mantissa, int_to_binary(mantissa));
+        mantissa &= 0x3ff;
+	printf("\tmantissa & 0x3ff = %u %s\n", mantissa, int_to_binary(mantissa));
+	mantissa |= 0x400; /* explicit the first bit */
+	printf("\tmantissa | 0x400 = %u %s\n", mantissa, int_to_binary(mantissa));
+        while (exp <= 0)
+        {
+	    rounding = mantissa & 1;
+            mantissa >>= 1;
+            exp++;
+        }
+	printf("\trounding = %d\n", rounding);
+        ret = mantissa + rounding;
+    }
+    else
+    {
+        ret = (exp << 10) | (mantissa & 0x3ff);
+    }
+
+    ret |= ((sign ? 1 : 0) << 15); /* Add the sign */
+    return ret;
+}
+
+const char *single_to_binary
+(
+    unsigned int x
+ )
+{
+    static char b[100];
+    int i = 0;
+    b[0] = '\0';
+
+    unsigned int z;
+    for (z = 32768*65536; z > 0; z >>= 1, i++)
+	{
+	    strcat(b, ((x & z) == z) ? "1" : "0");
+	    if (i == 0 || i == 8) strcat(b, " ");
+	}
+
+    return b;
+}
+
+const char *half_to_binary
+(
+    int x
+ )
+{
+    static char b[100];
+    int i = 0;
+    b[0] = '\0';
+
+    int z;
+    for (z = 32768; z > 0; z >>= 1, i++)
+	{
+	    strcat(b, ((x & z) == z) ? "1" : "0");
+	    if (i == 0 || i == 5) strcat(b, " ");
+	}
+
+    return b;
+}
+
+static void test_D3DXFloat_Array(void)
+{
+    unsigned int i;
+    void *out = NULL;
+    D3DXFLOAT16 half;
+    FLOAT single;
+    struct
+    {
+        FLOAT single_in;
+
+        /* half_ver2 occurs on WXPPROSP3 (32 bit math), WVISTAADM (32 bit math), W7PRO (32 bit math) */
+        WORD half_ver1, half_ver2;
+
+        /* single_out_ver2 confirms that half -> single conversion is consistent across platforms */
+        FLOAT single_out_ver1, single_out_ver2;
+    } testdata[] = {
+        { 80000.0f, 0x7c00, 0x7ce2, 65536.0f, 80000.0f },
+        { 65503.0f, 0x7bff, 0x7bff, 65504.0f, 65504.0f },
+        { 65504.0f, 0x7bff, 0x7bff, 65504.0f, 65504.0f },
+        { 65520.0f, 0x7bff, 0x7c00, 65504.0f, 65536.0f },
+        { 65521.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f },
+        { 65534.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f },
+        { 65535.0f, 0x7c00, 0x7c00, 65535.0f, 65536.0f },
+        { 65536.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f },
+        { -80000.0f, 0xfc00, 0xfce2, -65536.0f, -80000.0f },
+        { -65503.0f, 0xfbff, 0xfbff, -65504.0f, -65504.0f },
+        { -65504.0f, 0xfbff, 0xfbff, -65504.0f, -65504.0f },
+        { -65520.0f, 0xfbff, 0xfc00, -65504.0f, -65536.0f },
+        { -65521.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f },
+        { -65534.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f },
+        { -65535.0f, 0xfc00, 0xfc00, -65535.0f, -65536.0f },
+        { -65536.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f },
+        { INFINITY, 0x7c00, 0x7fff, 65536.0f, 131008.0f },
+        { -INFINITY, 0xffff, 0xffff, -131008.0f, -131008.0f },
+        { NAN, 0x7fff, 0x7fff, 131008.0f, 131008.0f },
+        { -NAN, 0xffff, 0xffff, -131008.0f, -131008.0f },
+        { 0.0f, 0x0, 0x0, 0.0f, 0.0f },
+        { -0.0f, 0x8000, 0x8000, 0.0f, 0.0f }
+    };
+
+    /* exception on NULL out or in parameter */
+    out = D3DXFloat32To16Array(&half, &single, 0);
+    ok(out == &half, "Got %p, expected %p.\n", out, &half);
+
+    out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&half, 0);
+    ok(out == &single, "Got %p, expected %p.\n", out, &single);
+
+    for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++)
+    {
+        out = D3DXFloat32To16Array(&half, &testdata[i].single_in, 1);
+        ok(out == &half, "Got %p, expected %p.\n", out, &half);
+        ok(half.value == testdata[i].half_ver1 || half.value == testdata[i].half_ver2,
+           "Got %x, expected %x or %x for index %d.\n", half.value, testdata[i].half_ver1,
+           testdata[i].half_ver2, i);
+
+        out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&testdata[i].half_ver1, 1);
+        ok(out == &single, "Got %p, expected %p.\n", out, &single);
+        ok(relative_error(single, testdata[i].single_out_ver1) < admitted_error,
+           "Got %f, expected %f for index %d.\n", single, testdata[i].single_out_ver1, i);
+
+        out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&testdata[i].half_ver2, 1);
+        ok(out == &single, "Got %p, expected %p.\n", out, &single);
+        ok(relative_error(single, testdata[i].single_out_ver2) < admitted_error,
+           "Got %f, expected %f for index %d.\n", single, testdata[i].single_out_ver2, i);
+    }
+
+    {
+        HMODULE dll_handle = NULL;
+        D3DXFLOAT16 res, res2;
+        D3DXFLOAT16* (WINAPI * float32to16)(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n);
+        union
+        {
+            float f;
+            DWORD d;
+        } x;
+
+        dll_handle = LoadLibraryA("d3dx9_36_2.dll");
+        if (!dll_handle) skip("init: Could not load d3dx9_36_2.dll.\n");
+
+        float32to16 = (void *)GetProcAddress(dll_handle, "D3DXFloat32To16Array");
+        if (!float32to16)
+        {
+            FreeLibrary(dll_handle);
+            skip("init: Could not get function pointer (D3DXFloat32To16Array).\n");
+        }
+
+        for (i = 0; i < 0xfffff000; i += 0xff)
+        {
+            x.d = i;
+            float32to16(&res, &x.f, 1);
+	    D3DXFloat32To16Array(&res2, &x.f, 1);
+	    //	    singles2halfp(&res2, &x.f, 1);
+
+            if (res.value != res2.value)
+            {
+		unsigned int *ptr = (unsigned int *)&x.f;
+		printf("%s: res2 - res = %d\n", single_to_binary(*ptr), res2.value - res.value);
+		float_32_to_16(x.f);
+		//                ok(res.value == res2.value, "Failed i=%#x f=%f (%#x!=%#x)\n", i, x.f, res.value, res2.value);
+		/*
+		  printf("\t%s: ", single_to_binary(*ptr));
+		  printf("%s !=", half_to_binary(res.value));
+		  printf(" %s\n", half_to_binary(res2.value));
+		*/
+            }
+            //trace("i=%#x f=%f (%#x!=%#x)\n", i, x.f, res.value, res2.value);
+        }
+        FreeLibrary(dll_handle);
+    }
+}
+
 START_TEST(math)
 {
     D3DXColorTest();
@@ -2230,4 +2562,5 @@ START_TEST(math)
     test_Matrix_Decompose();
     test_Matrix_Transformation2D();
     test_D3DXVec_Array();
+    test_D3DXFloat_Array();
 }
diff --git a/include/d3dx9math.h b/include/d3dx9math.h
index f842e3e..cdb1deb 100644
--- a/include/d3dx9math.h
+++ b/include/d3dx9math.h
@@ -261,6 +261,21 @@ typedef struct D3DXCOLOR
     FLOAT r, g, b, a;
 } D3DXCOLOR, *LPD3DXCOLOR;
 
+typedef struct D3DXFLOAT16
+{
+#ifdef __cplusplus
+    D3DXFLOAT16();
+    D3DXFLOAT16(FLOAT f);
+    D3DXFLOAT16(CONST D3DXFLOAT16 &f);
+
+    operator FLOAT ();
+
+    BOOL operator == (CONST D3DXFLOAT16 &) const;
+    BOOL operator != (CONST D3DXFLOAT16 &) const;
+#endif /* __cplusplus */
+    WORD value;
+} D3DXFLOAT16, *LPD3DXFLOAT16;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -358,6 +373,9 @@ D3DXVECTOR4* WINAPI D3DXVec4Normalize(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv);
 D3DXVECTOR4* WINAPI D3DXVec4Transform(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv, CONST D3DXMATRIX *pm);
 D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4 *pout, UINT outstride, CONST D3DXVECTOR4 *pv, UINT vstride, CONST D3DXMATRIX *pm, UINT n);
 
+D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n);
+FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, CONST D3DXFLOAT16 *pin, UINT n);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/d3dx9math.inl b/include/d3dx9math.inl
index 3cd078a..3f55aef 100644
--- a/include/d3dx9math.inl
+++ b/include/d3dx9math.inl
@@ -851,6 +851,37 @@ inline BOOL D3DXCOLOR::operator != (CONST D3DXCOLOR& col) const
     return r != col.r || g != col.g || b != col.b || a != col.a;
 }
 
+inline D3DXFLOAT16::D3DXFLOAT16()
+{
+}
+
+inline D3DXFLOAT16::D3DXFLOAT16(FLOAT f)
+{
+    D3DXFloat32To16Array(this, &f, 1);
+}
+
+inline D3DXFLOAT16::D3DXFLOAT16(CONST D3DXFLOAT16 &f)
+{
+    value = f.value;
+}
+
+inline D3DXFLOAT16::operator FLOAT ()
+{
+    FLOAT f;
+    D3DXFloat16To32Array(&f, this, 1);
+    return f;
+}
+
+inline BOOL D3DXFLOAT16::operator == (CONST D3DXFLOAT16 &f) const
+{
+    return value == f.value;
+}
+
+inline BOOL D3DXFLOAT16::operator != (CONST D3DXFLOAT16 &f) const
+{
+    return value != f.value;
+}
+
 #endif /* __cplusplus */
 
 /*_______________D3DXCOLOR_____________________*/
-------------- next part --------------
../../../tools/runtest -q -P wine -M d3dx9_36.dll -T ../../.. -p d3dx9_36_test.exe.so math.c && touch math.ok
0 01100110 00000000000000011001100: res2 - res = 1
	tmp = 1024.024902
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000000111001011: res2 - res = 1
	tmp = 1024.056030
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000001011001010: res2 - res = 1
	tmp = 1024.087158
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000001111001001: res2 - res = 1
	tmp = 1024.118286
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000010011001000: res2 - res = 1
	tmp = 1024.149414
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000010111000111: res2 - res = 1
	tmp = 1024.180542
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000011011000110: res2 - res = 1
	tmp = 1024.211670
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01100110 00000000000011111000101: res2 - res = 1
	tmp = 1024.242798
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
0 01101000 01000000000000010101011: res2 - res = 1
	tmp = 1280.020874
	mantissa = 1280 0000010100000000
	mantissa & 0x3ff = 256 0000000100000000
	mantissa | 0x400 = 1280 0000010100000000
	rounding = 1
0 01101000 01000000000000110101010: res2 - res = 1
	tmp = 1280.052002
	mantissa = 1280 0000010100000000
	mantissa & 0x3ff = 256 0000000100000000
	mantissa | 0x400 = 1280 0000010100000000
	rounding = 1
0 01101001 00100000000000000111011: res2 - res = 1
	tmp = 1152.007202
	mantissa = 1152 0000010010000000
	mantissa & 0x3ff = 128 0000000010000000
	mantissa | 0x400 = 1152 0000010010000000
	rounding = 1
0 01101001 10100000000000011111010: res2 - res = 1
	tmp = 1664.030518
	mantissa = 1664 0000011010000000
	mantissa & 0x3ff = 640 0000001010000000
	mantissa | 0x400 = 1664 0000011010000000
	rounding = 1
0 01101010 11010000000000001100010: res2 - res = 1
	tmp = 1856.011963
	mantissa = 1856 0000011101000000
	mantissa & 0x3ff = 832 0000001101000000
	mantissa | 0x400 = 1856 0000011101000000
	rounding = 1
0 01101011 00101000000000000110110: res2 - res = 1
	tmp = 1184.006592
	mantissa = 1184 0000010010100000
	mantissa & 0x3ff = 160 0000000010100000
	mantissa | 0x400 = 1184 0000010010100000
	rounding = 1
0 01101011 01001000000000000100110: res2 - res = 1
	tmp = 1312.004639
	mantissa = 1312 0000010100100000
	mantissa & 0x3ff = 288 0000000100100000
	mantissa | 0x400 = 1312 0000010100100000
	rounding = 1
0 01101011 01101000000000000010110: res2 - res = 1
	tmp = 1440.002686
	mantissa = 1440 0000010110100000
	mantissa & 0x3ff = 416 0000000110100000
	mantissa | 0x400 = 1440 0000010110100000
	rounding = 1
0 01101011 10001000000000000000110: res2 - res = 1
	tmp = 1568.000732
	mantissa = 1568 0000011000100000
	mantissa & 0x3ff = 544 0000001000100000
	mantissa | 0x400 = 1568 0000011000100000
	rounding = 1
0 01101101 01111010000000000001100: res2 - res = 1
	tmp = 1512.001465
	mantissa = 1512 0000010111101000
	mantissa & 0x3ff = 488 0000000111101000
	mantissa | 0x400 = 1512 0000010111101000
	rounding = 1
0 01101101 10000010000000000001000: res2 - res = 1
	tmp = 1544.000977
	mantissa = 1544 0000011000001000
	mantissa & 0x3ff = 520 0000001000001000
	mantissa | 0x400 = 1544 0000011000001000
	rounding = 1
0 01101101 10001010000000000000100: res2 - res = 1
	tmp = 1576.000488
	mantissa = 1576 0000011000101000
	mantissa & 0x3ff = 552 0000001000101000
	mantissa | 0x400 = 1576 0000011000101000
	rounding = 1
0 01101101 10010010000000000000000: res2 - res = 1
	tmp = 1608.000000
	mantissa = 1608 0000011001001000
	mantissa & 0x3ff = 584 0000001001001000
	mantissa | 0x400 = 1608 0000011001001000
	rounding = 1
0 01101110 10000101000000000000110: res2 - res = 1
	tmp = 1556.000732
	mantissa = 1556 0000011000010100
	mantissa & 0x3ff = 532 0000001000010100
	mantissa | 0x400 = 1556 0000011000010100
	rounding = 1
0 01101110 10001001000000000000100: res2 - res = 1
	tmp = 1572.000488
	mantissa = 1572 0000011000100100
	mantissa & 0x3ff = 548 0000001000100100
	mantissa | 0x400 = 1572 0000011000100100
	rounding = 1
0 01101110 10001101000000000000010: res2 - res = 1
	tmp = 1588.000244
	mantissa = 1588 0000011000110100
	mantissa & 0x3ff = 564 0000001000110100
	mantissa | 0x400 = 1588 0000011000110100
	rounding = 1
0 01101110 10010001000000000000000: res2 - res = 1
	tmp = 1604.000000
	mantissa = 1604 0000011001000100
	mantissa & 0x3ff = 580 0000001001000100
	mantissa | 0x400 = 1604 0000011001000100
	rounding = 1
0 01101111 00001010100000000000011: res2 - res = 1
	tmp = 1066.000366
	mantissa = 1066 0000010000101010
	mantissa & 0x3ff = 42 0000000000101010
	mantissa | 0x400 = 1066 0000010000101010
	rounding = 1
0 01101111 00001100100000000000010: res2 - res = 1
	tmp = 1074.000244
	mantissa = 1074 0000010000110010
	mantissa & 0x3ff = 50 0000000000110010
	mantissa | 0x400 = 1074 0000010000110010
	rounding = 1
0 01101111 00001110100000000000001: res2 - res = 1
	tmp = 1082.000122
	mantissa = 1082 0000010000111010
	mantissa & 0x3ff = 58 0000000000111010
	mantissa | 0x400 = 1082 0000010000111010
	rounding = 1
0 01101111 00010000100000000000000: res2 - res = 1
	tmp = 1090.000000
	mantissa = 1090 0000010001000010
	mantissa & 0x3ff = 66 0000000001000010
	mantissa | 0x400 = 1090 0000010001000010
	rounding = 1
0 01110000 01001101010000000000001: res2 - res = 1
	tmp = 1333.000122
	mantissa = 1333 0000010100110101
	mantissa & 0x3ff = 309 0000000100110101
	mantissa | 0x400 = 1333 0000010100110101
	rounding = 1
0 01110000 01001111010000000000000: res2 - res = 1
	tmp = 1341.000000
	mantissa = 1341 0000010100111101
	mantissa & 0x3ff = 317 0000000100111101
	mantissa | 0x400 = 1341 0000010100111101
	rounding = 1
1 01100110 00000000000000001001100: res2 - res = 1
	tmp = 1024.009277
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000000101001011: res2 - res = 1
	tmp = 1024.040405
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000001001001010: res2 - res = 1
	tmp = 1024.071533
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000001101001001: res2 - res = 1
	tmp = 1024.102661
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000010001001000: res2 - res = 1
	tmp = 1024.133789
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000010101000111: res2 - res = 1
	tmp = 1024.164917
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000011001000110: res2 - res = 1
	tmp = 1024.196045
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01100110 00000000000011101000101: res2 - res = 1
	tmp = 1024.227173
	mantissa = 1024 0000010000000000
	mantissa & 0x3ff = 0 0000000000000000
	mantissa | 0x400 = 1024 0000010000000000
	rounding = 1
1 01101000 01000000000000000101011: res2 - res = 1
	tmp = 1280.005249
	mantissa = 1280 0000010100000000
	mantissa & 0x3ff = 256 0000000100000000
	mantissa | 0x400 = 1280 0000010100000000
	rounding = 1
1 01101000 01000000000000100101010: res2 - res = 1
	tmp = 1280.036377
	mantissa = 1280 0000010100000000
	mantissa & 0x3ff = 256 0000000100000000
	mantissa | 0x400 = 1280 0000010100000000
	rounding = 1
1 01101001 00100000000000010111010: res2 - res = 1
	tmp = 1152.022705
	mantissa = 1152 0000010010000000
	mantissa & 0x3ff = 128 0000000010000000
	mantissa | 0x400 = 1152 0000010010000000
	rounding = 1
1 01101001 10100000000000001111010: res2 - res = 1
	tmp = 1664.014893
	mantissa = 1664 0000011010000000
	mantissa & 0x3ff = 640 0000001010000000
	mantissa | 0x400 = 1664 0000011010000000
	rounding = 1
1 01101010 00010000000000001000010: res2 - res = 1
	tmp = 1088.008057
	mantissa = 1088 0000010001000000
	mantissa & 0x3ff = 64 0000000001000000
	mantissa | 0x400 = 1088 0000010001000000
	rounding = 1
1 01101010 01010000000000000100010: res2 - res = 1
	tmp = 1344.004150
	mantissa = 1344 0000010101000000
	mantissa & 0x3ff = 320 0000000101000000
	mantissa | 0x400 = 1344 0000010101000000
	rounding = 1
1 01101010 10010000000000000000010: res2 - res = 1
	tmp = 1600.000244
	mantissa = 1600 0000011001000000
	mantissa & 0x3ff = 576 0000001001000000
	mantissa | 0x400 = 1600 0000011001000000
	rounding = 1
1 01101100 01010100000000000011111: res2 - res = 1
	tmp = 1360.003784
	mantissa = 1360 0000010101010000
	mantissa & 0x3ff = 336 0000000101010000
	mantissa | 0x400 = 1360 0000010101010000
	rounding = 1
1 01101100 01100100000000000010111: res2 - res = 1
	tmp = 1424.002808
	mantissa = 1424 0000010110010000
	mantissa & 0x3ff = 400 0000000110010000
	mantissa | 0x400 = 1424 0000010110010000
	rounding = 1
1 01101100 01110100000000000001111: res2 - res = 1
	tmp = 1488.001831
	mantissa = 1488 0000010111010000
	mantissa & 0x3ff = 464 0000000111010000
	mantissa | 0x400 = 1488 0000010111010000
	rounding = 1
1 01101100 10000100000000000000111: res2 - res = 1
	tmp = 1552.000854
	mantissa = 1552 0000011000010000
	mantissa & 0x3ff = 528 0000001000010000
	mantissa | 0x400 = 1552 0000011000010000
	rounding = 1
1 01110000 01001100010000000000001: res2 - res = 1
	tmp = 1329.000122
	mantissa = 1329 0000010100110001
	mantissa & 0x3ff = 305 0000000100110001
	mantissa | 0x400 = 1329 0000010100110001
	rounding = 1
1 01110000 01001110010000000000000: res2 - res = 1
	tmp = 1337.000000
	mantissa = 1337 0000010100111001
	mantissa & 0x3ff = 313 0000000100111001
	mantissa | 0x400 = 1337 0000010100111001
	rounding = 1


More information about the wine-devel mailing list