Use explicit conversion from regexp matched array values

Signed-off-by: Jan Vesely <[email protected]>
---
 tests/cl/program/program-tester.c | 31 +++++++++++++++++++++++++----
 tests/util/piglit-util-cl.c       | 42 +++++++++++++++++++++++++++++++++++++++
 tests/util/piglit-util-cl.h       | 25 +++++++++++++++++++++++
 3 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/tests/cl/program/program-tester.c 
b/tests/cl/program/program-tester.c
index 8e3cb4d..25b677f 100644
--- a/tests/cl/program/program-tester.c
+++ b/tests/cl/program/program-tester.c
@@ -111,12 +111,14 @@
 // TODO: probably we could use libmpdec to handle this
 //       http://www.bytereef.org/mpdecimal/index.html
 //#define REGEX_TYPE_HALF       "buffer half[1]"
+#define REGEX_TYPE_HALF       REGEX_DEFINE_TYPE("half")
 #define REGEX_TYPE_FLOAT      REGEX_DEFINE_TYPE("float")
 #define REGEX_TYPE_DOUBLE      REGEX_DEFINE_TYPE("double")
 #define REGEX_TYPE  REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
                     REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
-                    REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" REGEX_TYPE_LONG "|" 
\
-                    REGEX_TYPE_ULONG "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
+                    REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
+                    REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
+                    REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
 
 /* Image types */
 /* TODO: add OpenCL 1.2+ types */
@@ -324,6 +326,7 @@ enum cl_type {
        TYPE_UINT,
        TYPE_LONG,
        TYPE_ULONG,
+       TYPE_HALF,
        TYPE_FLOAT,
        TYPE_DOUBLE,
 };
@@ -1002,7 +1005,7 @@ get_test_arg_value(struct test_arg* test_arg, const char* 
value, size_t length)
                        for(c = 0; c < test_arg->cl_size; c++) {                
\
                                ra = i*test_arg->cl_size + c;                   
    \
                                rb = i*test_arg->cl_mem_size + c;               
    \
-                               ((cl_type*)test_arg->value)[rb] = 
array[ra%length]; \
+                               ((cl_type*)test_arg->value)[rb] = 
convert_##cl_type(array[ra%length]); \
                        }                                                       
\
                }                                                           \
                break;
@@ -1016,8 +1019,9 @@ get_test_arg_value(struct test_arg* test_arg, const char* 
value, size_t length)
                CASE(TYPE_UINT,   cl_uint,    get_uint_array,   uint_array)
                CASE(TYPE_LONG,   cl_long,    get_int_array,    int_array)
                CASE(TYPE_ULONG,  cl_ulong,   get_uint_array,   uint_array)
+               CASE(TYPE_HALF,   cl_half,    get_float_array,  float_array)
                CASE(TYPE_FLOAT,  cl_float,   get_float_array,  float_array)
-               CASE(TYPE_DOUBLE,  cl_double,   get_float_array,  float_array)
+               CASE(TYPE_DOUBLE, cl_double,  get_float_array,  float_array)
        }
 
 #undef CASE
