int_to_fp_impl.inc (8930B)
1 //===-- int_to_fp_impl.inc - integer to floating point conversion ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Thsi file implements a generic conversion from an integer type to an 10 // IEEE-754 floating point type, allowing a common implementation to be hsared 11 // without copy and paste. 12 // 13 //===----------------------------------------------------------------------===// 14 15 // ---- int_to_fp.h (was a separate header; merged) ---- 16 #include "int_lib.h" 17 18 // Self-clean any prior inclusion's per-(src, dst) state. May coexist with 19 // fp_extend.h / fp_trunc.h which define overlapping bare-name aliases. 20 #undef _INT_TO_FP_SRC_SUF 21 #undef _INT_TO_FP_DST_SUF 22 #undef SRC_REP_C 23 #undef DST_REP_C 24 #undef src_t 25 #undef usrc_t 26 #undef dst_t 27 #undef dst_rep_t 28 #undef clzSrcT 29 #undef dstFromRep 30 #undef dstSigBits 31 32 #if defined SRC_I64 33 #define _INT_TO_FP_SRC_SUF i64 34 #elif defined SRC_U64 35 #define _INT_TO_FP_SRC_SUF u64 36 #elif defined SRC_I128 37 #define _INT_TO_FP_SRC_SUF i128 38 #elif defined SRC_U128 39 #define _INT_TO_FP_SRC_SUF u128 40 #else 41 #error Source should be a handled integer type. 42 #endif 43 44 #if defined DST_SINGLE 45 #define _INT_TO_FP_DST_SUF sf 46 #elif defined DST_DOUBLE 47 #define _INT_TO_FP_DST_SUF df 48 #elif defined DST_QUAD 49 #define _INT_TO_FP_DST_SUF tf 50 #else 51 #error Destination should be a handled floating point type 52 #endif 53 54 #define _INT_TO_FP_PASTE4_(a, b, c, d) a##b##c##d 55 #define _INT_TO_FP_PASTE4(a, b, c, d) _INT_TO_FP_PASTE4_(a, b, c, d) 56 #define _INT_TO_FP_PAIR(stem) _INT_TO_FP_PASTE4(stem, _, _INT_TO_FP_SRC_SUF, _INT_TO_FP_DST_SUF) 57 58 // ---- Bare-name aliases (re-set every inclusion). ------------------------ 59 60 #define src_t _INT_TO_FP_PAIR(src_t) 61 #define usrc_t _INT_TO_FP_PAIR(usrc_t) 62 #define dst_t _INT_TO_FP_PAIR(dst_t) 63 #define dst_rep_t _INT_TO_FP_PAIR(dst_rep_t) 64 #define clzSrcT _INT_TO_FP_PAIR(clzSrcT) 65 #define dstFromRep _INT_TO_FP_PAIR(dstFromRep) 66 #define dstSigBits _INT_TO_FP_PAIR(dstSigBits) 67 68 // DST_REP_C: simple textual macro per dst. 69 #if defined DST_SINGLE 70 #define DST_REP_C UINT32_C 71 #elif defined DST_DOUBLE 72 #define DST_REP_C UINT64_C 73 #elif defined DST_QUAD 74 #define DST_REP_C (__uint128_t) 75 #endif 76 77 // ---- One-time emission per (TU, src+dst pair). -------------------------- 78 // Pairs kit uses: (i64,u64) × (sf,df) and (i128,u128) × (sf,df,tf). 79 80 #if defined SRC_I64 && defined DST_SINGLE && !defined INT_TO_FP_I64SF_EMITTED 81 #define INT_TO_FP_I64SF_EMITTED 82 #define _INT_TO_FP_EMIT 1 83 #elif defined SRC_I64 && defined DST_DOUBLE && !defined INT_TO_FP_I64DF_EMITTED 84 #define INT_TO_FP_I64DF_EMITTED 85 #define _INT_TO_FP_EMIT 1 86 #elif defined SRC_U64 && defined DST_SINGLE && !defined INT_TO_FP_U64SF_EMITTED 87 #define INT_TO_FP_U64SF_EMITTED 88 #define _INT_TO_FP_EMIT 1 89 #elif defined SRC_U64 && defined DST_DOUBLE && !defined INT_TO_FP_U64DF_EMITTED 90 #define INT_TO_FP_U64DF_EMITTED 91 #define _INT_TO_FP_EMIT 1 92 #elif defined SRC_I128 && defined DST_SINGLE && !defined INT_TO_FP_I128SF_EMITTED 93 #define INT_TO_FP_I128SF_EMITTED 94 #define _INT_TO_FP_EMIT 1 95 #elif defined SRC_I128 && defined DST_DOUBLE && !defined INT_TO_FP_I128DF_EMITTED 96 #define INT_TO_FP_I128DF_EMITTED 97 #define _INT_TO_FP_EMIT 1 98 #elif defined SRC_I128 && defined DST_QUAD && !defined INT_TO_FP_I128TF_EMITTED 99 #define INT_TO_FP_I128TF_EMITTED 100 #define _INT_TO_FP_EMIT 1 101 #elif defined SRC_U128 && defined DST_SINGLE && !defined INT_TO_FP_U128SF_EMITTED 102 #define INT_TO_FP_U128SF_EMITTED 103 #define _INT_TO_FP_EMIT 1 104 #elif defined SRC_U128 && defined DST_DOUBLE && !defined INT_TO_FP_U128DF_EMITTED 105 #define INT_TO_FP_U128DF_EMITTED 106 #define _INT_TO_FP_EMIT 1 107 #elif defined SRC_U128 && defined DST_QUAD && !defined INT_TO_FP_U128TF_EMITTED 108 #define INT_TO_FP_U128TF_EMITTED 109 #define _INT_TO_FP_EMIT 1 110 #endif 111 112 #ifdef _INT_TO_FP_EMIT 113 #undef _INT_TO_FP_EMIT 114 115 #if defined SRC_I64 116 typedef int64_t src_t; 117 typedef uint64_t usrc_t; 118 static inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } 119 120 #elif defined SRC_U64 121 typedef uint64_t src_t; 122 typedef uint64_t usrc_t; 123 static inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } 124 125 #elif defined SRC_I128 126 typedef __int128_t src_t; 127 typedef __uint128_t usrc_t; 128 static inline int clzSrcT(usrc_t x) { return __clzti2(x); } 129 130 #elif defined SRC_U128 131 typedef __uint128_t src_t; 132 typedef __uint128_t usrc_t; 133 static inline int clzSrcT(usrc_t x) { return __clzti2(x); } 134 135 #endif 136 137 #if defined DST_SINGLE 138 typedef float dst_t; 139 typedef uint32_t dst_rep_t; 140 141 enum { 142 dstSigBits = 23, 143 }; 144 145 #elif defined DST_DOUBLE 146 typedef double dst_t; 147 typedef uint64_t dst_rep_t; 148 149 enum { 150 dstSigBits = 52, 151 }; 152 153 #elif defined DST_QUAD 154 typedef tf_float dst_t; 155 typedef __uint128_t dst_rep_t; 156 157 enum { 158 dstSigBits = 112, 159 }; 160 161 #endif 162 163 static inline dst_t dstFromRep(dst_rep_t x) { 164 const union { 165 dst_t f; 166 dst_rep_t i; 167 } rep = {.i = x}; 168 return rep.f; 169 } 170 171 #endif // _INT_TO_FP_EMIT 172 173 #define __floatXiYf__ _INT_TO_FP_PAIR(__floatXiYf__) 174 175 #if defined SRC_I64 && defined DST_SINGLE && !defined INT_TO_FP_IMPL_I64SF_EMITTED 176 #define INT_TO_FP_IMPL_I64SF_EMITTED 177 #define _INT_TO_FP_IMPL_EMIT 1 178 #elif defined SRC_I64 && defined DST_DOUBLE && !defined INT_TO_FP_IMPL_I64DF_EMITTED 179 #define INT_TO_FP_IMPL_I64DF_EMITTED 180 #define _INT_TO_FP_IMPL_EMIT 1 181 #elif defined SRC_U64 && defined DST_SINGLE && !defined INT_TO_FP_IMPL_U64SF_EMITTED 182 #define INT_TO_FP_IMPL_U64SF_EMITTED 183 #define _INT_TO_FP_IMPL_EMIT 1 184 #elif defined SRC_U64 && defined DST_DOUBLE && !defined INT_TO_FP_IMPL_U64DF_EMITTED 185 #define INT_TO_FP_IMPL_U64DF_EMITTED 186 #define _INT_TO_FP_IMPL_EMIT 1 187 #elif defined SRC_I128 && defined DST_SINGLE && !defined INT_TO_FP_IMPL_I128SF_EMITTED 188 #define INT_TO_FP_IMPL_I128SF_EMITTED 189 #define _INT_TO_FP_IMPL_EMIT 1 190 #elif defined SRC_I128 && defined DST_DOUBLE && !defined INT_TO_FP_IMPL_I128DF_EMITTED 191 #define INT_TO_FP_IMPL_I128DF_EMITTED 192 #define _INT_TO_FP_IMPL_EMIT 1 193 #elif defined SRC_I128 && defined DST_QUAD && !defined INT_TO_FP_IMPL_I128TF_EMITTED 194 #define INT_TO_FP_IMPL_I128TF_EMITTED 195 #define _INT_TO_FP_IMPL_EMIT 1 196 #elif defined SRC_U128 && defined DST_SINGLE && !defined INT_TO_FP_IMPL_U128SF_EMITTED 197 #define INT_TO_FP_IMPL_U128SF_EMITTED 198 #define _INT_TO_FP_IMPL_EMIT 1 199 #elif defined SRC_U128 && defined DST_DOUBLE && !defined INT_TO_FP_IMPL_U128DF_EMITTED 200 #define INT_TO_FP_IMPL_U128DF_EMITTED 201 #define _INT_TO_FP_IMPL_EMIT 1 202 #elif defined SRC_U128 && defined DST_QUAD && !defined INT_TO_FP_IMPL_U128TF_EMITTED 203 #define INT_TO_FP_IMPL_U128TF_EMITTED 204 #define _INT_TO_FP_IMPL_EMIT 1 205 #endif 206 207 #ifdef _INT_TO_FP_IMPL_EMIT 208 #undef _INT_TO_FP_IMPL_EMIT 209 210 static inline dst_t __floatXiYf__(src_t a) { 211 if (a == 0) 212 return 0.0; 213 214 enum { 215 dstMantDig = dstSigBits + 1, 216 srcBits = sizeof(src_t) * CHAR_BIT, 217 srcIsSigned = ((src_t)-1) < 0, 218 }; 219 220 const src_t s = srcIsSigned ? a >> (srcBits - 1) : 0; 221 222 a = (usrc_t)(a ^ s) - s; 223 int sd = srcBits - clzSrcT(a); // number of significant digits 224 int e = sd - 1; // exponent 225 if (sd > dstMantDig) { 226 // start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 227 // finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 228 // 12345678901234567890123456 229 // 1 = msb 1 bit 230 // P = bit dstMantDig-1 bits to the right of 1 231 // Q = bit dstMantDig bits to the right of 1 232 // R = "or" of all bits to the right of Q 233 if (sd == dstMantDig + 1) { 234 a <<= 1; 235 } else if (sd == dstMantDig + 2) { 236 // Do nothing. 237 } else { 238 a = ((usrc_t)a >> (sd - (dstMantDig + 2))) | 239 ((a & ((usrc_t)(-1) >> ((srcBits + dstMantDig + 2) - sd))) != 0); 240 } 241 // finish: 242 a |= (a & 4) != 0; // Or P into R 243 ++a; // round - this step may add a significant bit 244 a >>= 2; // dump Q and R 245 // a is now rounded to dstMantDig or dstMantDig+1 bits 246 if (a & ((usrc_t)1 << dstMantDig)) { 247 a >>= 1; 248 ++e; 249 } 250 // a is now rounded to dstMantDig bits 251 } else { 252 a <<= (dstMantDig - sd); 253 // a is now rounded to dstMantDig bits 254 } 255 const int dstBits = sizeof(dst_t) * CHAR_BIT; 256 const dst_rep_t dstSignMask = DST_REP_C(1) << (dstBits - 1); 257 const int dstExpBits = dstBits - dstSigBits - 1; 258 const int dstExpBias = (1 << (dstExpBits - 1)) - 1; 259 const dst_rep_t dstSignificandMask = (DST_REP_C(1) << dstSigBits) - 1; 260 // Combine sign, exponent, and mantissa. 261 const dst_rep_t result = ((dst_rep_t)s & dstSignMask) | 262 ((dst_rep_t)(e + dstExpBias) << dstSigBits) | 263 ((dst_rep_t)(a) & dstSignificandMask); 264 return dstFromRep(result); 265 } 266 267 #endif // _INT_TO_FP_IMPL_EMIT