brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.6 KiB · 3a8968a Raw
343 lines · c
1#include <assert.h>2#include <limits.h>3#include <stdint.h>4#include <stdlib.h>5#include <string.h>6 7#include "int_types.h"8 9#ifdef COMPILER_RT_HAS_FLOAT1610#define TYPE_FP16 _Float1611#else12#define TYPE_FP16 uint16_t13#endif14 15enum EXPECTED_RESULT {16    LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_017};18 19static inline TYPE_FP16 fromRep16(uint16_t x)20{21#ifdef COMPILER_RT_HAS_FLOAT1622    TYPE_FP16 ret;23    memcpy(&ret, &x, sizeof(ret));24    return ret;25#else26    return x;27#endif28}29 30static inline float fromRep32(uint32_t x)31{32    float ret;33    memcpy(&ret, &x, 4);34    return ret;35}36 37static inline double fromRep64(uint64_t x)38{39    double ret;40    memcpy(&ret, &x, 8);41    return ret;42}43 44#if defined(CRT_HAS_TF_MODE)45static inline tf_float fromRep128(uint64_t hi, uint64_t lo) {46    __uint128_t x = ((__uint128_t)hi << 64) + lo;47    tf_float ret;48    memcpy(&ret, &x, 16);49    return ret;50}51#endif52 53static inline uint16_t toRep16(TYPE_FP16 x)54{55#ifdef COMPILER_RT_HAS_FLOAT1656    uint16_t ret;57    memcpy(&ret, &x, sizeof(ret));58    return ret;59#else60    return x;61#endif62}63 64static inline uint32_t toRep32(float x)65{66    uint32_t ret;67    memcpy(&ret, &x, 4);68    return ret;69}70 71static inline uint64_t toRep64(double x)72{73    uint64_t ret;74    memcpy(&ret, &x, 8);75    return ret;76}77 78#if defined(CRT_HAS_TF_MODE)79static inline __uint128_t toRep128(tf_float x) {80    __uint128_t ret;81    memcpy(&ret, &x, 16);82    return ret;83}84#endif85 86static inline int compareResultH(TYPE_FP16 result,87                                 uint16_t expected)88{89    uint16_t rep = toRep16(result);90 91    if (rep == expected){92        return 0;93    }94    // test other possible NaN representation(signal NaN)95    else if (expected == 0x7e00U){96        if ((rep & 0x7c00U) == 0x7c00U &&97            (rep & 0x3ffU) > 0){98            return 0;99        }100    }101    return 1;102}103 104static inline int compareResultF(float result,105                                 uint32_t expected)106{107    uint32_t rep = toRep32(result);108 109    if (rep == expected){110        return 0;111    }112    // test other possible NaN representation(signal NaN)113    else if (expected == 0x7fc00000U){114        if ((rep & 0x7f800000U) == 0x7f800000U &&115            (rep & 0x7fffffU) > 0){116            return 0;117        }118    }119    return 1;120}121 122static inline int compareResultD(double result,123                                 uint64_t expected)124{125    uint64_t rep = toRep64(result);126 127    if (rep == expected){128        return 0;129    }130    // test other possible NaN representation(signal NaN)131    else if (expected == 0x7ff8000000000000UL){132        if ((rep & 0x7ff0000000000000UL) == 0x7ff0000000000000UL &&133            (rep & 0xfffffffffffffUL) > 0){134            return 0;135        }136    }137    return 1;138}139 140#if defined(CRT_HAS_TF_MODE)141// return 0 if equal142// use two 64-bit integers instead of one 128-bit integer143// because 128-bit integer constant can't be assigned directly144static inline int compareResultF128(tf_float result, uint64_t expectedHi,145                                    uint64_t expectedLo) {146    __uint128_t rep = toRep128(result);147    uint64_t hi = rep >> 64;148    uint64_t lo = rep;149 150    if (hi == expectedHi && lo == expectedLo) {151        return 0;152    }153    // test other possible NaN representation(signal NaN)154    else if (expectedHi == 0x7fff800000000000UL && expectedLo == 0x0UL) {155        if ((hi & 0x7fff000000000000UL) == 0x7fff000000000000UL &&156            ((hi & 0xffffffffffffUL) > 0 || lo > 0)) {157            return 0;158        }159    }160    return 1;161}162#endif163 164static inline int compareResultCMP(int result,165                                   enum EXPECTED_RESULT expected)166{167    switch(expected){168        case LESS_0:169            if (result < 0)170                return 0;171            break;172        case LESS_EQUAL_0:173            if (result <= 0)174                return 0;175            break;176        case EQUAL_0:177            if (result == 0)178                return 0;179            break;180        case NEQUAL_0:181            if (result != 0)182                return 0;183            break;184        case GREATER_EQUAL_0:185            if (result >= 0)186                return 0;187            break;188        case GREATER_0:189            if (result > 0)190                return 0;191            break;192        default:193            return 1;194    }195    return 1;196}197 198static inline char *expectedStr(enum EXPECTED_RESULT expected)199{200    switch(expected){201        case LESS_0:202            return "<0";203        case LESS_EQUAL_0:204            return "<=0";205        case EQUAL_0:206            return "=0";207        case NEQUAL_0:208            return "!=0";209        case GREATER_EQUAL_0:210            return ">=0";211        case GREATER_0:212            return ">0";213        default:214            return "";215    }216    return "";217}218 219static inline TYPE_FP16 makeQNaN16(void)220{221    return fromRep16(0x7e00U);222}223 224static inline float makeQNaN32(void)225{226    return fromRep32(0x7fc00000U);227}228 229static inline double makeQNaN64(void)230{231    return fromRep64(0x7ff8000000000000UL);232}233 234#if HAS_80_BIT_LONG_DOUBLE235static inline xf_float F80FromRep80(uint16_t hi, uint64_t lo) {236  uqwords bits;237  bits.high.all = hi;238  bits.low.all = lo;239  xf_float ret;240  static_assert(sizeof(xf_float) <= sizeof(uqwords), "wrong representation");241  memcpy(&ret, &bits, sizeof(ret));242  return ret;243}244 245static inline uqwords F80ToRep80(xf_float x) {246  uqwords ret;247  memset(&ret, 0, sizeof(ret));248  memcpy(&ret, &x, sizeof(x));249  // Any bits beyond the first 16 in high are undefined.250  ret.high.all = (uint16_t)ret.high.all;251  return ret;252}253 254static inline int compareResultF80(xf_float result, uint16_t expectedHi,255                                   uint64_t expectedLo) {256  uqwords rep = F80ToRep80(result);257  // F80 high occupies the lower 16 bits of high.258  assert((uint64_t)(uint16_t)rep.high.all == rep.high.all);259  return !(rep.high.all == expectedHi && rep.low.all == expectedLo);260}261 262static inline xf_float makeQNaN80(void) {263  return F80FromRep80(0x7fffu, 0xc000000000000000UL);264}265 266static inline xf_float makeNaN80(uint64_t rand) {267  return F80FromRep80(0x7fffu,268                      0x8000000000000000 | (rand & 0x3fffffffffffffff));269}270 271static inline xf_float makeInf80(void) {272  return F80FromRep80(0x7fffu, 0x8000000000000000UL);273}274 275static inline xf_float makeNegativeInf80(void) {276  return F80FromRep80(0xffffu, 0x8000000000000000UL);277}278#endif279 280#if defined(CRT_HAS_TF_MODE)281static inline tf_float makeQNaN128(void) {282    return fromRep128(0x7fff800000000000UL, 0x0UL);283}284#endif285 286static inline TYPE_FP16 makeNaN16(uint16_t rand)287{288    return fromRep16(0x7c00U | (rand & 0x7fffU));289}290 291static inline float makeNaN32(uint32_t rand)292{293    return fromRep32(0x7f800000U | (rand & 0x7fffffU));294}295 296static inline double makeNaN64(uint64_t rand)297{298    return fromRep64(0x7ff0000000000000UL | (rand & 0xfffffffffffffUL));299}300 301#if defined(CRT_HAS_TF_MODE)302static inline tf_float makeNaN128(uint64_t rand) {303    return fromRep128(0x7fff000000000000UL | (rand & 0xffffffffffffUL), 0x0UL);304}305#endif306 307static inline TYPE_FP16 makeInf16(void)308{309    return fromRep16(0x7c00U);310}311 312static inline TYPE_FP16 makeNegativeInf16(void) { return fromRep16(0xfc00U); }313 314static inline float makeInf32(void)315{316    return fromRep32(0x7f800000U);317}318 319static inline float makeNegativeInf32(void)320{321    return fromRep32(0xff800000U);322}323 324static inline double makeInf64(void)325{326    return fromRep64(0x7ff0000000000000UL);327}328 329static inline double makeNegativeInf64(void)330{331    return fromRep64(0xfff0000000000000UL);332}333 334#if defined(CRT_HAS_TF_MODE)335static inline tf_float makeInf128(void) {336    return fromRep128(0x7fff000000000000UL, 0x0UL);337}338 339static inline tf_float makeNegativeInf128(void) {340    return fromRep128(0xffff000000000000UL, 0x0UL);341}342#endif343