@@ -1040,6 +1044,7 @@ get_test_arg_tolerance(struct test_arg* test_arg, const 
char* tolerance_str)
                             REG_NEWLINE)) {
                regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
                switch(test_arg->cl_type) {
+               case TYPE_HALF:
                case TYPE_FLOAT:
                case TYPE_DOUBLE:
                        test_arg->ulp = get_uint(value_str);
@@ -1070,6 +1075,7 @@ get_test_arg_tolerance(struct test_arg* test_arg, const 
char* tolerance_str)
                case TYPE_ULONG:
                        test_arg->tolu = get_uint(value_str);
                        break;
+               case TYPE_HALF:
                case TYPE_FLOAT:
                case TYPE_DOUBLE: {
                        float value = get_float(value_str);
@@ -1152,6 +1158,7 @@ get_test_arg(const char* src, struct test* test, bool 
arg_in)
                ELSEIF(REGEX_TYPE_UINT,   TYPE_UINT,   cl_uint)
                ELSEIF(REGEX_TYPE_LONG,   TYPE_LONG,   cl_long)
                ELSEIF(REGEX_TYPE_ULONG,  TYPE_ULONG,  cl_ulong)
+               ELSEIF(REGEX_TYPE_HALF,   TYPE_HALF,   cl_half)
                ELSEIF(REGEX_TYPE_FLOAT,  TYPE_FLOAT,  cl_float)
                ELSEIF(REGEX_TYPE_DOUBLE,  TYPE_DOUBLE,  cl_double)
 
@@ -2093,6 +2100,21 @@ check_test_arg_value(struct test_arg test_arg,
                        }                                                       
         \
                }                                                               
     \
                return true;
+#define CASEH(enum_type, type, cl_type)                                      \
+       case enum_type:                                                         
 \
+               for(i = 0; i < test_arg.length; i++) {                          
     \
+                       for(c = 0; c < test_arg.cl_size; c++) {                 
         \
+                               rb = i*test_arg.cl_mem_size + c;                
             \
+                               if(!piglit_cl_probe_half(((cl_type*)value)[rb], 
         \
+                                                            
((cl_type*)test_arg.value)[rb], \
+                                                            test_arg.ulp)) {   
            \
+                                       ra = i*test_arg.cl_size + c;            
                 \
+                                       printf("Error at %s[%zu]\n", type, ra); 
                 \
+                                       return false;                           
                 \
+                               }                                               
             \
+                       }                                                       
         \
+               }                                                               
     \
+               return true;
 #define CASEF(enum_type, type, cl_type)                                      \
        case enum_type:                                                         
 \
                for(i = 0; i < test_arg.length; i++) {                          
     \
@@ -2118,6 +2140,7 @@ check_test_arg_value(struct test_arg test_arg,
                CASEU(TYPE_UINT,   "uint",   cl_uint)
                CASEI(TYPE_LONG,   "long",   cl_long)
                CASEU(TYPE_ULONG,  "ulong",  cl_ulong)
+               CASEH(TYPE_HALF,   "half",   cl_half)
                CASEF(TYPE_FLOAT,  "float",  cl_float)
                CASEF(TYPE_DOUBLE,  "double",  cl_double)
        }
diff --git a/tests/util/piglit-util-cl.c b/tests/util/piglit-util-cl.c
index 7e7d985..d7a7901 100644
--- a/tests/util/piglit-util-cl.c
+++ b/tests/util/piglit-util-cl.c
@@ -59,6 +59,29 @@ piglit_cl_probe_uinteger(uint64_t value, uint64_t expect, 
uint64_t tolerance)
        ((isnan(value) && isnan(expect)) || \
        (isinf(value) && isinf(expect) && ((value > 0) == (expect > 0))))
 
+static float float_from_cl_half(uint32_t in)
+{
+       union {
+               uint32_t bits;
+               float val;
+       } convert;
+       uint32_t exponent = ((in >> 10) & 0x1f);
+       convert.bits = (((in >> 15) & 0x1) << 31) | //sign
+                      ((exponent ? (exponent != 0x1f ? exponent + 112 : 0xff)
+                        : 0) << 23) | //exponent (0 and 1f are special cases)
+                      (((in >>  0) & 0x3ff) << 13) | // mantissa
+                      0xfff ; // add 0.5 of non-represented value to put
+                              // the final value in the middle
+       return convert.val;
+}
+
+bool piglit_cl_probe_half(cl_half value, cl_half expect, uint32_t ulp)
+{
+       // after conversion to float the last 13 digits are 0, adjust ulp
+       return piglit_cl_probe_floating(float_from_cl_half(value),
+                                       float_from_cl_half(expect),
+                                       (ulp + 1) * 4096);
+}
 
 /* TODO: Tolerance should be specified in terms of ULP. */
 bool
@@ -118,6 +141,25 @@ piglit_cl_probe_double(double value, double expect, 
uint64_t ulp)
 
 }
 
+cl_half convert_cl_half(double in)
+{
+       union {
+               uint64_t bits;
+               double val;
+       } convert = { .val = in };
+       /* Bit 63 is sign bit */
+       cl_half sign = (cl_half)((convert.bits >> 63) << 15);
+       /* Get only the top 10 bits of mantissa */
+       cl_half mantissa = (cl_half)((convert.bits >> 42) & 0x3ff);
+       /* 11 bits of exponent */
+       uint64_t exp = (convert.bits >> 52) & 0x7ff;
+       /* 0 and ~0 are special cases that are not adjusted,
+        * half bias is 15, double bias is 1023 */
+       cl_half exponent = ((exp == 0 || exp == 0x7ff) ? (exp & 0x3ff) :
+                          (exp - 1008)) << 10;
+       return (sign | exponent | mantissa);
+}
+
 bool
 piglit_cl_check_error(cl_int error, cl_int expected_error)
 {
diff --git a/tests/util/piglit-util-cl.h b/tests/util/piglit-util-cl.h
index 9fb4f9f..bd9f5a8 100644
--- a/tests/util/piglit-util-cl.h
+++ b/tests/util/piglit-util-cl.h
@@ -44,6 +44,25 @@
 extern "C" {
 #endif
 
+#define DIRECT_CONVERT(to, from) \
+static inline from convert_##to(from in) \
+{ \
+       return (to)in; \
+}
+
+DIRECT_CONVERT(cl_char, int64_t);
+DIRECT_CONVERT(cl_uchar, uint64_t);
+DIRECT_CONVERT(cl_short, int64_t);
+DIRECT_CONVERT(cl_ushort, uint64_t);
+DIRECT_CONVERT(cl_int, int64_t);
+DIRECT_CONVERT(cl_uint, uint64_t);
+DIRECT_CONVERT(cl_long, int64_t);
+DIRECT_CONVERT(cl_ulong, uint64_t);
+DIRECT_CONVERT(cl_float, double);
+DIRECT_CONVERT(cl_double, double);
+
+cl_half convert_cl_half(double in);
+
 
 /* Runtime independent */
 
@@ -62,6 +81,12 @@ bool piglit_cl_probe_uinteger(uint64_t value,
                               uint64_t tolerance);
 
 /**
+ * \brief Probe half-floating-point \c value if it compares equal to \c expect 
with
+ *        tolerance \c ulp.
+ */
+bool piglit_cl_probe_half(cl_half value, cl_half expect, uint32_t ulp);
+
+/**
  * \brief Probe floating-point \c value if it compares equal to \c expect with
  *        tolerance \c ulp.
  */
-- 
2.7.4

_______________________________________________
Piglit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to