master
  1//===-- Abstract class for bit manipulation of float numbers. ---*- C++ -*-===//
  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// -----------------------------------------------------------------------------
 10//                               **** WARNING ****
 11// This file is shared with libc++. You should also be careful when adding
 12// dependencies to this file, since it needs to build for all libc++ targets.
 13// -----------------------------------------------------------------------------
 14
 15#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
 16#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
 17
 18#include "src/__support/CPP/bit.h"
 19#include "src/__support/CPP/type_traits.h"
 20#include "src/__support/common.h"
 21#include "src/__support/libc_assert.h"       // LIBC_ASSERT
 22#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
 23#include "src/__support/macros/config.h"
 24#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_FLOAT128
 25#include "src/__support/math_extras.h"             // mask_trailing_ones
 26#include "src/__support/sign.h"                    // Sign
 27#include "src/__support/uint128.h"
 28
 29#include <stdint.h>
 30
 31namespace LIBC_NAMESPACE_DECL {
 32namespace fputil {
 33
 34// The supported floating point types.
 35enum class FPType {
 36  IEEE754_Binary16,
 37  IEEE754_Binary32,
 38  IEEE754_Binary64,
 39  IEEE754_Binary128,
 40  X86_Binary80,
 41  BFloat16
 42};
 43
 44// The classes hierarchy is as follows:
 45//
 46//             ┌───────────────────┐
 47//             │ FPLayout<FPType>  │
 48//             └─────────▲─────────┘
 49//                       │
 50//             ┌─────────┴─────────┐
 51//             │ FPStorage<FPType> │
 52//             └─────────▲─────────┘
 53//                       │
 54//          ┌────────────┴─────────────┐
 55//          │                          │
 56// ┌────────┴─────────┐ ┌──────────────┴──────────────────┐
 57// │ FPRepSem<FPType> │ │  FPRepSem<FPType::X86_Binary80  │
 58// └────────▲─────────┘ └──────────────▲──────────────────┘
 59//          │                          │
 60//          └────────────┬─────────────┘
 61//                       │
 62//               ┌───────┴───────┐
 63//               │  FPRepImpl<T> │
 64//               └───────▲───────┘
 65//                       │
 66//              ┌────────┴────────┐
 67//        ┌─────┴─────┐     ┌─────┴─────┐
 68//        │  FPRep<T> │     │ FPBits<T> │
 69//        └───────────┘     └───────────┘
 70//
 71// - 'FPLayout' defines only a few constants, namely the 'StorageType' and
 72//   length of the sign, the exponent, fraction and significand parts.
 73// - 'FPStorage' builds more constants on top of those from 'FPLayout' like
 74//   exponent bias and masks. It also holds the bit representation of the
 75//   floating point as a 'StorageType' type and defines tools to assemble or
 76//   test these parts.
 77// - 'FPRepSem' defines functions to interact semantically with the floating
 78//   point representation. The default implementation is the one for 'IEEE754',
 79//   a specialization is provided for X86 Extended Precision.
 80// - 'FPRepImpl' derives from 'FPRepSem' and adds functions that are common to
 81//   all implementations or build on the ones in 'FPRepSem'.
 82// - 'FPRep' exposes all functions from 'FPRepImpl' and returns 'FPRep'
 83//   instances when using Builders (static functions to create values).
 84// - 'FPBits' exposes all the functions from 'FPRepImpl' but operates on the
 85//   native C++ floating point type instead of 'FPType'. An additional 'get_val'
 86//   function allows getting the C++ floating point type value back. Builders
 87//   called from 'FPBits' return 'FPBits' instances.
 88
 89namespace internal {
 90
 91// Defines the layout (sign, exponent, significand) of a floating point type in
 92// memory. It also defines its associated StorageType, i.e., the unsigned
 93// integer type used to manipulate its representation.
 94// Additionally we provide the fractional part length, i.e., the number of bits
 95// after the decimal dot when the number is in normal form.
 96template <FPType> struct FPLayout {};
 97
 98template <> struct FPLayout<FPType::IEEE754_Binary16> {
 99  using StorageType = uint16_t;
100  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
101  LIBC_INLINE_VAR static constexpr int EXP_LEN = 5;
102  LIBC_INLINE_VAR static constexpr int SIG_LEN = 10;
103  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
104};
105
106template <> struct FPLayout<FPType::IEEE754_Binary32> {
107  using StorageType = uint32_t;
108  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
109  LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
110  LIBC_INLINE_VAR static constexpr int SIG_LEN = 23;
111  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
112};
113
114template <> struct FPLayout<FPType::IEEE754_Binary64> {
115  using StorageType = uint64_t;
116  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
117  LIBC_INLINE_VAR static constexpr int EXP_LEN = 11;
118  LIBC_INLINE_VAR static constexpr int SIG_LEN = 52;
119  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
120};
121
122template <> struct FPLayout<FPType::IEEE754_Binary128> {
123  using StorageType = UInt128;
124  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
125  LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
126  LIBC_INLINE_VAR static constexpr int SIG_LEN = 112;
127  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
128};
129
130template <> struct FPLayout<FPType::X86_Binary80> {
131#if __SIZEOF_LONG_DOUBLE__ == 12
132  using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
133#else
134  using StorageType = UInt128;
135#endif
136  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
137  LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
138  LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
139  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;
140};
141
142template <> struct FPLayout<FPType::BFloat16> {
143  using StorageType = uint16_t;
144  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
145  LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
146  LIBC_INLINE_VAR static constexpr int SIG_LEN = 7;
147  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
148};
149
150// FPStorage derives useful constants from the FPLayout above.
151template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
152  using UP = FPLayout<fp_type>;
153
154  using UP::EXP_LEN;  // The number of bits for the *exponent* part
155  using UP::SIG_LEN;  // The number of bits for the *significand* part
156  using UP::SIGN_LEN; // The number of bits for the *sign* part
157  // For convenience, the sum of `SIG_LEN`, `EXP_LEN`, and `SIGN_LEN`.
158  LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + EXP_LEN + SIG_LEN;
159
160  // The number of bits after the decimal dot when the number is in normal form.
161  using UP::FRACTION_LEN;
162
163  // An unsigned integer that is wide enough to contain all of the floating
164  // point bits.
165  using StorageType = typename UP::StorageType;
166
167  // The number of bits in StorageType.
168  LIBC_INLINE_VAR static constexpr int STORAGE_LEN =
169      sizeof(StorageType) * CHAR_BIT;
170  static_assert(STORAGE_LEN >= TOTAL_LEN);
171
172  // The exponent bias. Always positive.
173  LIBC_INLINE_VAR static constexpr int32_t EXP_BIAS =
174      (1U << (EXP_LEN - 1U)) - 1U;
175  static_assert(EXP_BIAS > 0);
176
177  // The bit pattern that keeps only the *significand* part.
178  LIBC_INLINE_VAR static constexpr StorageType SIG_MASK =
179      mask_trailing_ones<StorageType, SIG_LEN>();
180  // The bit pattern that keeps only the *exponent* part.
181  LIBC_INLINE_VAR static constexpr StorageType EXP_MASK =
182      mask_trailing_ones<StorageType, EXP_LEN>() << SIG_LEN;
183  // The bit pattern that keeps only the *sign* part.
184  LIBC_INLINE_VAR static constexpr StorageType SIGN_MASK =
185      mask_trailing_ones<StorageType, SIGN_LEN>() << (EXP_LEN + SIG_LEN);
186  // The bit pattern that keeps only the *exponent + significand* part.
187  LIBC_INLINE_VAR static constexpr StorageType EXP_SIG_MASK =
188      mask_trailing_ones<StorageType, EXP_LEN + SIG_LEN>();
189  // The bit pattern that keeps only the *sign + exponent + significand* part.
190  LIBC_INLINE_VAR static constexpr StorageType FP_MASK =
191      mask_trailing_ones<StorageType, TOTAL_LEN>();
192  // The bit pattern that keeps only the *fraction* part.
193  // i.e., the *significand* without the leading one.
194  LIBC_INLINE_VAR static constexpr StorageType FRACTION_MASK =
195      mask_trailing_ones<StorageType, FRACTION_LEN>();
196
197  static_assert((SIG_MASK & EXP_MASK & SIGN_MASK) == 0, "masks disjoint");
198  static_assert((SIG_MASK | EXP_MASK | SIGN_MASK) == FP_MASK, "masks cover");
199
200protected:
201  // Merge bits from 'a' and 'b' values according to 'mask'.
202  // Use 'a' bits when corresponding 'mask' bits are zeroes and 'b' bits when
203  // corresponding bits are ones.
204  LIBC_INLINE static constexpr StorageType merge(StorageType a, StorageType b,
205                                                 StorageType mask) {
206    // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
207    return a ^ ((a ^ b) & mask);
208  }
209
210  // A stongly typed integer that prevents mixing and matching integers with
211  // different semantics.
212  template <typename T> struct TypedInt {
213    using value_type = T;
214    LIBC_INLINE constexpr explicit TypedInt(T value) : value(value) {}
215    LIBC_INLINE constexpr TypedInt(const TypedInt &value) = default;
216    LIBC_INLINE constexpr TypedInt &operator=(const TypedInt &value) = default;
217
218    LIBC_INLINE constexpr explicit operator T() const { return value; }
219
220    LIBC_INLINE constexpr StorageType to_storage_type() const {
221      return StorageType(value);
222    }
223
224    LIBC_INLINE friend constexpr bool operator==(TypedInt a, TypedInt b) {
225      return a.value == b.value;
226    }
227    LIBC_INLINE friend constexpr bool operator!=(TypedInt a, TypedInt b) {
228      return a.value != b.value;
229    }
230
231  protected:
232    T value;
233  };
234
235  // An opaque type to store a floating point exponent.
236  // We define special values but it is valid to create arbitrary values as long
237  // as they are in the range [min, max].
238  struct Exponent : public TypedInt<int32_t> {
239    using UP = TypedInt<int32_t>;
240    using UP::UP;
241    LIBC_INLINE static constexpr auto subnormal() {
242      return Exponent(-EXP_BIAS);
243    }
244    LIBC_INLINE static constexpr auto min() { return Exponent(1 - EXP_BIAS); }
245    LIBC_INLINE static constexpr auto zero() { return Exponent(0); }
246    LIBC_INLINE static constexpr auto max() { return Exponent(EXP_BIAS); }
247    LIBC_INLINE static constexpr auto inf() { return Exponent(EXP_BIAS + 1); }
248  };
249
250  // An opaque type to store a floating point biased exponent.
251  // We define special values but it is valid to create arbitrary values as long
252  // as they are in the range [zero, bits_all_ones].
253  // Values greater than bits_all_ones are truncated.
254  struct BiasedExponent : public TypedInt<uint32_t> {
255    using UP = TypedInt<uint32_t>;
256    using UP::UP;
257
258    LIBC_INLINE constexpr BiasedExponent(Exponent exp)
259        : UP(static_cast<uint32_t>(static_cast<int32_t>(exp) + EXP_BIAS)) {}
260
261    // Cast operator to get convert from BiasedExponent to Exponent.
262    LIBC_INLINE constexpr operator Exponent() const {
263      return Exponent(static_cast<int32_t>(UP::value - EXP_BIAS));
264    }
265
266    LIBC_INLINE constexpr BiasedExponent &operator++() {
267      LIBC_ASSERT(*this != BiasedExponent(Exponent::inf()));
268      ++UP::value;
269      return *this;
270    }
271
272    LIBC_INLINE constexpr BiasedExponent &operator--() {
273      LIBC_ASSERT(*this != BiasedExponent(Exponent::subnormal()));
274      --UP::value;
275      return *this;
276    }
277  };
278
279  // An opaque type to store a floating point significand.
280  // We define special values but it is valid to create arbitrary values as long
281  // as they are in the range [zero, bits_all_ones].
282  // Note that the semantics of the Significand are implementation dependent.
283  // Values greater than bits_all_ones are truncated.
284  struct Significand : public TypedInt<StorageType> {
285    using UP = TypedInt<StorageType>;
286    using UP::UP;
287
288    LIBC_INLINE friend constexpr Significand operator|(const Significand a,
289                                                       const Significand b) {
290      return Significand(
291          StorageType(a.to_storage_type() | b.to_storage_type()));
292    }
293    LIBC_INLINE friend constexpr Significand operator^(const Significand a,
294                                                       const Significand b) {
295      return Significand(
296          StorageType(a.to_storage_type() ^ b.to_storage_type()));
297    }
298    LIBC_INLINE friend constexpr Significand operator>>(const Significand a,
299                                                        int shift) {
300      return Significand(StorageType(a.to_storage_type() >> shift));
301    }
302
303    LIBC_INLINE static constexpr auto zero() {
304      return Significand(StorageType(0));
305    }
306    LIBC_INLINE static constexpr auto lsb() {
307      return Significand(StorageType(1));
308    }
309    LIBC_INLINE static constexpr auto msb() {
310      return Significand(StorageType(1) << (SIG_LEN - 1));
311    }
312    LIBC_INLINE static constexpr auto bits_all_ones() {
313      return Significand(SIG_MASK);
314    }
315  };
316
317  LIBC_INLINE static constexpr StorageType encode(BiasedExponent exp) {
318    return (exp.to_storage_type() << SIG_LEN) & EXP_MASK;
319  }
320
321  LIBC_INLINE static constexpr StorageType encode(Significand value) {
322    return value.to_storage_type() & SIG_MASK;
323  }
324
325  LIBC_INLINE static constexpr StorageType encode(BiasedExponent exp,
326                                                  Significand sig) {
327    return encode(exp) | encode(sig);
328  }
329
330  LIBC_INLINE static constexpr StorageType encode(Sign sign, BiasedExponent exp,
331                                                  Significand sig) {
332    if (sign.is_neg())
333      return SIGN_MASK | encode(exp, sig);
334    return encode(exp, sig);
335  }
336
337  // The floating point number representation as an unsigned integer.
338  StorageType bits{};
339
340  LIBC_INLINE constexpr FPStorage() : bits(0) {}
341  LIBC_INLINE constexpr FPStorage(StorageType value) : bits(value) {}
342
343  // Observers
344  LIBC_INLINE constexpr StorageType exp_bits() const { return bits & EXP_MASK; }
345  LIBC_INLINE constexpr StorageType sig_bits() const { return bits & SIG_MASK; }
346  LIBC_INLINE constexpr StorageType exp_sig_bits() const {
347    return bits & EXP_SIG_MASK;
348  }
349
350  // Parts
351  LIBC_INLINE constexpr BiasedExponent biased_exponent() const {
352    return BiasedExponent(static_cast<uint32_t>(exp_bits() >> SIG_LEN));
353  }
354  LIBC_INLINE constexpr void set_biased_exponent(BiasedExponent biased) {
355    bits = merge(bits, encode(biased), EXP_MASK);
356  }
357
358public:
359  LIBC_INLINE constexpr Sign sign() const {
360    return (bits & SIGN_MASK) ? Sign::NEG : Sign::POS;
361  }
362  LIBC_INLINE constexpr void set_sign(Sign signVal) {
363    if (sign() != signVal)
364      bits ^= SIGN_MASK;
365  }
366};
367
368// This layer defines all functions that are specific to how the the floating
369// point type is encoded. It enables constructions, modification and observation
370// of values manipulated as 'StorageType'.
371template <FPType fp_type, typename RetT>
372struct FPRepSem : public FPStorage<fp_type> {
373  using UP = FPStorage<fp_type>;
374  using typename UP::StorageType;
375  using UP::FRACTION_LEN;
376  using UP::FRACTION_MASK;
377
378protected:
379  using typename UP::Exponent;
380  using typename UP::Significand;
381  using UP::bits;
382  using UP::encode;
383  using UP::exp_bits;
384  using UP::exp_sig_bits;
385  using UP::sig_bits;
386  using UP::UP;
387
388public:
389  // Builders
390  LIBC_INLINE static constexpr RetT zero(Sign sign = Sign::POS) {
391    return RetT(encode(sign, Exponent::subnormal(), Significand::zero()));
392  }
393  LIBC_INLINE static constexpr RetT one(Sign sign = Sign::POS) {
394    return RetT(encode(sign, Exponent::zero(), Significand::zero()));
395  }
396  LIBC_INLINE static constexpr RetT min_subnormal(Sign sign = Sign::POS) {
397    return RetT(encode(sign, Exponent::subnormal(), Significand::lsb()));
398  }
399  LIBC_INLINE static constexpr RetT max_subnormal(Sign sign = Sign::POS) {
400    return RetT(
401        encode(sign, Exponent::subnormal(), Significand::bits_all_ones()));
402  }
403  LIBC_INLINE static constexpr RetT min_normal(Sign sign = Sign::POS) {
404    return RetT(encode(sign, Exponent::min(), Significand::zero()));
405  }
406  LIBC_INLINE static constexpr RetT max_normal(Sign sign = Sign::POS) {
407    return RetT(encode(sign, Exponent::max(), Significand::bits_all_ones()));
408  }
409  LIBC_INLINE static constexpr RetT inf(Sign sign = Sign::POS) {
410    return RetT(encode(sign, Exponent::inf(), Significand::zero()));
411  }
412  LIBC_INLINE static constexpr RetT signaling_nan(Sign sign = Sign::POS,
413                                                  StorageType v = 0) {
414    return RetT(encode(sign, Exponent::inf(),
415                       (v ? Significand(v) : (Significand::msb() >> 1))));
416  }
417  LIBC_INLINE static constexpr RetT quiet_nan(Sign sign = Sign::POS,
418                                              StorageType v = 0) {
419    return RetT(
420        encode(sign, Exponent::inf(), Significand::msb() | Significand(v)));
421  }
422
423  // Observers
424  LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; }
425  LIBC_INLINE constexpr bool is_nan() const {
426    return exp_sig_bits() > encode(Exponent::inf(), Significand::zero());
427  }
428  LIBC_INLINE constexpr bool is_quiet_nan() const {
429    return exp_sig_bits() >= encode(Exponent::inf(), Significand::msb());
430  }
431  LIBC_INLINE constexpr bool is_signaling_nan() const {
432    return is_nan() && !is_quiet_nan();
433  }
434  LIBC_INLINE constexpr bool is_inf() const {
435    return exp_sig_bits() == encode(Exponent::inf(), Significand::zero());
436  }
437  LIBC_INLINE constexpr bool is_finite() const {
438    return exp_bits() != encode(Exponent::inf());
439  }
440  LIBC_INLINE
441  constexpr bool is_subnormal() const {
442    return exp_bits() == encode(Exponent::subnormal());
443  }
444  LIBC_INLINE constexpr bool is_normal() const {
445    return is_finite() && !is_subnormal();
446  }
447  LIBC_INLINE constexpr RetT next_toward_inf() const {
448    if (is_finite())
449      return RetT(bits + StorageType(1));
450    return RetT(bits);
451  }
452
453  // Returns the mantissa with the implicit bit set iff the current
454  // value is a valid normal number.
455  LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
456    if (is_subnormal())
457      return sig_bits();
458    return (StorageType(1) << UP::SIG_LEN) | sig_bits();
459  }
460};
461
462// Specialization for the X86 Extended Precision type.
463template <typename RetT>
464struct FPRepSem<FPType::X86_Binary80, RetT>
465    : public FPStorage<FPType::X86_Binary80> {
466  using UP = FPStorage<FPType::X86_Binary80>;
467  using typename UP::StorageType;
468  using UP::FRACTION_LEN;
469  using UP::FRACTION_MASK;
470
471  // The x86 80 bit float represents the leading digit of the mantissa
472  // explicitly. This is the mask for that bit.
473  static constexpr StorageType EXPLICIT_BIT_MASK = StorageType(1)
474                                                   << FRACTION_LEN;
475  // The X80 significand is made of an explicit bit and the fractional part.
476  static_assert((EXPLICIT_BIT_MASK & FRACTION_MASK) == 0,
477                "the explicit bit and the fractional part should not overlap");
478  static_assert((EXPLICIT_BIT_MASK | FRACTION_MASK) == SIG_MASK,
479                "the explicit bit and the fractional part should cover the "
480                "whole significand");
481
482protected:
483  using typename UP::Exponent;
484  using typename UP::Significand;
485  using UP::encode;
486  using UP::UP;
487
488public:
489  // Builders
490  LIBC_INLINE static constexpr RetT zero(Sign sign = Sign::POS) {
491    return RetT(encode(sign, Exponent::subnormal(), Significand::zero()));
492  }
493  LIBC_INLINE static constexpr RetT one(Sign sign = Sign::POS) {
494    return RetT(encode(sign, Exponent::zero(), Significand::msb()));
495  }
496  LIBC_INLINE static constexpr RetT min_subnormal(Sign sign = Sign::POS) {
497    return RetT(encode(sign, Exponent::subnormal(), Significand::lsb()));
498  }
499  LIBC_INLINE static constexpr RetT max_subnormal(Sign sign = Sign::POS) {
500    return RetT(encode(sign, Exponent::subnormal(),
501                       Significand::bits_all_ones() ^ Significand::msb()));
502  }
503  LIBC_INLINE static constexpr RetT min_normal(Sign sign = Sign::POS) {
504    return RetT(encode(sign, Exponent::min(), Significand::msb()));
505  }
506  LIBC_INLINE static constexpr RetT max_normal(Sign sign = Sign::POS) {
507    return RetT(encode(sign, Exponent::max(), Significand::bits_all_ones()));
508  }
509  LIBC_INLINE static constexpr RetT inf(Sign sign = Sign::POS) {
510    return RetT(encode(sign, Exponent::inf(), Significand::msb()));
511  }
512  LIBC_INLINE static constexpr RetT signaling_nan(Sign sign = Sign::POS,
513                                                  StorageType v = 0) {
514    return RetT(encode(sign, Exponent::inf(),
515                       Significand::msb() |
516                           (v ? Significand(v) : (Significand::msb() >> 2))));
517  }
518  LIBC_INLINE static constexpr RetT quiet_nan(Sign sign = Sign::POS,
519                                              StorageType v = 0) {
520    return RetT(encode(sign, Exponent::inf(),
521                       Significand::msb() | (Significand::msb() >> 1) |
522                           Significand(v)));
523  }
524
525  // Observers
526  LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; }
527  LIBC_INLINE constexpr bool is_nan() const {
528    // Most encoding forms from the table found in
529    // https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format
530    // are interpreted as NaN.
531    // More precisely :
532    // - Pseudo-Infinity
533    // - Pseudo Not a Number
534    // - Signalling Not a Number
535    // - Floating-point Indefinite
536    // - Quiet Not a Number
537    // - Unnormal
538    // This can be reduced to the following logic:
539    if (exp_bits() == encode(Exponent::inf()))
540      return !is_inf();
541    if (exp_bits() != encode(Exponent::subnormal()))
542      return (sig_bits() & encode(Significand::msb())) == 0;
543    return false;
544  }
545  LIBC_INLINE constexpr bool is_quiet_nan() const {
546    return exp_sig_bits() >=
547           encode(Exponent::inf(),
548                  Significand::msb() | (Significand::msb() >> 1));
549  }
550  LIBC_INLINE constexpr bool is_signaling_nan() const {
551    return is_nan() && !is_quiet_nan();
552  }
553  LIBC_INLINE constexpr bool is_inf() const {
554    return exp_sig_bits() == encode(Exponent::inf(), Significand::msb());
555  }
556  LIBC_INLINE constexpr bool is_finite() const {
557    return !is_inf() && !is_nan();
558  }
559  LIBC_INLINE
560  constexpr bool is_subnormal() const {
561    return exp_bits() == encode(Exponent::subnormal());
562  }
563  LIBC_INLINE constexpr bool is_normal() const {
564    const auto exp = exp_bits();
565    if (exp == encode(Exponent::subnormal()) || exp == encode(Exponent::inf()))
566      return false;
567    return get_implicit_bit();
568  }
569  LIBC_INLINE constexpr RetT next_toward_inf() const {
570    if (is_finite()) {
571      if (exp_sig_bits() == max_normal().uintval()) {
572        return inf(sign());
573      } else if (exp_sig_bits() == max_subnormal().uintval()) {
574        return min_normal(sign());
575      } else if (sig_bits() == SIG_MASK) {
576        return RetT(encode(sign(), ++biased_exponent(), Significand::zero()));
577      } else {
578        return RetT(bits + StorageType(1));
579      }
580    }
581    return RetT(bits);
582  }
583
584  LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
585    return sig_bits();
586  }
587
588  // This functions is specific to FPRepSem<FPType::X86_Binary80>.
589  // TODO: Remove if possible.
590  LIBC_INLINE constexpr bool get_implicit_bit() const {
591    return static_cast<bool>(bits & EXPLICIT_BIT_MASK);
592  }
593
594  // This functions is specific to FPRepSem<FPType::X86_Binary80>.
595  // TODO: Remove if possible.
596  LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
597    if (get_implicit_bit() != implicitVal)
598      bits ^= EXPLICIT_BIT_MASK;
599  }
600};
601
602// 'FPRepImpl' is the bottom of the class hierarchy that only deals with
603// 'FPType'. The operations dealing with specific float semantics are
604// implemented by 'FPRepSem' above and specialized when needed.
605//
606// The 'RetT' type is being propagated up to 'FPRepSem' so that the functions
607// creating new values (Builders) can return the appropriate type. That is, when
608// creating a value through 'FPBits' below the builder will return an 'FPBits'
609// value.
610// FPBits<float>::zero(); // returns an FPBits<>
611//
612// When we don't care about specific C++ floating point type we can use
613// 'FPRep' and specify the 'FPType' directly.
614// FPRep<FPType::IEEE754_Binary32:>::zero() // returns an FPRep<>
615template <FPType fp_type, typename RetT>
616struct FPRepImpl : public FPRepSem<fp_type, RetT> {
617  using UP = FPRepSem<fp_type, RetT>;
618  using StorageType = typename UP::StorageType;
619
620protected:
621  using UP::bits;
622  using UP::encode;
623  using UP::exp_bits;
624  using UP::exp_sig_bits;
625
626  using typename UP::BiasedExponent;
627  using typename UP::Exponent;
628  using typename UP::Significand;
629
630  using UP::FP_MASK;
631
632public:
633  // Constants.
634  using UP::EXP_BIAS;
635  using UP::EXP_MASK;
636  using UP::FRACTION_MASK;
637  using UP::SIG_LEN;
638  using UP::SIG_MASK;
639  using UP::SIGN_MASK;
640  LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
641      (1 << UP::EXP_LEN) - 1;
642
643  // CTors
644  LIBC_INLINE constexpr FPRepImpl() = default;
645  LIBC_INLINE constexpr explicit FPRepImpl(StorageType x) : UP(x) {}
646
647  // Comparison
648  LIBC_INLINE constexpr friend bool operator==(FPRepImpl a, FPRepImpl b) {
649    return a.uintval() == b.uintval();
650  }
651  LIBC_INLINE constexpr friend bool operator!=(FPRepImpl a, FPRepImpl b) {
652    return a.uintval() != b.uintval();
653  }
654
655  // Representation
656  LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
657  LIBC_INLINE constexpr void set_uintval(StorageType value) {
658    bits = (value & FP_MASK);
659  }
660
661  // Builders
662  using UP::inf;
663  using UP::max_normal;
664  using UP::max_subnormal;
665  using UP::min_normal;
666  using UP::min_subnormal;
667  using UP::one;
668  using UP::quiet_nan;
669  using UP::signaling_nan;
670  using UP::zero;
671
672  // Modifiers
673  LIBC_INLINE constexpr RetT abs() const {
674    return RetT(static_cast<StorageType>(bits & UP::EXP_SIG_MASK));
675  }
676
677  // Observers
678  using UP::get_explicit_mantissa;
679  using UP::is_finite;
680  using UP::is_inf;
681  using UP::is_nan;
682  using UP::is_normal;
683  using UP::is_quiet_nan;
684  using UP::is_signaling_nan;
685  using UP::is_subnormal;
686  using UP::is_zero;
687  using UP::next_toward_inf;
688  using UP::sign;
689  LIBC_INLINE constexpr bool is_inf_or_nan() const { return !is_finite(); }
690  LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }
691  LIBC_INLINE constexpr bool is_pos() const { return sign().is_pos(); }
692
693  LIBC_INLINE constexpr uint16_t get_biased_exponent() const {
694    return static_cast<uint16_t>(static_cast<uint32_t>(UP::biased_exponent()));
695  }
696
697  LIBC_INLINE constexpr void set_biased_exponent(StorageType biased) {
698    UP::set_biased_exponent(BiasedExponent(static_cast<uint32_t>(biased)));
699  }
700
701  LIBC_INLINE constexpr int get_exponent() const {
702    return static_cast<int32_t>(Exponent(UP::biased_exponent()));
703  }
704
705  // If the number is subnormal, the exponent is treated as if it were the
706  // minimum exponent for a normal number. This is to keep continuity between
707  // the normal and subnormal ranges, but it causes problems for functions where
708  // values are calculated from the exponent, since just subtracting the bias
709  // will give a slightly incorrect result. Additionally, zero has an exponent
710  // of zero, and that should actually be treated as zero.
711  LIBC_INLINE constexpr int get_explicit_exponent() const {
712    Exponent exponent(UP::biased_exponent());
713    if (is_zero())
714      exponent = Exponent::zero();
715    if (exponent == Exponent::subnormal())
716      exponent = Exponent::min();
717    return static_cast<int32_t>(exponent);
718  }
719
720  LIBC_INLINE constexpr StorageType get_mantissa() const {
721    return bits & FRACTION_MASK;
722  }
723
724  LIBC_INLINE constexpr void set_mantissa(StorageType mantVal) {
725    bits = UP::merge(bits, mantVal, FRACTION_MASK);
726  }
727
728  LIBC_INLINE constexpr void set_significand(StorageType sigVal) {
729    bits = UP::merge(bits, sigVal, SIG_MASK);
730  }
731  // Unsafe function to create a floating point representation.
732  // It simply packs the sign, biased exponent and mantissa values without
733  // checking bound nor normalization.
734  //
735  // WARNING: For X86 Extended Precision, implicit bit needs to be set correctly
736  // in the 'mantissa' by the caller.  This function will not check for its
737  // validity.
738  //
739  // FIXME: Use an uint32_t for 'biased_exp'.
740  LIBC_INLINE static constexpr RetT
741  create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
742    return RetT(encode(sign, BiasedExponent(static_cast<uint32_t>(biased_exp)),
743                       Significand(mantissa)));
744  }
745
746  // The function converts integer number and unbiased exponent to proper
747  // float T type:
748  //   Result = number * 2^(ep+1 - exponent_bias)
749  // Be careful!
750  //   1) "ep" is the raw exponent value.
751  //   2) The function adds +1 to ep for seamless normalized to denormalized
752  //      transition.
753  //   3) The function does not check exponent high limit.
754  //   4) "number" zero value is not processed correctly.
755  //   5) Number is unsigned, so the result can be only positive.
756  LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) {
757    FPRepImpl result(0);
758    int lz =
759        UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number));
760
761    number <<= lz;
762    ep -= lz;
763
764    if (LIBC_LIKELY(ep >= 0)) {
765      // Implicit number bit will be removed by mask
766      result.set_significand(number);
767      result.set_biased_exponent(static_cast<StorageType>(ep + 1));
768    } else {
769      result.set_significand(number >> static_cast<unsigned>(-ep));
770    }
771    return RetT(result.uintval());
772  }
773};
774
775// A generic class to manipulate floating point formats.
776// It derives its functionality to FPRepImpl above.
777template <FPType fp_type>
778struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> {
779  using UP = FPRepImpl<fp_type, FPRep<fp_type>>;
780  using StorageType = typename UP::StorageType;
781  using UP::UP;
782
783  LIBC_INLINE constexpr explicit operator StorageType() const {
784    return UP::uintval();
785  }
786};
787
788} // namespace internal
789
790// Returns the FPType corresponding to C++ type T on the host.
791template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
792  using UnqualT = cpp::remove_cv_t<T>;
793  if constexpr (cpp::is_same_v<UnqualT, float> && __FLT_MANT_DIG__ == 24)
794    return FPType::IEEE754_Binary32;
795  else if constexpr (cpp::is_same_v<UnqualT, double> && __DBL_MANT_DIG__ == 53)
796    return FPType::IEEE754_Binary64;
797  else if constexpr (cpp::is_same_v<UnqualT, long double>) {
798    if constexpr (__LDBL_MANT_DIG__ == 53)
799      return FPType::IEEE754_Binary64;
800    else if constexpr (__LDBL_MANT_DIG__ == 64)
801      return FPType::X86_Binary80;
802    else if constexpr (__LDBL_MANT_DIG__ == 113)
803      return FPType::IEEE754_Binary128;
804  }
805#if defined(LIBC_TYPES_HAS_FLOAT16)
806  else if constexpr (cpp::is_same_v<UnqualT, float16>)
807    return FPType::IEEE754_Binary16;
808#endif
809#if defined(LIBC_TYPES_HAS_FLOAT128)
810  else if constexpr (cpp::is_same_v<UnqualT, float128>)
811    return FPType::IEEE754_Binary128;
812#endif
813  else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
814    return FPType::BFloat16;
815  else
816    static_assert(cpp::always_false<UnqualT>, "Unsupported type");
817}
818
819// -----------------------------------------------------------------------------
820//                               **** WARNING ****
821// This interface is shared with libc++, if you change this interface you need
822// to update it in both libc and libc++. You should also be careful when adding
823// dependencies to this file, since it needs to build for all libc++ targets.
824// -----------------------------------------------------------------------------
825// A generic class to manipulate C++ floating point formats.
826// It derives its functionality to FPRepImpl above.
827template <typename T>
828struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> {
829  static_assert(cpp::is_floating_point_v<T>,
830                "FPBits instantiated with invalid type.");
831  using UP = internal::FPRepImpl<get_fp_type<T>(), FPBits<T>>;
832  using StorageType = typename UP::StorageType;
833
834  // Constructors.
835  LIBC_INLINE constexpr FPBits() = default;
836
837  template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
838    using Unqual = typename cpp::remove_cv_t<XType>;
839    if constexpr (cpp::is_same_v<Unqual, T>) {
840      UP::bits = cpp::bit_cast<StorageType>(x);
841    } else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
842      UP::bits = x;
843    } else {
844      // We don't want accidental type promotions/conversions, so we require
845      // exact type match.
846      static_assert(cpp::always_false<XType>);
847    }
848  }
849
850  // Floating-point conversions.
851  LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); }
852};
853
854} // namespace fputil
855} // namespace LIBC_NAMESPACE_DECL
856
857#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H