<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 5, 2016, at 13:35, Jan Vesely <<a href="mailto:jan.vesely@rutgers.edu" class="">jan.vesely@rutgers.edu</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">On Mon, 2016-12-05 at 09:48 -0800,<span class="Apple-converted-space"> </span></span><a href="mailto:arsenm2@gmail.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">arsenm2@gmail.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space"> </span>wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">From: Matt Arsenault <<a href="mailto:arsenm2@gmail.com" class="">arsenm2@gmail.com</a>><br class=""><br class="">These do not use the normal simple format because the number<br class="">of combinations that need to be tested is simply too large,<br class="">especially when tests for min3/max3 are added.<br class=""><br class="">The unordered compare tests could be improved. Currently they truly<br class="">test the unordered compare because of LLVM bug 21610, but<br class="">ideally that would be fixed.<br class="">---<br class="">tests/cl/program/CMakeLists.cl.txt                 |   1 +<br class="">.../cl/program/execute/scalar-comparison-float.cl  | 105 +++++<br class="">tests/cl/program/float-min-max-kernels.cl          | 492 +++++++++++++++++++++<br class="">tests/cl/program/float-min-max.cpp                 | 475 ++++++++++++++++++++<br class="">4 files changed, 1073 insertions(+)<br class="">create mode 100644 tests/cl/program/float-min-max-kernels.cl<br class="">create mode 100644 tests/cl/program/float-min-max.cpp<br class=""><br class="">diff --git a/tests/cl/program/CMakeLists.cl.txt b/tests/cl/program/CMakeLists.cl.txt<br class="">index c8d7307..5ef0f6b 100644<br class="">--- a/tests/cl/program/CMakeLists.cl.txt<br class="">+++ b/tests/cl/program/CMakeLists.cl.txt<br class="">@@ -2,3 +2,4 @@ piglit_cl_add_program_test (tester program-tester.c)<br class="">piglit_cl_add_program_test (max-work-item-sizes max-work-item-sizes.c)<br class="">piglit_cl_add_program_test (bitcoin-phatk bitcoin-phatk.c)<br class="">piglit_cl_add_program_test (predefined-macros predefined-macros.c)<br class="">+piglit_cl_add_program_test (float-min-max float-min-max.cpp)<br class="">diff --git a/tests/cl/program/execute/scalar-comparison-float.cl b/tests/cl/program/execute/scalar-comparison-float.cl<br class="">index 4891fc5..598fae0 100644<br class="">--- a/tests/cl/program/execute/scalar-comparison-float.cl<br class="">+++ b/tests/cl/program/execute/scalar-comparison-float.cl<br class="">@@ -148,6 +148,71 @@ arg_in:  1 float -3.5<br class="">arg_in:  2 float 4.5<br class="">arg_out: 0 buffer int[1] 1<br class=""><br class="">+<br class="">+[test]<br class="">+name: select_max_gt<br class="">+kernel_name: select_max_gt<br class="">+global_size: 24 0 0<br class="">+<br class="">+arg_out: 0 buffer float[24]    \<br class="">+  0.0  1.0  2.0  2.0  0.0  0.0 \<br class="">+  NAN  NAN  1.0  NAN -1.0  NAN \<br class="">+  0.0  0.0 97.0  INF  INF  INF \<br class="">+  NAN  NAN  INF  NAN -INF  INF<br class="">+<br class="">+arg_in: 1 buffer float[24]     \<br class="">+  0.0  1.0  1.0  2.0  0.0 -1.0 \<br class="">+  NAN  1.0  NAN -1.0  NAN  0.0 \<br class="">+  0.0 -0.0 37.0  INF  INF -INF \<br class="">+ -INF  INF  NAN -INF  NAN  0.0<br class="">+<br class="">+arg_in: 2 buffer float[24]     \<br class="">+  0.0  1.0  2.0  1.0 -1.0  0.0 \<br class="">+  NAN  NAN  1.0  NAN -1.0  NAN \<br class="">+ -0.0  0.0 97.0  INF -INF  INF \<br class="">+ -INF  NAN  INF  NAN -INF  INF<br class="">+<br class="">+[test]<br class="">+name: select_max_gte<br class="">+kernel_name: select_max_gte<br class="">+global_size: 15 0 0<br class="">+<br class="">+arg_out: 0 buffer float[15]    \<br class="">+  0.0  1.0  2.0  2.0  0.0  0.0 \<br class="">+  NAN  NAN  1.0  NAN -1.0  NAN \<br class="">+  0.0  0.0 97.0<br class="">+<br class="">+arg_in: 1 buffer float[15]     \<br class="">+  0.0  1.0  1.0  2.0  0.0 -1.0 \<br class="">+  NAN  1.0  NAN -1.0  NAN  0.0 \<br class="">+  0.0 -0.0 37.0<br class="">+<br class="">+arg_in: 2 buffer float[15]     \<br class="">+  0.0  1.0  2.0  1.0 -1.0  0.0 \<br class="">+  NAN  NAN  1.0  NAN -1.0  NAN \<br class="">+ -0.0  0.0 97.0<br class="">+<br class="">+[test]<br class="">+name: select_min_gt<br class="">+kernel_name: select_min_gt<br class="">+global_size: 15 0 0<br class="">+<br class="">+arg_out: 0 buffer float[15]    \<br class="">+  0.0  1.0  1.0  1.0 -1.0 -1.0 \<br class="">+  NAN  NAN  NAN  NAN NAN  NAN  \<br class="">+  0.0  0.0 37.0<br class="">+<br class="">+arg_in: 1 buffer float[15] \<br class="">+  0.0  1.0  1.0  2.0  0.0 -1.0 \<br class="">+  NAN  1.0  NAN -1.0  NAN  0.0 \<br class="">+  0.0 -0.0  37.0<br class="">+<br class="">+arg_in: 2 buffer float[15]     \<br class="">+  0.0  1.0  2.0  1.0 -1.0  0.0 \<br class="">+  NAN  NAN  1.0  NAN -1.0  NAN \<br class="">+ -0.0  0.0 97.0<br class="">+<br class="">+<br class="">!*/<br class=""><br class="">kernel void eq(global int* out, float a, float b) {<br class="">@@ -173,3 +238,43 @@ kernel void lt(global int* out, float a, float b) {<br class="">kernel void lte(global int* out, float a, float b) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>out[0] = a <= b;<br class="">}<br class="">+<br class="">+kernel void select_max_gt(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">    </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] > b[id]) ? a[id] : b[id];<br class="">+}<br class="">+<br class="">+kernel void select_max_gte(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">        </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] >= b[id]) ? a[id] : b[id];<br class="">+}<br class="">+<br class="">+kernel void select_min_gt(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">        </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] > b[id]) ? b[id] : a[id];<br class="">+}<br class="">+<br class="">+kernel void select_min_gte(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">        </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] >= b[id]) ? b[id] : a[id];<br class="">+}<br class="">+<br class="">+kernel void select_min_lt(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">        </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] < b[id]) ? a[id] : b[id];<br class="">+}<br class="">+<br class="">+kernel void select_max_lt(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;"> </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] < b[id]) ? b[id] : a[id];<br class="">+}<br class="">+<br class="">+kernel void select_min_lte(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">        </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] <= b[id]) ? a[id] : b[id];<br class="">+}<br class="">+<br class="">+kernel void select_max_lte(global float* restrict out, global float* restrict a, global float* restrict b) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">       </span>int id = get_global_id(0);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>out[id] = (a[id] <= b[id]) ? b[id] : a[id];<br class="">+}<br class="">diff --git a/tests/cl/program/float-min-max-kernels.cl b/tests/cl/program/float-min-max-kernels.cl<br class="">new file mode 100644<br class="">index 0000000..09f31d4<br class="">--- /dev/null<br class="">+++ b/tests/cl/program/float-min-max-kernels.cl<br class="">@@ -0,0 +1,492 @@<br class="">+#pragma OPENCL EXTENSION cl_khr_fp64 : enable<br class="">+<br class="">+kernel void select_max_gt_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a > b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_max_ge_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a >= b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_gt_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a > b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_ge_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a >= b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_lt_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a < b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_le_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a <= b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_lt_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a < b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_le_f32(global float* restrict out,<br class="">+                              constant float* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a <= b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void test_fmin_f32(global float* restrict out,<br class="">+                          constant float* in,<br class="">+                          int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = fmin(a, b);<br class="">+}<br class="">+<br class="">+kernel void test_fmax_f32(global float* restrict out,<br class="">+                          constant float* in,<br class="">+                          int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = fmax(a, b);<br class="">+}<br class="">+<br class="">+// FIXME: It is a canonicalization bug that an unordered comparison is<br class="">+// emitted for this if the intermediate cmp variable is used.<br class="">+kernel void select_max_ugt_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a <= b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_max_uge_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a < b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_ugt_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a <= b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_uge_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a < b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_ult_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a >= b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_ule_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a > b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_ult_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a >= b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_ule_f32(global float* restrict out,<br class="">+                               constant float* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    float a = in[idx];<br class="">+    float b = in[idy];<br class="">+<br class="">+    bool cmp = !(a > b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+#if cl_khr_fp64<br class="">+kernel void select_max_gt_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a > b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_max_ge_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a >= b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_gt_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a > b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_ge_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a >= b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_lt_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a < b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_le_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a <= b) ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_lt_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a < b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_le_f64(global double* restrict out,<br class="">+                              constant double* restrict in,<br class="">+                              int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = (a <= b) ? a : b;<br class="">+}<br class="">+<br class="">+kernel void test_fmin_f64(global double* restrict out,<br class="">+                          constant double* in,<br class="">+                          int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = fmin(a, b);<br class="">+}<br class="">+<br class="">+kernel void test_fmax_f64(global double* restrict out,<br class="">+                          constant double* in,<br class="">+                          int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    out[n * idx + idy] = fmax(a, b);<br class="">+}<br class="">+<br class="">+// FIXME: It is a canonicalization bug that an unordered comparison is<br class="">+// emitted for this if the intermediate cmp variable is used.<br class="">+kernel void select_max_ugt_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a <= b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_max_uge_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a < b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_ugt_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a <= b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_uge_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a < b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_ult_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a >= b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_max_ule_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a > b);<br class="">+    out[n * idx + idy] = cmp ? b : a;<br class="">+}<br class="">+<br class="">+kernel void select_min_ult_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a >= b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+kernel void select_min_ule_f64(global double* restrict out,<br class="">+                               constant double* restrict in,<br class="">+                               int n)<br class="">+{<br class="">+    int idx = get_global_id(0);<br class="">+    int idy = get_global_id(1);<br class="">+<br class="">+    double a = in[idx];<br class="">+    double b = in[idy];<br class="">+<br class="">+    bool cmp = !(a > b);<br class="">+    out[n * idx + idy] = cmp ? a : b;<br class="">+}<br class="">+<br class="">+#endif<br class="">diff --git a/tests/cl/program/float-min-max.cpp b/tests/cl/program/float-min-max.cpp<br class="">new file mode 100644<br class="">index 0000000..296b446<br class="">--- /dev/null<br class="">+++ b/tests/cl/program/float-min-max.cpp<br class="">@@ -0,0 +1,475 @@<br class="">+<br class="">+extern "C" {<br class="">+#include "piglit-framework-cl-program.h"<br class="">+}<br class="">+<br class="">+PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN<br class="">+<br class="">+    config.name = "Run kernels which will use select min / max instructions";<br class="">+<br class="">+    config.run_per_device = true;<br class="">+<br class="">+    config.program_source_file = "float-min-max-kernels.cl";<br class="">+    config.kernel_name = NULL; // We have many kernels.<br class="">+<br class="">+PIGLIT_CL_PROGRAM_TEST_CONFIG_END<br class="">+<br class="">+<br class="">+template <typename Real><br class="">+struct TestFunction<br class="">+{<br class="">+    typedef Real (*MinMaxFunc)(Real, Real);<br class="">+<br class="">+    const char* kernel_name;<br class="">+    MinMaxFunc ref_func;<br class="">+};<br class="">+<br class="">+static const size_t n_cases = 32;<br class="">+static const size_t n_denormal_cases = 8;<br class="">+static const size_t n_tests = 18;<br class="">+<br class="">+template <typename Real><br class="">+class FMinFMaxTest<br class="">+{<br class="">+public:<br class="">+    typedef typename TestFunction<Real>::MinMaxFunc MinMaxFunc;<br class="">+<br class="">+    static const Real cases[n_cases];<br class="">+    static const TestFunction<Real> test_minmax_fns[n_tests];<br class="">+<br class="">+<br class="">+    FMinFMaxTest() { }<br class="">+    ~FMinFMaxTest() { }<br class="">+<br class="">+    static cl_mem create_input_buffer(const piglit_cl_program_test_env* env,<br class="">+                                      bool denormals);<br class="">+<br class="">+    static bool verify_results(MinMaxFunc func,<br class="">+                               const Real* results,<br class="">+                               bool test_denormals);<br class="">+    static bool run_minmax_test(const piglit_cl_program_test_env* env,<br class="">+                                const TestFunction<Real>* test_fn,<br class="">+                                cl_mem input,<br class="">+                                bool test_denormals);<br class="">+<br class="">+    static piglit_result run_tests(const piglit_cl_program_test_env* env,<br class="">+                                   cl_device_fp_config fp_config);<br class="">+<br class="">+};<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_gt(Real a, Real b)<br class="">+{<br class="">+    return (a > b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_ge(Real a, Real b)<br class="">+{<br class="">+    return (a >= b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_gt(Real a, Real b)<br class="">+{<br class="">+    return (a > b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_ge(Real a, Real b)<br class="">+{<br class="">+    return (a >= b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_lt(Real a, Real b)<br class="">+{<br class="">+    return (a < b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_le(Real a, Real b)<br class="">+{<br class="">+    return (a <= b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_lt(Real a, Real b)<br class="">+{<br class="">+    return (a < b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_le(Real a, Real b)<br class="">+{<br class="">+    return (a <= b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_ugt(Real a, Real b)<br class="">+{<br class="">+    return !(a <= b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_uge(Real a, Real b)<br class="">+{<br class="">+    return !(a < b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_ugt(Real a, Real b)<br class="">+{<br class="">+    return !(a <= b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_uge(Real a, Real b)<br class="">+{<br class="">+    return !(a < b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_ult(Real a, Real b)<br class="">+{<br class="">+    return !(a >= b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_max_ule(Real a, Real b)<br class="">+{<br class="">+    return !(a > b) ? b : a;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_ult(Real a, Real b)<br class="">+{<br class="">+    return !(a >= b) ? a : b;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+static Real select_min_ule(Real a, Real b)<br class="">+{<br class="">+    return !(a > b) ? a : b;<br class="">+}<br class="">+<br class="">+#define TYPE_SUFFIX "_f32"<br class="">+#define TYPE_NAME float<br class="">+#define TEST_FN(name) { #name TYPE_SUFFIX, name<TYPE_NAME> }<br class="">+<br class="">+template <><br class="">+const TestFunction<float> FMinFMaxTest<float>::test_minmax_fns[n_tests] = {<br class="">+    TEST_FN(select_max_gt),<br class="">+    TEST_FN(select_max_ge),<br class="">+    TEST_FN(select_min_gt),<br class="">+    TEST_FN(select_min_ge),<br class="">+<br class="">+    TEST_FN(select_max_lt),<br class="">+    TEST_FN(select_max_le),<br class="">+    TEST_FN(select_min_lt),<br class="">+    TEST_FN(select_min_le),<br class="">+<br class="">+    TEST_FN(select_max_ugt),<br class="">+    TEST_FN(select_max_uge),<br class="">+    TEST_FN(select_min_ugt),<br class="">+    TEST_FN(select_min_uge),<br class="">+<br class="">+    TEST_FN(select_max_ult),<br class="">+    TEST_FN(select_max_ule),<br class="">+    TEST_FN(select_min_ult),<br class="">+    TEST_FN(select_min_ule),<br class="">+<br class="">+    { "test_fmin_f32", fminf },<br class="">+    { "test_fmax_f32", fmaxf }<br class="">+};<br class="">+<br class="">+#undef TYPE_SUFFIX<br class="">+#undef TYPE_NAME<br class="">+#define TYPE_SUFFIX "_f64"<br class="">+#define TYPE_NAME double<br class="">+<br class="">+template <><br class="">+const TestFunction<double> FMinFMaxTest<double>::test_minmax_fns[n_tests] = {<br class="">+    TEST_FN(select_max_gt),<br class="">+    TEST_FN(select_max_ge),<br class="">+    TEST_FN(select_min_gt),<br class="">+    TEST_FN(select_min_ge),<br class="">+<br class="">+    TEST_FN(select_max_lt),<br class="">+    TEST_FN(select_max_le),<br class="">+    TEST_FN(select_min_lt),<br class="">+    TEST_FN(select_min_le),<br class="">+<br class="">+    TEST_FN(select_max_ugt),<br class="">+    TEST_FN(select_max_uge),<br class="">+    TEST_FN(select_min_ugt),<br class="">+    TEST_FN(select_min_uge),<br class="">+<br class="">+    TEST_FN(select_max_ult),<br class="">+    TEST_FN(select_max_ule),<br class="">+    TEST_FN(select_min_ult),<br class="">+    TEST_FN(select_min_ule),<br class="">+<br class="">+    { "test_fmin_f64", fmin },<br class="">+    { "test_fmax_f64", fmax }<br class="">+};<br class="">+<br class="">+#undef TYPE_SUFFIX<br class="">+#undef TYPE_NAME<br class="">+<br class="">+template <><br class="">+const float FMinFMaxTest<float>::cases[n_cases] = {<br class="">+    0.0f,<br class="">+    -0.0f,<br class="">+<br class="">+    0.5f,<br class="">+    -0.5f,<br class="">+<br class="">+    -1.0f,<br class="">+    1.0f,<br class="">+<br class="">+    -2.0f,<br class="">+    2.0f,<br class="">+<br class="">+    3.0f,<br class="">+    -3.0f,<br class="">+<br class="">+    4.0f,<br class="">+    -4.0f,<br class="">+<br class="">+    12345.0,<br class="">+<br class="">+    0x1p-126f,         // Minimum normal number<br class="">+    -0x1p-126f,<br class="">+<br class="">+    0x1p-126f,         // Min float<br class="">+    -0x1p-126f,<br class="">+<br class="">+    0x1.fffffep+127f,  // Max float<br class="">+    -0x1.fffffep+127f,<br class="">+<br class="">+    0x1p-23f,          // Epsilon<br class="">+    -0x1p-23f,<br class="">+<br class="">+    INFINITY,<br class="">+    -INFINITY,<br class="">+    NAN,<br class="">+<br class="">+    // Denormals.<br class="">+    0x1p-149f,         // Denorm min<br class="">+    -0x1p-149f,<br class="">+<br class="">+    0x1p-148f,         // Denorm min * 2.0<br class="">+    -0x1p-148f,<br class="">+<br class="">+    0x1.fffffcp-127f,  // Max denormal<br class="">+    -0x1.fffffcp-127f,<br class="">+<br class="">+    0x1.fffffcp-128f,  // Max denormal / 2.0<br class="">+    -0x1.fffffcp-128f<br class="">+};<br class="">+<br class="">+template <><br class="">+const double FMinFMaxTest<double>::cases[n_cases] = {<br class="">+    0.0,<br class="">+    -0.0,<br class="">+<br class="">+    0.5,<br class="">+    -0.5,<br class="">+<br class="">+    -1.0,<br class="">+    1.0,<br class="">+<br class="">+    -2.0,<br class="">+    2.0,<br class="">+<br class="">+    3.0,<br class="">+    -3.0,<br class="">+<br class="">+    4.0,<br class="">+    -4.0,<br class="">+<br class="">+    12345.0,<br class="">+<br class="">+    0x1.fffffffffffffp+1023, // Maximum double<br class="">+    -0x1.fffffffffffffp+1023,<br class="">+<br class="">+    0x1p-1022, // Minimum normal number<br class="">+    -0x1p-1022,<br class="">+<br class="">+    0x1p-52, // Epsilon<br class="">+    -0x1p-52,<br class="">+<br class="">+    INFINITY,<br class="">+    -INFINITY,<br class="">+    NAN,<br class="">+<br class="">+    // Denormals.<br class="">+    0x0.0000000000001p-1022, // Denorm min<br class="">+    -0x0.0000000000001p-1022,<br class="">+<br class="">+    0x0.0000000000002p-1022, // Denorm min * 2.0<br class="">+    -0x0.0000000000002p-1022,<br class="">+<br class="">+    0x0.fffffffffffffp-1022, // Max denormal<br class="">+    -0x0.fffffffffffffp-1022,<br class="">+<br class="">+    0x0.8p-1022, // Max denormal / 2.0<br class="">+    -0x0.8p-1022<br class="">+};<br class="">+<br class="">+<br class="">+<br class="">+template <typename Real><br class="">+cl_mem FMinFMaxTest<Real>::create_input_buffer(const piglit_cl_program_test_env* env,<br class="">+                                               bool denormals)<br class="">+{<br class="">+    const size_t n = denormals ? n_cases : (n_cases - n_denormal_cases);<br class="">+    cl_mem buf = piglit_cl_create_buffer(env->context, CL_MEM_READ_ONLY, n * n * sizeof(Real));<br class="">+    if (!buf)<br class="">+        return NULL;<br class="">+<br class="">+    for (size_t i = 0; i < n; ++i)<br class="">+    {<br class="">+        if (!piglit_cl_write_buffer(env->context->command_queues[0], buf, i * n * sizeof(Real), n * sizeof(Real), cases))<br class="">+        {<br class="">+            // Leaking buf<br class="">+            return NULL;<br class="">+        }<br class="">+    }<br class="">+<br class="">+    return buf;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+bool FMinFMaxTest<Real>::verify_results(MinMaxFunc func,<br class="">+                                        const Real* results,<br class="">+                                        bool test_denormals)<br class="">+{<br class="">+    bool failed = false;<br class="">+<br class="">+    const size_t n = test_denormals ? n_cases : (n_cases - n_denormal_cases);<br class="">+<br class="">+    for (size_t i = 0; i < n; ++i)<br class="">+    {<br class="">+        for (size_t j = 0; j < n; ++j)<br class="">+        {<br class="">+            Real x = cases[i];<br class="">+            Real y = cases[j];<br class="">+<br class="">+            Real ref = func(x, y);<br class="">+            Real result = results[n * i + j];<br class="">+<br class="">+            failed |= !piglit_cl_probe_floating(result, ref, 0);<br class="">+        }<br class="">+    }<br class="">+<br class="">+    return failed;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+bool FMinFMaxTest<Real>::run_minmax_test(const piglit_cl_program_test_env* env,<br class="">+                                         const TestFunction<Real>* test_fn,<br class="">+                                         cl_mem input,<br class="">+                                         bool test_denormals)<br class="">+{<br class="">+    const size_t n = test_denormals ? n_cases : (n_cases - n_denormal_cases);<br class="">+    const cl_int n_i = (cl_int) n;<br class="">+    const size_t global_size[2] = { n, n };<br class="">+    printf("Create kernel '%s'\n", test_fn->kernel_name);<br class="">+    cl_kernel kernel = piglit_cl_create_kernel(env->program,<br class="">+                                               test_fn->kernel_name);<br class="">+    if (!kernel)<br class="">+    {<br class="">+        return true;<br class="">+    }<br class="">+<br class="">+    Real* ptr_out = new Real[n * n]();<br class="">+    if (!ptr_out)<br class="">+    {<br class="">+        return true;<br class="">+    }<br class="">+<br class="">+    cl_mem mem_out = piglit_cl_create_buffer(env->context, CL_MEM_WRITE_ONLY,<br class="">+                                             n * n * sizeof(Real));<br class="">+    if (!mem_out)<br class="">+    {<br class="">+        delete[] ptr_out;<br class="">+        return true;<br class="">+    }<br class="">+<br class="">+    piglit_cl_set_kernel_buffer_arg(kernel, 0, &mem_out);<br class="">+    piglit_cl_set_kernel_buffer_arg(kernel, 1, &input);<br class="">+    piglit_cl_set_kernel_arg(kernel, 2, sizeof(cl_int), &n_i);<br class="">+<br class="">+    piglit_cl_execute_ND_range_kernel(env->context->command_queues[0],<br class="">+                                      kernel,<br class="">+                                      2,<br class="">+                                      NULL,<br class="">+                                      global_size,<br class="">+                                      NULL);<br class="">+<br class="">+    bool failed = !piglit_cl_read_buffer(env->context->command_queues[0], mem_out, 0,<br class="">+                                         n * n * sizeof(Real), ptr_out);<br class="">+    if (!failed)<br class="">+        failed = verify_results(test_fn->ref_func, ptr_out, test_denormals);<br class="">+<br class="">+    delete[] ptr_out;<br class="">+<br class="">+    // Leaking mem_out<br class="">+    return failed;<br class="">+}<br class="">+<br class="">+template <typename Real><br class="">+piglit_result FMinFMaxTest<Real>::run_tests(const piglit_cl_program_test_env* env,<br class="">+                                            cl_device_fp_config fp_config)<br class="">+{<br class="">+    bool failed = false;<br class="">+<br class="">+    bool test_denormals = (fp_config & CL_FP_DENORM) != 0;<br class="">+<br class="">+    cl_mem input = create_input_buffer(env, test_denormals);<br class="">+    if (!input)<br class="">+        return PIGLIT_FAIL;<br class="">+<br class="">+    for (size_t i = 0; i < n_tests; ++i)<br class="">+    {<br class="">+        if (run_minmax_test(env, &test_minmax_fns[i], input, test_denormals))<br class="">+        {<br class="">+            fprintf(stderr, "Failure testing kernel %s\n", test_minmax_fns[i].kernel_name);<br class="">+            return PIGLIT_FAIL;<br class="">+        }<br class="">+    }<br class="">+<br class="">+    return failed ? PIGLIT_FAIL : PIGLIT_PASS;<br class="">+}<br class="">+<br class="">+piglit_result<br class="">+piglit_cl_test(const int argc,<br class="">+               const char** argv,<br class="">+               const piglit_cl_program_test_config* config,<br class="">+               const piglit_cl_program_test_env* env)<br class="">+{<br class="">+    cl_device_fp_config float_fp_config = 0;<br class="">+    cl_device_fp_config double_fp_config = 0;<br class="">+<br class="">+    clGetDeviceInfo(env->device_id, CL_DEVICE_SINGLE_FP_CONFIG,<br class="">+                    sizeof(cl_device_fp_config), &float_fp_config, NULL);<br class="">+<br class="">+    clGetDeviceInfo(env->device_id, CL_DEVICE_DOUBLE_FP_CONFIG,<br class="">+                    sizeof(cl_device_fp_config), &double_fp_config, NULL);<br class="">+<br class="">+    piglit_result result = FMinFMaxTest<float>().run_tests(env,<br class="">+                                                           float_fp_config);<br class="">+    if (result != PIGLIT_PASS)<br class="">+        return result;<br class="">+<br class="">+    if (double_fp_config != 0) {<br class="">+        piglit_result result = FMinFMaxTest<double>().run_tests(env,<br class="">+                                                                double_fp_config);<br class="">+        if (result != PIGLIT_PASS)<br class="">+            return result;<br class="">+    }<br class="">+<br class="">+    return PIGLIT_PASS;<br class="">+}<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">why are these tests created at runtime instead of build time? the c++</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">code would be better as python generator.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Jan</span></div></blockquote><br class=""></div><div><br class=""></div><div>The number of combinations started growing, and repeating the same list of inputs for the tests and manually adding the output results grew tiresome. I didn’t see other precedent for other tests to generate the test outputs. </div><div><br class=""></div><div>-Matt</div><br class=""></body></html>