|  | #include <stdlib.h> | 
|  | #include <limits.h> | 
|  | #include <string.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "int_types.h" | 
|  |  | 
|  | #ifdef COMPILER_RT_HAS_FLOAT16 | 
|  | #define TYPE_FP16 _Float16 | 
|  | #else | 
|  | #define TYPE_FP16 uint16_t | 
|  | #endif | 
|  |  | 
|  | enum EXPECTED_RESULT { | 
|  | LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_0 | 
|  | }; | 
|  |  | 
|  | static inline TYPE_FP16 fromRep16(uint16_t x) | 
|  | { | 
|  | #ifdef COMPILER_RT_HAS_FLOAT16 | 
|  | TYPE_FP16 ret; | 
|  | memcpy(&ret, &x, sizeof(ret)); | 
|  | return ret; | 
|  | #else | 
|  | return x; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | static inline float fromRep32(uint32_t x) | 
|  | { | 
|  | float ret; | 
|  | memcpy(&ret, &x, 4); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline double fromRep64(uint64_t x) | 
|  | { | 
|  | double ret; | 
|  | memcpy(&ret, &x, 8); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | static inline tf_float fromRep128(uint64_t hi, uint64_t lo) { | 
|  | __uint128_t x = ((__uint128_t)hi << 64) + lo; | 
|  | tf_float ret; | 
|  | memcpy(&ret, &x, 16); | 
|  | return ret; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static inline uint16_t toRep16(TYPE_FP16 x) | 
|  | { | 
|  | #ifdef COMPILER_RT_HAS_FLOAT16 | 
|  | uint16_t ret; | 
|  | memcpy(&ret, &x, sizeof(ret)); | 
|  | return ret; | 
|  | #else | 
|  | return x; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | static inline uint32_t toRep32(float x) | 
|  | { | 
|  | uint32_t ret; | 
|  | memcpy(&ret, &x, 4); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline uint64_t toRep64(double x) | 
|  | { | 
|  | uint64_t ret; | 
|  | memcpy(&ret, &x, 8); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | static inline __uint128_t toRep128(tf_float x) { | 
|  | __uint128_t ret; | 
|  | memcpy(&ret, &x, 16); | 
|  | return ret; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static inline int compareResultH(TYPE_FP16 result, | 
|  | uint16_t expected) | 
|  | { | 
|  | uint16_t rep = toRep16(result); | 
|  |  | 
|  | if (rep == expected){ | 
|  | return 0; | 
|  | } | 
|  | // test other possible NaN representation(signal NaN) | 
|  | else if (expected == 0x7e00U){ | 
|  | if ((rep & 0x7c00U) == 0x7c00U && | 
|  | (rep & 0x3ffU) > 0){ | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static inline int compareResultF(float result, | 
|  | uint32_t expected) | 
|  | { | 
|  | uint32_t rep = toRep32(result); | 
|  |  | 
|  | if (rep == expected){ | 
|  | return 0; | 
|  | } | 
|  | // test other possible NaN representation(signal NaN) | 
|  | else if (expected == 0x7fc00000U){ | 
|  | if ((rep & 0x7f800000U) == 0x7f800000U && | 
|  | (rep & 0x7fffffU) > 0){ | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static inline int compareResultD(double result, | 
|  | uint64_t expected) | 
|  | { | 
|  | uint64_t rep = toRep64(result); | 
|  |  | 
|  | if (rep == expected){ | 
|  | return 0; | 
|  | } | 
|  | // test other possible NaN representation(signal NaN) | 
|  | else if (expected == 0x7ff8000000000000UL){ | 
|  | if ((rep & 0x7ff0000000000000UL) == 0x7ff0000000000000UL && | 
|  | (rep & 0xfffffffffffffUL) > 0){ | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | // return 0 if equal | 
|  | // use two 64-bit integers instead of one 128-bit integer | 
|  | // because 128-bit integer constant can't be assigned directly | 
|  | static inline int compareResultF128(tf_float result, uint64_t expectedHi, | 
|  | uint64_t expectedLo) { | 
|  | __uint128_t rep = toRep128(result); | 
|  | uint64_t hi = rep >> 64; | 
|  | uint64_t lo = rep; | 
|  |  | 
|  | if (hi == expectedHi && lo == expectedLo) { | 
|  | return 0; | 
|  | } | 
|  | // test other possible NaN representation(signal NaN) | 
|  | else if (expectedHi == 0x7fff800000000000UL && expectedLo == 0x0UL) { | 
|  | if ((hi & 0x7fff000000000000UL) == 0x7fff000000000000UL && | 
|  | ((hi & 0xffffffffffffUL) > 0 || lo > 0)) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | return 1; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static inline int compareResultCMP(int result, | 
|  | enum EXPECTED_RESULT expected) | 
|  | { | 
|  | switch(expected){ | 
|  | case LESS_0: | 
|  | if (result < 0) | 
|  | return 0; | 
|  | break; | 
|  | case LESS_EQUAL_0: | 
|  | if (result <= 0) | 
|  | return 0; | 
|  | break; | 
|  | case EQUAL_0: | 
|  | if (result == 0) | 
|  | return 0; | 
|  | break; | 
|  | case NEQUAL_0: | 
|  | if (result != 0) | 
|  | return 0; | 
|  | break; | 
|  | case GREATER_EQUAL_0: | 
|  | if (result >= 0) | 
|  | return 0; | 
|  | break; | 
|  | case GREATER_0: | 
|  | if (result > 0) | 
|  | return 0; | 
|  | break; | 
|  | default: | 
|  | return 1; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static inline char *expectedStr(enum EXPECTED_RESULT expected) | 
|  | { | 
|  | switch(expected){ | 
|  | case LESS_0: | 
|  | return "<0"; | 
|  | case LESS_EQUAL_0: | 
|  | return "<=0"; | 
|  | case EQUAL_0: | 
|  | return "=0"; | 
|  | case NEQUAL_0: | 
|  | return "!=0"; | 
|  | case GREATER_EQUAL_0: | 
|  | return ">=0"; | 
|  | case GREATER_0: | 
|  | return ">0"; | 
|  | default: | 
|  | return ""; | 
|  | } | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | static inline TYPE_FP16 makeQNaN16(void) | 
|  | { | 
|  | return fromRep16(0x7e00U); | 
|  | } | 
|  |  | 
|  | static inline float makeQNaN32(void) | 
|  | { | 
|  | return fromRep32(0x7fc00000U); | 
|  | } | 
|  |  | 
|  | static inline double makeQNaN64(void) | 
|  | { | 
|  | return fromRep64(0x7ff8000000000000UL); | 
|  | } | 
|  |  | 
|  | #if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) | 
|  | static inline long double F80FromRep128(uint64_t hi, uint64_t lo) { | 
|  | __uint128_t x = ((__uint128_t)hi << 64) + lo; | 
|  | long double ret; | 
|  | memcpy(&ret, &x, 16); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline __uint128_t F80ToRep128(long double x) { | 
|  | __uint128_t ret; | 
|  | memcpy(&ret, &x, 16); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline int compareResultF80(long double result, uint64_t expectedHi, | 
|  | uint64_t expectedLo) { | 
|  | __uint128_t rep = F80ToRep128(result); | 
|  | // F80 occupies the lower 80 bits of __uint128_t. | 
|  | uint64_t hi = (rep >> 64) & ((1UL << (80 - 64)) - 1); | 
|  | uint64_t lo = rep; | 
|  | return !(hi == expectedHi && lo == expectedLo); | 
|  | } | 
|  |  | 
|  | static inline long double makeQNaN80(void) { | 
|  | return F80FromRep128(0x7fffUL, 0xc000000000000000UL); | 
|  | } | 
|  |  | 
|  | static inline long double makeNaN80(uint64_t rand) { | 
|  | return F80FromRep128(0x7fffUL, | 
|  | 0x8000000000000000 | (rand & 0x3fffffffffffffff)); | 
|  | } | 
|  |  | 
|  | static inline long double makeInf80(void) { | 
|  | return F80FromRep128(0x7fffUL, 0x8000000000000000UL); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | static inline tf_float makeQNaN128(void) { | 
|  | return fromRep128(0x7fff800000000000UL, 0x0UL); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static inline TYPE_FP16 makeNaN16(uint16_t rand) | 
|  | { | 
|  | return fromRep16(0x7c00U | (rand & 0x7fffU)); | 
|  | } | 
|  |  | 
|  | static inline float makeNaN32(uint32_t rand) | 
|  | { | 
|  | return fromRep32(0x7f800000U | (rand & 0x7fffffU)); | 
|  | } | 
|  |  | 
|  | static inline double makeNaN64(uint64_t rand) | 
|  | { | 
|  | return fromRep64(0x7ff0000000000000UL | (rand & 0xfffffffffffffUL)); | 
|  | } | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | static inline tf_float makeNaN128(uint64_t rand) { | 
|  | return fromRep128(0x7fff000000000000UL | (rand & 0xffffffffffffUL), 0x0UL); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static inline TYPE_FP16 makeInf16(void) | 
|  | { | 
|  | return fromRep16(0x7c00U); | 
|  | } | 
|  |  | 
|  | static inline float makeInf32(void) | 
|  | { | 
|  | return fromRep32(0x7f800000U); | 
|  | } | 
|  |  | 
|  | static inline float makeNegativeInf32(void) | 
|  | { | 
|  | return fromRep32(0xff800000U); | 
|  | } | 
|  |  | 
|  | static inline double makeInf64(void) | 
|  | { | 
|  | return fromRep64(0x7ff0000000000000UL); | 
|  | } | 
|  |  | 
|  | static inline double makeNegativeInf64(void) | 
|  | { | 
|  | return fromRep64(0xfff0000000000000UL); | 
|  | } | 
|  |  | 
|  | #if defined(CRT_HAS_TF_MODE) | 
|  | static inline tf_float makeInf128(void) { | 
|  | return fromRep128(0x7fff000000000000UL, 0x0UL); | 
|  | } | 
|  |  | 
|  | static inline tf_float makeNegativeInf128(void) { | 
|  | return fromRep128(0xffff000000000000UL, 0x0UL); | 
|  | } | 
|  | #endif |