180d59932Sopenharmony_ci// 280d59932Sopenharmony_ci// Copyright (c) 2020 The Khronos Group Inc. 380d59932Sopenharmony_ci// 480d59932Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 580d59932Sopenharmony_ci// you may not use this file except in compliance with the License. 680d59932Sopenharmony_ci// You may obtain a copy of the License at 780d59932Sopenharmony_ci// 880d59932Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 980d59932Sopenharmony_ci// 1080d59932Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 1180d59932Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 1280d59932Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1380d59932Sopenharmony_ci// See the License for the specific language governing permissions and 1480d59932Sopenharmony_ci// limitations under the License. 1580d59932Sopenharmony_ci// 1680d59932Sopenharmony_ci 1780d59932Sopenharmony_ci#include <math.h> 1880d59932Sopenharmony_ci#include <stdio.h> 1980d59932Sopenharmony_ci 2080d59932Sopenharmony_ci#include "CL/cl_half.h" 2180d59932Sopenharmony_ci 2280d59932Sopenharmony_ciunion FI { 2380d59932Sopenharmony_ci float f; 2480d59932Sopenharmony_ci uint32_t i; 2580d59932Sopenharmony_ci}; 2680d59932Sopenharmony_ci 2780d59932Sopenharmony_ciint test_half_to_float(cl_half h, cl_float ref) 2880d59932Sopenharmony_ci{ 2980d59932Sopenharmony_ci cl_float f = cl_half_to_float(h); 3080d59932Sopenharmony_ci if (f != ref) { 3180d59932Sopenharmony_ci union FI f_i, ref_i; 3280d59932Sopenharmony_ci f_i.f = f; 3380d59932Sopenharmony_ci ref_i.f = ref; 3480d59932Sopenharmony_ci printf("\nERROR: converting 0x%04x to float: expected 0x%08x, got 0x%08x\n", 3580d59932Sopenharmony_ci h, ref_i.i, f_i.i); 3680d59932Sopenharmony_ci return 0; 3780d59932Sopenharmony_ci } 3880d59932Sopenharmony_ci return 1; 3980d59932Sopenharmony_ci} 4080d59932Sopenharmony_ci 4180d59932Sopenharmony_ciint test_half_from_float(cl_float f, cl_half ref, 4280d59932Sopenharmony_ci cl_half_rounding_mode mode, const char *mode_str) 4380d59932Sopenharmony_ci{ 4480d59932Sopenharmony_ci cl_half h = cl_half_from_float(f, mode); 4580d59932Sopenharmony_ci if (h != ref) { 4680d59932Sopenharmony_ci union FI f_i; 4780d59932Sopenharmony_ci f_i.f = f; 4880d59932Sopenharmony_ci printf( 4980d59932Sopenharmony_ci "\nERROR: converting 0x%08x to half (%s): expected 0x%04x, got 0x%04x\n", 5080d59932Sopenharmony_ci f_i.i, mode_str, ref, h); 5180d59932Sopenharmony_ci return 0; 5280d59932Sopenharmony_ci } 5380d59932Sopenharmony_ci return 1; 5480d59932Sopenharmony_ci} 5580d59932Sopenharmony_ci 5680d59932Sopenharmony_ciint main(void) 5780d59932Sopenharmony_ci{ 5880d59932Sopenharmony_ci printf("\nChecking conversion routines in cl_half.h\n"); 5980d59932Sopenharmony_ci 6080d59932Sopenharmony_ci#define CHECK_TO_FLOAT(h, ref) \ 6180d59932Sopenharmony_ci if (!test_half_to_float(h, ref)) { \ 6280d59932Sopenharmony_ci printf("Test failed on line %d.\n", __LINE__); \ 6380d59932Sopenharmony_ci return 1; \ 6480d59932Sopenharmony_ci } 6580d59932Sopenharmony_ci 6680d59932Sopenharmony_ci // Check a handful of values 6780d59932Sopenharmony_ci CHECK_TO_FLOAT(0x0000, 0.f); 6880d59932Sopenharmony_ci CHECK_TO_FLOAT(0x3c00, 1.f); 6980d59932Sopenharmony_ci CHECK_TO_FLOAT(0xbc00, -1.f); 7080d59932Sopenharmony_ci CHECK_TO_FLOAT(0x7c00, INFINITY); 7180d59932Sopenharmony_ci CHECK_TO_FLOAT(0xfc00, -INFINITY); 7280d59932Sopenharmony_ci 7380d59932Sopenharmony_ci 7480d59932Sopenharmony_ci#define CHECK_FROM_FLOAT(f, ref, mode) \ 7580d59932Sopenharmony_ci if (!test_half_from_float(f, ref, CL_HALF_##mode, #mode)) { \ 7680d59932Sopenharmony_ci printf("Test failed on line %d.\n", __LINE__); \ 7780d59932Sopenharmony_ci return 1; \ 7880d59932Sopenharmony_ci } 7980d59932Sopenharmony_ci 8080d59932Sopenharmony_ci // Check a handful of normal values 8180d59932Sopenharmony_ci CHECK_FROM_FLOAT(0.f, 0x0000, RTE); 8280d59932Sopenharmony_ci CHECK_FROM_FLOAT(1.f, 0x3c00, RTE); 8380d59932Sopenharmony_ci CHECK_FROM_FLOAT(-1.f, 0xbc00, RTE); 8480d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MAX, 0x7bff, RTE); 8580d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MIN, 0x0400, RTE); 8680d59932Sopenharmony_ci 8780d59932Sopenharmony_ci // Check huge positive (non-inf) values round properly 8880d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MAX + 1000.f, 0x7c00, RTE); 8980d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MAX + 1000.f, 0x7c00, RTP); 9080d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MAX + 1000.f, 0x7bff, RTN); 9180d59932Sopenharmony_ci CHECK_FROM_FLOAT(CL_HALF_MAX + 1000.f, 0x7bff, RTZ); 9280d59932Sopenharmony_ci 9380d59932Sopenharmony_ci // Check huge negative (non-inf) values round properly 9480d59932Sopenharmony_ci CHECK_FROM_FLOAT(-(CL_HALF_MAX + 1000.f), 0xfc00, RTE); 9580d59932Sopenharmony_ci CHECK_FROM_FLOAT(-(CL_HALF_MAX + 1000.f), 0xfbff, RTP); 9680d59932Sopenharmony_ci CHECK_FROM_FLOAT(-(CL_HALF_MAX + 1000.f), 0xfc00, RTN); 9780d59932Sopenharmony_ci CHECK_FROM_FLOAT(-(CL_HALF_MAX + 1000.f), 0xfbff, RTZ); 9880d59932Sopenharmony_ci#if 0 // Hexadecimal float constant is C++17 9980d59932Sopenharmony_ci // Check tiny positive values round properly 10080d59932Sopenharmony_ci CHECK_FROM_FLOAT(0x1.000000p-25, 0x0000, RTE); 10180d59932Sopenharmony_ci CHECK_FROM_FLOAT(0x1.000000p-25, 0x0001, RTP); 10280d59932Sopenharmony_ci CHECK_FROM_FLOAT(0x1.000000p-25, 0x0000, RTN); 10380d59932Sopenharmony_ci CHECK_FROM_FLOAT(0x1.000000p-25, 0x0000, RTZ); 10480d59932Sopenharmony_ci 10580d59932Sopenharmony_ci // Check tiny negative values round properly 10680d59932Sopenharmony_ci CHECK_FROM_FLOAT(-0x1.000000p-25, 0x8000, RTE); 10780d59932Sopenharmony_ci CHECK_FROM_FLOAT(-0x1.000000p-25, 0x8000, RTP); 10880d59932Sopenharmony_ci CHECK_FROM_FLOAT(-0x1.000000p-25, 0x8001, RTN); 10980d59932Sopenharmony_ci CHECK_FROM_FLOAT(-0x1.000000p-25, 0x8000, RTZ); 11080d59932Sopenharmony_ci#else 11180d59932Sopenharmony_ci // Check tiny positive values round properly 11280d59932Sopenharmony_ci CHECK_FROM_FLOAT(2.98023223876953125e-08, 0x0000, RTE); 11380d59932Sopenharmony_ci CHECK_FROM_FLOAT(2.98023223876953125e-08, 0x0001, RTP); 11480d59932Sopenharmony_ci CHECK_FROM_FLOAT(2.98023223876953125e-08, 0x0000, RTN); 11580d59932Sopenharmony_ci CHECK_FROM_FLOAT(2.98023223876953125e-08, 0x0000, RTZ); 11680d59932Sopenharmony_ci 11780d59932Sopenharmony_ci // Check tiny negative values round properly 11880d59932Sopenharmony_ci CHECK_FROM_FLOAT(-2.98023223876953125e-08, 0x8000, RTE); 11980d59932Sopenharmony_ci CHECK_FROM_FLOAT(-2.98023223876953125e-08, 0x8000, RTP); 12080d59932Sopenharmony_ci CHECK_FROM_FLOAT(-2.98023223876953125e-08, 0x8001, RTN); 12180d59932Sopenharmony_ci CHECK_FROM_FLOAT(-2.98023223876953125e-08, 0x8000, RTZ); 12280d59932Sopenharmony_ci#endif 12380d59932Sopenharmony_ci printf("\nAll tests passed!\n"); 12480d59932Sopenharmony_ci 12580d59932Sopenharmony_ci return 0; 12680d59932Sopenharmony_ci} 127