fp_extend.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //===-lib/fp_extend.h - low precision -> high precision conversion -*- C
  2. //-*-===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Set source and destination setting
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef FP_EXTEND_HEADER
  14. #define FP_EXTEND_HEADER
  15. #include "int_lib.h"
  16. #if defined SRC_SINGLE
  17. typedef float src_t;
  18. typedef uint32_t src_rep_t;
  19. #define SRC_REP_C UINT32_C
  20. static const int srcBits = sizeof(src_t) * CHAR_BIT;
  21. static const int srcSigFracBits = 23;
  22. // -1 accounts for the sign bit.
  23. // srcBits - srcSigFracBits - 1
  24. static const int srcExpBits = 8;
  25. #define src_rep_t_clz clzsi
  26. #elif defined SRC_DOUBLE
  27. typedef double src_t;
  28. typedef uint64_t src_rep_t;
  29. #define SRC_REP_C UINT64_C
  30. static const int srcBits = sizeof(src_t) * CHAR_BIT;
  31. static const int srcSigFracBits = 52;
  32. // -1 accounts for the sign bit.
  33. // srcBits - srcSigFracBits - 1
  34. static const int srcExpBits = 11;
  35. static inline int src_rep_t_clz_impl(src_rep_t a) {
  36. #if defined __LP64__
  37. return __builtin_clzl(a);
  38. #else
  39. if (a & REP_C(0xffffffff00000000))
  40. return clzsi(a >> 32);
  41. else
  42. return 32 + clzsi(a & REP_C(0xffffffff));
  43. #endif
  44. }
  45. #define src_rep_t_clz src_rep_t_clz_impl
  46. #elif defined SRC_80
  47. typedef xf_float src_t;
  48. typedef __uint128_t src_rep_t;
  49. #define SRC_REP_C (__uint128_t)
  50. // sign bit, exponent and significand occupy the lower 80 bits.
  51. static const int srcBits = 80;
  52. static const int srcSigFracBits = 63;
  53. // -1 accounts for the sign bit.
  54. // -1 accounts for the explicitly stored integer bit.
  55. // srcBits - srcSigFracBits - 1 - 1
  56. static const int srcExpBits = 15;
  57. #elif defined SRC_HALF
  58. #ifdef COMPILER_RT_HAS_FLOAT16
  59. typedef _Float16 src_t;
  60. #else
  61. typedef uint16_t src_t;
  62. #endif
  63. typedef uint16_t src_rep_t;
  64. #define SRC_REP_C UINT16_C
  65. static const int srcBits = sizeof(src_t) * CHAR_BIT;
  66. static const int srcSigFracBits = 10;
  67. // -1 accounts for the sign bit.
  68. // srcBits - srcSigFracBits - 1
  69. static const int srcExpBits = 5;
  70. static inline int src_rep_t_clz_impl(src_rep_t a) {
  71. return __builtin_clz(a) - 16;
  72. }
  73. #define src_rep_t_clz src_rep_t_clz_impl
  74. #else
  75. #error Source should be half, single, or double precision!
  76. #endif // end source precision
  77. #if defined DST_SINGLE
  78. typedef float dst_t;
  79. typedef uint32_t dst_rep_t;
  80. #define DST_REP_C UINT32_C
  81. static const int dstBits = sizeof(dst_t) * CHAR_BIT;
  82. static const int dstSigFracBits = 23;
  83. // -1 accounts for the sign bit.
  84. // dstBits - dstSigFracBits - 1
  85. static const int dstExpBits = 8;
  86. #elif defined DST_DOUBLE
  87. typedef double dst_t;
  88. typedef uint64_t dst_rep_t;
  89. #define DST_REP_C UINT64_C
  90. static const int dstBits = sizeof(dst_t) * CHAR_BIT;
  91. static const int dstSigFracBits = 52;
  92. // -1 accounts for the sign bit.
  93. // dstBits - dstSigFracBits - 1
  94. static const int dstExpBits = 11;
  95. #elif defined DST_QUAD
  96. typedef tf_float dst_t;
  97. typedef __uint128_t dst_rep_t;
  98. #define DST_REP_C (__uint128_t)
  99. static const int dstBits = sizeof(dst_t) * CHAR_BIT;
  100. static const int dstSigFracBits = 112;
  101. // -1 accounts for the sign bit.
  102. // dstBits - dstSigFracBits - 1
  103. static const int dstExpBits = 15;
  104. #else
  105. #error Destination should be single, double, or quad precision!
  106. #endif // end destination precision
  107. // End of specialization parameters.
  108. // TODO: These helper routines should be placed into fp_lib.h
  109. // Currently they depend on macros/constants defined above.
  110. static inline src_rep_t extract_sign_from_src(src_rep_t x) {
  111. const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
  112. return (x & srcSignMask) >> (srcBits - 1);
  113. }
  114. static inline src_rep_t extract_exp_from_src(src_rep_t x) {
  115. const int srcSigBits = srcBits - 1 - srcExpBits;
  116. const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits;
  117. return (x & srcExpMask) >> srcSigBits;
  118. }
  119. static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) {
  120. const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1;
  121. return x & srcSigFracMask;
  122. }
  123. #ifdef src_rep_t_clz
  124. static inline int clz_in_sig_frac(src_rep_t sigFrac) {
  125. const int skip = 1 + srcExpBits;
  126. return src_rep_t_clz(sigFrac) - skip;
  127. }
  128. #endif
  129. static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) {
  130. return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
  131. }
  132. // Two helper routines for conversion to and from the representation of
  133. // floating-point data as integer values follow.
  134. static inline src_rep_t srcToRep(src_t x) {
  135. const union {
  136. src_t f;
  137. src_rep_t i;
  138. } rep = {.f = x};
  139. return rep.i;
  140. }
  141. static inline dst_t dstFromRep(dst_rep_t x) {
  142. const union {
  143. dst_t f;
  144. dst_rep_t i;
  145. } rep = {.i = x};
  146. return rep.f;
  147. }
  148. // End helper routines. Conversion implementation follows.
  149. #endif // FP_EXTEND_HEADER