Nikolay Sivov : scrrun: Implement HashVal for floating point keys.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Feb 25 09:57:01 CST 2015


Module: wine
Branch: master
Commit: 08900265a0aaba4c658f359acd90398e1aac8a8c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=08900265a0aaba4c658f359acd90398e1aac8a8c

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Feb 25 08:11:15 2015 +0300

scrrun: Implement HashVal for floating point keys.

---

 dlls/scrrun/dictionary.c       |  19 ++++++++
 dlls/scrrun/tests/dictionary.c | 104 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)

diff --git a/dlls/scrrun/dictionary.c b/dlls/scrrun/dictionary.c
index b5edfc6..a33e1de 100644
--- a/dlls/scrrun/dictionary.c
+++ b/dlls/scrrun/dictionary.c
@@ -18,6 +18,8 @@
 #define COBJMACROS
 
 #include "config.h"
+#include "wine/port.h"
+
 #include <stdarg.h>
 
 #include "windef.h"
@@ -336,6 +338,23 @@ static HRESULT WINAPI dictionary_get_HashVal(IDictionary *iface, VARIANT *key, V
     case VT_I4:
         V_I4(hash) = get_num_hash(V_I4(key));
         break;
+    case VT_R4:
+    case VT_R8:
+    {
+        FLOAT flt = V_VT(key) == VT_R4 ? V_R4(key) : V_R8(key);
+
+        if (isinf(flt))
+        {
+            V_I4(hash) = 0;
+            break;
+        }
+        else if (!isnan(flt))
+        {
+            V_I4(hash) = get_num_hash(flt);
+            break;
+        }
+        /* fallthrough on NAN */
+    }
     case VT_INT:
     case VT_UINT:
     case VT_I1:
diff --git a/dlls/scrrun/tests/dictionary.c b/dlls/scrrun/tests/dictionary.c
index 0a168e0..0c3a92c 100644
--- a/dlls/scrrun/tests/dictionary.c
+++ b/dlls/scrrun/tests/dictionary.c
@@ -149,6 +149,29 @@ static DWORD get_num_hash(FLOAT num)
     return (*((DWORD*)&num)) % 1201;
 }
 
+typedef union
+{
+    struct
+    {
+        unsigned int m : 23;
+        unsigned int exp_bias : 8;
+        unsigned int sign : 1;
+    } i;
+    float f;
+} R4_FIELDS;
+
+typedef union
+{
+    struct
+    {
+        unsigned int m_lo : 32;     /* 52 bits of precision */
+        unsigned int m_hi : 20;
+        unsigned int exp_bias : 11; /* bias == 1023 */
+        unsigned int sign : 1;
+    } i;
+    double d;
+} R8_FIELDS;
+
 static void test_hash_value(void)
 {
     /* string test data */
@@ -165,8 +188,14 @@ static void test_hash_value(void)
         0, -1, 100, 1, 255
     };
 
+    static const FLOAT float_hash_tests[] = {
+        0.0, -1.0, 100.0, 1.0, 255.0, 1.234
+    };
+
     IDictionary *dict;
     VARIANT key, hash;
+    R8_FIELDS fx8;
+    R4_FIELDS fx4;
     HRESULT hr;
     unsigned i;
 
@@ -307,6 +336,81 @@ static void test_hash_value(void)
             expected);
     }
 
+    /* nan */
+    fx4.f = 10.0;
+    fx4.i.exp_bias = 0xff;
+
+    V_VT(&key) = VT_R4;
+    V_R4(&key) = fx4.f;
+    VariantInit(&hash);
+    hr = IDictionary_get_HashVal(dict, &key, &hash);
+    ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
+    ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+    ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ ||
+        V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash));
+
+    /* inf */
+    fx4.f = 10.0;
+    fx4.i.m = 0;
+    fx4.i.exp_bias = 0xff;
+
+    V_VT(&key) = VT_R4;
+    V_R4(&key) = fx4.f;
+    V_I4(&hash) = 10;
+    hr = IDictionary_get_HashVal(dict, &key, &hash);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+    ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash));
+
+    /* nan */
+    fx8.d = 10.0;
+    fx8.i.exp_bias = 0x7ff;
+
+    V_VT(&key) = VT_R8;
+    V_R8(&key) = fx8.d;
+    VariantInit(&hash);
+    hr = IDictionary_get_HashVal(dict, &key, &hash);
+    ok(hr == CTL_E_ILLEGALFUNCTIONCALL || broken(hr == S_OK) /* win2k, win2k3 */, "got 0x%08x\n", hr);
+    ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+    ok(V_I4(&hash) == ~0u || broken(V_I4(&hash) == 0 /* win2k */ ||
+        V_I4(&hash) == 0x1f4 /* vista, win2k8 */), "got hash 0x%08x\n", V_I4(&hash));
+
+    /* inf */
+    fx8.d = 10.0;
+    fx8.i.m_lo = 0;
+    fx8.i.m_hi = 0;
+    fx8.i.exp_bias = 0x7ff;
+
+    V_VT(&key) = VT_R8;
+    V_R8(&key) = fx8.d;
+    V_I4(&hash) = 10;
+    hr = IDictionary_get_HashVal(dict, &key, &hash);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+    ok(V_I4(&hash) == 0, "got hash 0x%08x\n", V_I4(&hash));
+
+    for (i = 0; i < sizeof(float_hash_tests)/sizeof(float_hash_tests[0]); i++) {
+        DWORD expected = get_num_hash(float_hash_tests[i]);
+
+        V_VT(&key) = VT_R4;
+        V_R4(&key) = float_hash_tests[i];
+        VariantInit(&hash);
+        hr = IDictionary_get_HashVal(dict, &key, &hash);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+        ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
+            expected);
+
+        V_VT(&key) = VT_R8;
+        V_R8(&key) = float_hash_tests[i];
+        VariantInit(&hash);
+        hr = IDictionary_get_HashVal(dict, &key, &hash);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(V_VT(&hash) == VT_I4, "got %d\n", V_VT(&hash));
+        ok(V_I4(&hash) == expected, "%d: got hash 0x%08x, expected 0x%08x\n", i, V_I4(&hash),
+            expected);
+    }
+
     IDictionary_Release(dict);
 }
 




More information about the wine-cvs mailing list