aboutsummaryrefslogtreecommitdiff
path: root/lib/libcxx/libc/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-04-05 01:46:13 -0400
committerGitHub <noreply@github.com>2025-04-05 01:46:13 -0400
commit0cd31fc7ff157551cfbba5da35cd79f118d2a2e3 (patch)
treea308488f5d85184c8ec402fb3f55f1cf2704443e /lib/libcxx/libc/src
parent8acedfd5baabab705946ad097746f9183ef62420 (diff)
parentcefe65c1b8abe65a22d4b68410db1be264fdeda0 (diff)
downloadzig-0cd31fc7ff157551cfbba5da35cd79f118d2a2e3.tar.gz
zig-0cd31fc7ff157551cfbba5da35cd79f118d2a2e3.zip
Merge pull request #22780 from ziglang/llvm20
LLVM 20
Diffstat (limited to 'lib/libcxx/libc/src')
-rw-r--r--lib/libcxx/libc/src/__support/CPP/array.h80
-rw-r--r--lib/libcxx/libc/src/__support/CPP/bit.h298
-rw-r--r--lib/libcxx/libc/src/__support/CPP/iterator.h99
-rw-r--r--lib/libcxx/libc/src/__support/CPP/limits.h92
-rw-r--r--lib/libcxx/libc/src/__support/CPP/optional.h139
-rw-r--r--lib/libcxx/libc/src/__support/CPP/string_view.h220
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits.h70
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/add_lvalue_reference.h33
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/add_pointer.h30
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/add_rvalue_reference.h32
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/aligned_storage.h30
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/always_false.h32
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/bool_constant.h23
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/conditional.h28
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/decay.h40
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/enable_if.h26
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/false_type.h23
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/has_unique_object_representations.h30
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/integral_constant.h26
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/invoke.h67
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/invoke_result.h29
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_arithmetic.h30
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_array.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_base_of.h47
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_class.h32
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h53
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_const.h28
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h24
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_convertible.h48
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h32
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h68
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_enum.h26
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_fixed_point.h49
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_floating_point.h48
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_function.h35
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h43
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_lvalue_reference.h35
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_member_pointer.h33
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h33
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_null_pointer.h29
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_object.h33
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_pointer.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_reference.h34
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_rvalue_reference.h35
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_same.h28
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_scalar.h35
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_signed.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_constructible.h25
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_copyable.h29
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_destructible.h37
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_union.h26
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h31
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/is_void.h27
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/make_signed.h41
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/make_unsigned.h46
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/remove_all_extents.h41
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/remove_cv.h28
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/remove_cvref.h27
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/remove_extent.h28
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/remove_reference.h27
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/true_type.h23
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/type_identity.h24
-rw-r--r--lib/libcxx/libc/src/__support/CPP/type_traits/void_t.h29
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility.h18
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility/declval.h27
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility/forward.h35
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility/in_place.h39
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h40
-rw-r--r--lib/libcxx/libc/src/__support/CPP/utility/move.h27
-rw-r--r--lib/libcxx/libc/src/__support/FPUtil/FPBits.h846
-rw-r--r--lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h81
-rw-r--r--lib/libcxx/libc/src/__support/big_int.h1384
-rw-r--r--lib/libcxx/libc/src/__support/common.h82
-rw-r--r--lib/libcxx/libc/src/__support/ctype_utils.h584
-rw-r--r--lib/libcxx/libc/src/__support/detailed_powers_of_ten.h740
-rw-r--r--lib/libcxx/libc/src/__support/high_precision_decimal.h442
-rw-r--r--lib/libcxx/libc/src/__support/libc_assert.h88
-rw-r--r--lib/libcxx/libc/src/__support/macros/attributes.h51
-rw-r--r--lib/libcxx/libc/src/__support/macros/config.h46
-rw-r--r--lib/libcxx/libc/src/__support/macros/null_check.h28
-rw-r--r--lib/libcxx/libc/src/__support/macros/optimization.h61
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/architectures.h64
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/compiler.h43
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/complex_types.h30
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/cpu_features.h60
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/os.h32
-rw-r--r--lib/libcxx/libc/src/__support/macros/properties/types.h61
-rw-r--r--lib/libcxx/libc/src/__support/macros/sanitizer.h59
-rw-r--r--lib/libcxx/libc/src/__support/math_extras.h161
-rw-r--r--lib/libcxx/libc/src/__support/number_pair.h26
-rw-r--r--lib/libcxx/libc/src/__support/sign.h43
-rw-r--r--lib/libcxx/libc/src/__support/str_to_float.h1275
-rw-r--r--lib/libcxx/libc/src/__support/str_to_integer.h169
-rw-r--r--lib/libcxx/libc/src/__support/str_to_num_result.h48
-rw-r--r--lib/libcxx/libc/src/__support/uint128.h23
-rw-r--r--lib/libcxx/libc/src/errno/libc_errno.h47
98 files changed, 9709 insertions, 0 deletions
diff --git a/lib/libcxx/libc/src/__support/CPP/array.h b/lib/libcxx/libc/src/__support/CPP/array.h
new file mode 100644
index 0000000000..db0a986b71
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/array.h
@@ -0,0 +1,80 @@
+//===-- A self contained equivalent of std::array ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H
+
+#include "src/__support/CPP/iterator.h" // reverse_iterator
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include <stddef.h> // For size_t.
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <class T, size_t N> struct array {
+ static_assert(N != 0,
+ "Cannot create a LIBC_NAMESPACE::cpp::array of size 0.");
+
+ T Data[N];
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
+ using reverse_iterator = cpp::reverse_iterator<iterator>;
+ using const_reverse_iterator = cpp::reverse_iterator<const_iterator>;
+
+ LIBC_INLINE constexpr T *data() { return Data; }
+ LIBC_INLINE constexpr const T *data() const { return Data; }
+
+ LIBC_INLINE constexpr T &front() { return Data[0]; }
+ LIBC_INLINE constexpr const T &front() const { return Data[0]; }
+
+ LIBC_INLINE constexpr T &back() { return Data[N - 1]; }
+ LIBC_INLINE constexpr const T &back() const { return Data[N - 1]; }
+
+ LIBC_INLINE constexpr T &operator[](size_t Index) { return Data[Index]; }
+
+ LIBC_INLINE constexpr const T &operator[](size_t Index) const {
+ return Data[Index];
+ }
+
+ LIBC_INLINE constexpr size_t size() const { return N; }
+
+ LIBC_INLINE constexpr bool empty() const { return N == 0; }
+
+ LIBC_INLINE constexpr iterator begin() { return Data; }
+ LIBC_INLINE constexpr const_iterator begin() const { return Data; }
+ LIBC_INLINE constexpr const_iterator cbegin() const { return begin(); }
+
+ LIBC_INLINE constexpr iterator end() { return Data + N; }
+ LIBC_INLINE constexpr const_iterator end() const { return Data + N; }
+ LIBC_INLINE constexpr const_iterator cend() const { return end(); }
+
+ LIBC_INLINE constexpr reverse_iterator rbegin() {
+ return reverse_iterator{end()};
+ }
+ LIBC_INLINE constexpr const_reverse_iterator rbegin() const {
+ return const_reverse_iterator{end()};
+ }
+ LIBC_INLINE constexpr const_reverse_iterator crbegin() const {
+ return rbegin();
+ }
+
+ LIBC_INLINE constexpr reverse_iterator rend() {
+ return reverse_iterator{begin()};
+ }
+ LIBC_INLINE constexpr const_reverse_iterator rend() const {
+ return const_reverse_iterator{begin()};
+ }
+ LIBC_INLINE constexpr const_reverse_iterator crend() const { return rend(); }
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H
diff --git a/lib/libcxx/libc/src/__support/CPP/bit.h b/lib/libcxx/libc/src/__support/CPP/bit.h
new file mode 100644
index 0000000000..adcd047274
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/bit.h
@@ -0,0 +1,298 @@
+//===-- Implementation of the C++20 bit header -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This is inspired by LLVM ADT/bit.h header.
+// Some functions are missing, we can add them as needed (popcount, byteswap).
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
+
+#include "src/__support/CPP/limits.h" // numeric_limits
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/sanitizer.h"
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+#if __has_builtin(__builtin_memcpy_inline)
+#define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
+#endif
+
+// This implementation of bit_cast requires trivially-constructible To, to avoid
+// UB in the implementation.
+template <typename To, typename From>
+LIBC_INLINE constexpr cpp::enable_if_t<
+ (sizeof(To) == sizeof(From)) &&
+ cpp::is_trivially_constructible<To>::value &&
+ cpp::is_trivially_copyable<To>::value &&
+ cpp::is_trivially_copyable<From>::value,
+ To>
+bit_cast(const From &from) {
+ MSAN_UNPOISON(&from, sizeof(From));
+#if __has_builtin(__builtin_bit_cast)
+ return __builtin_bit_cast(To, from);
+#else
+ To to;
+ char *dst = reinterpret_cast<char *>(&to);
+ const char *src = reinterpret_cast<const char *>(&from);
+#if __has_builtin(__builtin_memcpy_inline)
+ __builtin_memcpy_inline(dst, src, sizeof(To));
+#else
+ for (unsigned i = 0; i < sizeof(To); ++i)
+ dst[i] = src[i];
+#endif // __has_builtin(__builtin_memcpy_inline)
+ return to;
+#endif // __has_builtin(__builtin_bit_cast)
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>,
+ bool>
+has_single_bit(T value) {
+ return (value != 0) && ((value & (value - 1)) == 0);
+}
+
+// A temporary macro to add template function specialization when compiler
+// builtin is available.
+#define ADD_SPECIALIZATION(NAME, TYPE, BUILTIN) \
+ template <> [[nodiscard]] LIBC_INLINE constexpr int NAME<TYPE>(TYPE value) { \
+ static_assert(cpp::is_unsigned_v<TYPE>); \
+ return value == 0 ? cpp::numeric_limits<TYPE>::digits : BUILTIN(value); \
+ }
+
+/// Count number of 0's from the least significant bit to the most
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// Returns cpp::numeric_limits<T>::digits on an input of 0.
+// clang-19+, gcc-14+
+#if __has_builtin(__builtin_ctzg)
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countr_zero(T value) {
+ return __builtin_ctzg(value, cpp::numeric_limits<T>::digits);
+}
+#else
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countr_zero(T value) {
+ if (!value)
+ return cpp::numeric_limits<T>::digits;
+ if (value & 0x1)
+ return 0;
+ // Bisection method.
+ unsigned zero_bits = 0;
+ unsigned shift = cpp::numeric_limits<T>::digits >> 1;
+ T mask = cpp::numeric_limits<T>::max() >> shift;
+ while (shift) {
+ if ((value & mask) == 0) {
+ value >>= shift;
+ zero_bits |= shift;
+ }
+ shift >>= 1;
+ mask >>= shift;
+ }
+ return zero_bits;
+}
+#if __has_builtin(__builtin_ctzs)
+ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)
+#endif
+ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz)
+ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl)
+ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll)
+#endif // __has_builtin(__builtin_ctzg)
+
+/// Count number of 0's from the most significant bit to the least
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// Returns cpp::numeric_limits<T>::digits on an input of 0.
+// clang-19+, gcc-14+
+#if __has_builtin(__builtin_clzg)
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countl_zero(T value) {
+ return __builtin_clzg(value, cpp::numeric_limits<T>::digits);
+}
+#else
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countl_zero(T value) {
+ if (!value)
+ return cpp::numeric_limits<T>::digits;
+ // Bisection method.
+ unsigned zero_bits = 0;
+ for (unsigned shift = cpp::numeric_limits<T>::digits >> 1; shift;
+ shift >>= 1) {
+ T tmp = value >> shift;
+ if (tmp)
+ value = tmp;
+ else
+ zero_bits |= shift;
+ }
+ return zero_bits;
+}
+#if __has_builtin(__builtin_clzs)
+ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)
+#endif
+ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz)
+ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl)
+ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
+#endif // __has_builtin(__builtin_clzg)
+
+#undef ADD_SPECIALIZATION
+
+/// Count the number of ones from the most significant bit to the first
+/// zero bit.
+///
+/// Ex. countl_one(0xFF0FFF00) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// Returns cpp::numeric_limits<T>::digits on an input of all ones.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countl_one(T value) {
+ return cpp::countl_zero<T>(~value);
+}
+
+/// Count the number of ones from the least significant bit to the first
+/// zero bit.
+///
+/// Ex. countr_one(0x00FF00FF) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// Returns cpp::numeric_limits<T>::digits on an input of all ones.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+countr_one(T value) {
+ return cpp::countr_zero<T>(~value);
+}
+
+/// Returns the number of bits needed to represent value if value is nonzero.
+/// Returns 0 otherwise.
+///
+/// Ex. bit_width(5) == 3.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+bit_width(T value) {
+ return cpp::numeric_limits<T>::digits - cpp::countl_zero(value);
+}
+
+/// Returns the largest integral power of two no greater than value if value is
+/// nonzero. Returns 0 otherwise.
+///
+/// Ex. bit_floor(5) == 4.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+bit_floor(T value) {
+ if (!value)
+ return 0;
+ return static_cast<T>(T(1) << (cpp::bit_width(value) - 1));
+}
+
+/// Returns the smallest integral power of two no smaller than value if value is
+/// nonzero. Returns 1 otherwise.
+///
+/// Ex. bit_ceil(5) == 8.
+///
+/// The return value is undefined if the input is larger than the largest power
+/// of two representable in T.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+bit_ceil(T value) {
+ if (value < 2)
+ return 1;
+ return static_cast<T>(T(1) << cpp::bit_width(value - 1U));
+}
+
+// Rotate algorithms make use of "Safe, Efficient, and Portable Rotate in C/C++"
+// from https://blog.regehr.org/archives/1063.
+
+// Forward-declare rotr so that rotl can use it.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+rotr(T value, int rotate);
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+rotl(T value, int rotate) {
+ constexpr unsigned N = cpp::numeric_limits<T>::digits;
+ rotate = rotate % N;
+ if (!rotate)
+ return value;
+ if (rotate < 0)
+ return cpp::rotr<T>(value, -rotate);
+ return (value << rotate) | (value >> (N - rotate));
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+rotr(T value, int rotate) {
+ constexpr unsigned N = cpp::numeric_limits<T>::digits;
+ rotate = rotate % N;
+ if (!rotate)
+ return value;
+ if (rotate < 0)
+ return cpp::rotl<T>(value, -rotate);
+ return (value >> rotate) | (value << (N - rotate));
+}
+
+// TODO: Do we need this function at all? How is it different from
+// 'static_cast'?
+template <class To, class From>
+LIBC_INLINE constexpr To bit_or_static_cast(const From &from) {
+ if constexpr (sizeof(To) == sizeof(From)) {
+ return bit_cast<To>(from);
+ } else {
+ return static_cast<To>(from);
+ }
+}
+
+/// Count number of 1's aka population count or Hamming weight.
+///
+/// Only unsigned integral types are allowed.
+// clang-19+, gcc-14+
+#if __has_builtin(__builtin_popcountg)
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+popcount(T value) {
+ return __builtin_popcountg(value);
+}
+#else // !__has_builtin(__builtin_popcountg)
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+popcount(T value) {
+ int count = 0;
+ while (value) {
+ value &= value - 1;
+ ++count;
+ }
+ return count;
+}
+#define ADD_SPECIALIZATION(TYPE, BUILTIN) \
+ template <> \
+ [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \
+ return BUILTIN(value); \
+ }
+ADD_SPECIALIZATION(unsigned char, __builtin_popcount)
+ADD_SPECIALIZATION(unsigned short, __builtin_popcount)
+ADD_SPECIALIZATION(unsigned, __builtin_popcount)
+ADD_SPECIALIZATION(unsigned long, __builtin_popcountl)
+ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
+#endif // __builtin_popcountg
+#undef ADD_SPECIALIZATION
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/iterator.h b/lib/libcxx/libc/src/__support/CPP/iterator.h
new file mode 100644
index 0000000000..168a269731
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/iterator.h
@@ -0,0 +1,99 @@
+//===-- Standalone implementation of iterator -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
+
+#include "src/__support/CPP/type_traits/enable_if.h"
+#include "src/__support/CPP/type_traits/is_convertible.h"
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <typename T> struct iterator_traits;
+template <typename T> struct iterator_traits<T *> {
+ using reference = T &;
+ using value_type = T;
+};
+
+template <typename Iter> class reverse_iterator {
+ Iter current;
+
+public:
+ using reference = typename iterator_traits<Iter>::reference;
+ using value_type = typename iterator_traits<Iter>::value_type;
+ using iterator_type = Iter;
+
+ LIBC_INLINE reverse_iterator() : current() {}
+ LIBC_INLINE constexpr explicit reverse_iterator(Iter it) : current(it) {}
+
+ template <typename Other,
+ cpp::enable_if_t<!cpp::is_same_v<Iter, Other> &&
+ cpp::is_convertible_v<const Other &, Iter>,
+ int> = 0>
+ LIBC_INLINE constexpr explicit reverse_iterator(const Other &it)
+ : current(it) {}
+
+ LIBC_INLINE friend constexpr bool operator==(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() == rhs.base();
+ }
+
+ LIBC_INLINE friend constexpr bool operator!=(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() != rhs.base();
+ }
+
+ LIBC_INLINE friend constexpr bool operator<(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() > rhs.base();
+ }
+
+ LIBC_INLINE friend constexpr bool operator<=(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() >= rhs.base();
+ }
+
+ LIBC_INLINE friend constexpr bool operator>(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() < rhs.base();
+ }
+
+ LIBC_INLINE friend constexpr bool operator>=(const reverse_iterator &lhs,
+ const reverse_iterator &rhs) {
+ return lhs.base() <= rhs.base();
+ }
+
+ LIBC_INLINE constexpr iterator_type base() const { return current; }
+
+ LIBC_INLINE constexpr reference operator*() const {
+ Iter tmp = current;
+ return *--tmp;
+ }
+ LIBC_INLINE constexpr reverse_iterator operator--() {
+ ++current;
+ return *this;
+ }
+ LIBC_INLINE constexpr reverse_iterator &operator++() {
+ --current;
+ return *this;
+ }
+ LIBC_INLINE constexpr reverse_iterator operator++(int) {
+ reverse_iterator tmp(*this);
+ --current;
+ return tmp;
+ }
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
diff --git a/lib/libcxx/libc/src/__support/CPP/limits.h b/lib/libcxx/libc/src/__support/CPP/limits.h
new file mode 100644
index 0000000000..cf4beb9cc8
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/limits.h
@@ -0,0 +1,92 @@
+//===-- A self contained equivalent of std::limits --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
+
+#include "hdr/limits_macros.h" // CHAR_BIT
+#include "src/__support/CPP/type_traits/is_integral.h"
+#include "src/__support/CPP/type_traits/is_signed.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+namespace internal {
+
+template <typename T, T min_value, T max_value> struct integer_impl {
+ static_assert(cpp::is_integral_v<T>);
+ LIBC_INLINE static constexpr T max() { return max_value; }
+ LIBC_INLINE static constexpr T min() { return min_value; }
+ LIBC_INLINE_VAR static constexpr int digits =
+ CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>;
+};
+
+} // namespace internal
+
+template <class T> struct numeric_limits {};
+
+// TODO: Add numeric_limits specializations as needed for new types.
+template <>
+struct numeric_limits<short>
+ : public internal::integer_impl<short, SHRT_MIN, SHRT_MAX> {};
+
+template <>
+struct numeric_limits<unsigned short>
+ : public internal::integer_impl<unsigned short, 0, USHRT_MAX> {};
+
+template <>
+struct numeric_limits<int>
+ : public internal::integer_impl<int, INT_MIN, INT_MAX> {};
+
+template <>
+struct numeric_limits<unsigned int>
+ : public internal::integer_impl<unsigned int, 0, UINT_MAX> {};
+
+template <>
+struct numeric_limits<long>
+ : public internal::integer_impl<long, LONG_MIN, LONG_MAX> {};
+
+template <>
+struct numeric_limits<unsigned long>
+ : public internal::integer_impl<unsigned long, 0, ULONG_MAX> {};
+
+template <>
+struct numeric_limits<long long>
+ : public internal::integer_impl<long long, LLONG_MIN, LLONG_MAX> {};
+
+template <>
+struct numeric_limits<unsigned long long>
+ : public internal::integer_impl<unsigned long long, 0, ULLONG_MAX> {};
+
+template <>
+struct numeric_limits<char>
+ : public internal::integer_impl<char, CHAR_MIN, CHAR_MAX> {};
+
+template <>
+struct numeric_limits<signed char>
+ : public internal::integer_impl<signed char, SCHAR_MIN, SCHAR_MAX> {};
+
+template <>
+struct numeric_limits<unsigned char>
+ : public internal::integer_impl<unsigned char, 0, UCHAR_MAX> {};
+
+#ifdef LIBC_TYPES_HAS_INT128
+// On platform where UInt128 resolves to __uint128_t, this specialization
+// provides the limits of UInt128.
+template <>
+struct numeric_limits<__uint128_t>
+ : public internal::integer_impl<__uint128_t, 0, ~__uint128_t(0)> {};
+#endif
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
diff --git a/lib/libcxx/libc/src/__support/CPP/optional.h b/lib/libcxx/libc/src/__support/CPP/optional.h
new file mode 100644
index 0000000000..aed2269db1
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/optional.h
@@ -0,0 +1,139 @@
+//===-- Standalone implementation of std::optional --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H
+
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/CPP/utility.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// Trivial nullopt_t struct.
+struct nullopt_t {
+ LIBC_INLINE constexpr explicit nullopt_t() = default;
+};
+
+// nullopt that can be used and returned.
+LIBC_INLINE_VAR constexpr nullopt_t nullopt{};
+
+// This is very simple implementation of the std::optional class. It makes
+// several assumptions that the underlying type is trivially constructible,
+// copyable, or movable.
+template <typename T> class optional {
+ template <typename U, bool = !is_trivially_destructible<U>::value>
+ struct OptionalStorage {
+ union {
+ char empty;
+ U stored_value;
+ };
+
+ bool in_use = false;
+
+ LIBC_INLINE ~OptionalStorage() { reset(); }
+
+ LIBC_INLINE constexpr OptionalStorage() : empty() {}
+
+ template <typename... Args>
+ LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)
+ : stored_value(forward<Args>(args)...) {}
+
+ LIBC_INLINE constexpr void reset() {
+ if (in_use)
+ stored_value.~U();
+ in_use = false;
+ }
+ };
+
+ // The only difference is that this type U doesn't have a nontrivial
+ // destructor.
+ template <typename U> struct OptionalStorage<U, false> {
+ union {
+ char empty;
+ U stored_value;
+ };
+
+ bool in_use = false;
+
+ LIBC_INLINE constexpr OptionalStorage() : empty() {}
+
+ template <typename... Args>
+ LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args)
+ : stored_value(forward<Args>(args)...) {}
+
+ LIBC_INLINE constexpr void reset() { in_use = false; }
+ };
+
+ OptionalStorage<T> storage;
+
+public:
+ LIBC_INLINE constexpr optional() = default;
+ LIBC_INLINE constexpr optional(nullopt_t) {}
+
+ LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) {
+ storage.in_use = true;
+ }
+ LIBC_INLINE constexpr optional(const optional &) = default;
+
+ LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) {
+ storage.in_use = true;
+ }
+ LIBC_INLINE constexpr optional(optional &&O) = default;
+
+ template <typename... ArgTypes>
+ LIBC_INLINE constexpr optional(in_place_t, ArgTypes &&...Args)
+ : storage(in_place, forward<ArgTypes>(Args)...) {
+ storage.in_use = true;
+ }
+
+ LIBC_INLINE constexpr optional &operator=(T &&t) {
+ storage = move(t);
+ return *this;
+ }
+ LIBC_INLINE constexpr optional &operator=(optional &&) = default;
+
+ LIBC_INLINE constexpr optional &operator=(const T &t) {
+ storage = t;
+ return *this;
+ }
+ LIBC_INLINE constexpr optional &operator=(const optional &) = default;
+
+ LIBC_INLINE constexpr void reset() { storage.reset(); }
+
+ LIBC_INLINE constexpr const T &value() const & {
+ return storage.stored_value;
+ }
+
+ LIBC_INLINE constexpr T &value() & { return storage.stored_value; }
+
+ LIBC_INLINE constexpr explicit operator bool() const {
+ return storage.in_use;
+ }
+ LIBC_INLINE constexpr bool has_value() const { return storage.in_use; }
+ LIBC_INLINE constexpr const T *operator->() const {
+ return &storage.stored_value;
+ }
+ LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; }
+ LIBC_INLINE constexpr const T &operator*() const & {
+ return storage.stored_value;
+ }
+ LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; }
+
+ LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); }
+ LIBC_INLINE constexpr T &&operator*() && {
+ return move(storage.stored_value);
+ }
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_OPTIONAL_H
diff --git a/lib/libcxx/libc/src/__support/CPP/string_view.h b/lib/libcxx/libc/src/__support/CPP/string_view.h
new file mode 100644
index 0000000000..745c62c35f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/string_view.h
@@ -0,0 +1,220 @@
+//===-- Standalone implementation std::string_view --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// This is very simple alternate of the std::string_view class. There is no
+// bounds check performed in any of the methods. The callers are expected to
+// do the checks before invoking the methods.
+//
+// This class will be extended as needed in future.
+class string_view {
+private:
+ const char *Data;
+ size_t Len;
+
+ LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; }
+
+ LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,
+ size_t Length) {
+ for (size_t i = 0; i < Length; ++i)
+ if (int Diff = (int)Lhs[i] - (int)Rhs[i])
+ return Diff;
+ return 0;
+ }
+
+ LIBC_INLINE static constexpr size_t length(const char *Str) {
+ for (const char *End = Str;; ++End)
+ if (*End == '\0')
+ return End - Str;
+ }
+
+ LIBC_INLINE bool equals(string_view Other) const {
+ return (Len == Other.Len &&
+ compareMemory(Data, Other.Data, Other.Len) == 0);
+ }
+
+public:
+ using value_type = char;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using pointer = char *;
+ using const_pointer = const char *;
+ using reference = char &;
+ using const_reference = const char &;
+ using const_iterator = char *;
+ using iterator = const_iterator;
+
+ // special value equal to the maximum value representable by the type
+ // size_type.
+ LIBC_INLINE_VAR static constexpr size_t npos = -1;
+
+ LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
+
+ // Assumes Str is a null-terminated string. The length of the string does
+ // not include the terminating null character.
+ // Preconditions: [Str, Str + ​length(Str)) is a valid range.
+ LIBC_INLINE constexpr string_view(const char *Str)
+ : Data(Str), Len(length(Str)) {}
+
+ // Preconditions: [Str, Str + N) is a valid range.
+ LIBC_INLINE constexpr string_view(const char *Str, size_t N)
+ : Data(Str), Len(N) {}
+
+ LIBC_INLINE constexpr const char *data() const { return Data; }
+
+ // Returns the size of the string_view.
+ LIBC_INLINE constexpr size_t size() const { return Len; }
+
+ // Returns whether the string_view is empty.
+ LIBC_INLINE constexpr bool empty() const { return Len == 0; }
+
+ // Returns an iterator to the first character of the view.
+ LIBC_INLINE const char *begin() const { return Data; }
+
+ // Returns an iterator to the character following the last character of the
+ // view.
+ LIBC_INLINE const char *end() const { return Data + Len; }
+
+ // Returns a const reference to the character at specified location pos.
+ // No bounds checking is performed: the behavior is undefined if pos >=
+ // size().
+ LIBC_INLINE constexpr const char &operator[](size_t Index) const {
+ return Data[Index];
+ }
+
+ /// compare - Compare two strings; the result is -1, 0, or 1 if this string
+ /// is lexicographically less than, equal to, or greater than the \p Other.
+ LIBC_INLINE int compare(string_view Other) const {
+ // Check the prefix for a mismatch.
+ if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len)))
+ return Res < 0 ? -1 : 1;
+ // Otherwise the prefixes match, so we only need to check the lengths.
+ if (Len == Other.Len)
+ return 0;
+ return Len < Other.Len ? -1 : 1;
+ }
+
+ LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); }
+ LIBC_INLINE bool operator!=(string_view Other) const {
+ return !(*this == Other);
+ }
+ LIBC_INLINE bool operator<(string_view Other) const {
+ return compare(Other) == -1;
+ }
+ LIBC_INLINE bool operator<=(string_view Other) const {
+ return compare(Other) != 1;
+ }
+ LIBC_INLINE bool operator>(string_view Other) const {
+ return compare(Other) == 1;
+ }
+ LIBC_INLINE bool operator>=(string_view Other) const {
+ return compare(Other) != -1;
+ }
+
+ // Moves the start of the view forward by n characters.
+ // The behavior is undefined if n > size().
+ LIBC_INLINE void remove_prefix(size_t N) {
+ Len -= N;
+ Data += N;
+ }
+
+ // Moves the end of the view back by n characters.
+ // The behavior is undefined if n > size().
+ LIBC_INLINE void remove_suffix(size_t N) { Len -= N; }
+
+ // Check if this string starts with the given Prefix.
+ LIBC_INLINE bool starts_with(string_view Prefix) const {
+ return Len >= Prefix.Len &&
+ compareMemory(Data, Prefix.Data, Prefix.Len) == 0;
+ }
+
+ // Check if this string starts with the given Prefix.
+ LIBC_INLINE bool starts_with(const char Prefix) const {
+ return !empty() && front() == Prefix;
+ }
+
+ // Check if this string ends with the given Prefix.
+ LIBC_INLINE bool ends_with(const char Suffix) const {
+ return !empty() && back() == Suffix;
+ }
+
+ // Check if this string ends with the given Suffix.
+ LIBC_INLINE bool ends_with(string_view Suffix) const {
+ return Len >= Suffix.Len &&
+ compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;
+ }
+
+ // Return a reference to the substring from [Start, Start + N).
+ //
+ // Start The index of the starting character in the substring; if the index is
+ // npos or greater than the length of the string then the empty substring will
+ // be returned.
+ //
+ // N The number of characters to included in the substring. If N exceeds the
+ // number of characters remaining in the string, the string suffix (starting
+ // with Start) will be returned.
+ LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const {
+ Start = min(Start, Len);
+ return string_view(Data + Start, min(N, Len - Start));
+ }
+
+ // front - Get the first character in the string.
+ LIBC_INLINE char front() const { return Data[0]; }
+
+ // back - Get the last character in the string.
+ LIBC_INLINE char back() const { return Data[Len - 1]; }
+
+ // Finds the first occurence of c in this view, starting at position From.
+ LIBC_INLINE constexpr size_t find_first_of(const char c,
+ size_t From = 0) const {
+ for (size_t Pos = From; Pos < size(); ++Pos)
+ if ((*this)[Pos] == c)
+ return Pos;
+ return npos;
+ }
+
+ // Finds the last occurence of c in this view, ending at position End.
+ LIBC_INLINE constexpr size_t find_last_of(const char c,
+ size_t End = npos) const {
+ End = End >= size() ? size() : End + 1;
+ for (; End > 0; --End)
+ if ((*this)[End - 1] == c)
+ return End - 1;
+ return npos;
+ }
+
+ // Finds the first character not equal to c in this view, starting at position
+ // From.
+ LIBC_INLINE constexpr size_t find_first_not_of(const char c,
+ size_t From = 0) const {
+ for (size_t Pos = From; Pos < size(); ++Pos)
+ if ((*this)[Pos] != c)
+ return Pos;
+ return npos;
+ }
+
+ // Check if this view contains the given character.
+ LIBC_INLINE constexpr bool contains(char c) const {
+ return find_first_of(c) != npos;
+ }
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits.h b/lib/libcxx/libc/src/__support/CPP/type_traits.h
new file mode 100644
index 0000000000..d48ee23aea
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits.h
@@ -0,0 +1,70 @@
+//===-- Self contained C++ type_traits --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_H
+
+#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/add_pointer.h"
+#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/aligned_storage.h"
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/conditional.h"
+#include "src/__support/CPP/type_traits/decay.h"
+#include "src/__support/CPP/type_traits/enable_if.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/has_unique_object_representations.h"
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/CPP/type_traits/invoke.h"
+#include "src/__support/CPP/type_traits/invoke_result.h"
+#include "src/__support/CPP/type_traits/is_arithmetic.h"
+#include "src/__support/CPP/type_traits/is_array.h"
+#include "src/__support/CPP/type_traits/is_base_of.h"
+#include "src/__support/CPP/type_traits/is_class.h"
+#include "src/__support/CPP/type_traits/is_complex.h"
+#include "src/__support/CPP/type_traits/is_const.h"
+#include "src/__support/CPP/type_traits/is_constant_evaluated.h"
+#include "src/__support/CPP/type_traits/is_convertible.h"
+#include "src/__support/CPP/type_traits/is_copy_assignable.h"
+#include "src/__support/CPP/type_traits/is_copy_constructible.h"
+#include "src/__support/CPP/type_traits/is_destructible.h"
+#include "src/__support/CPP/type_traits/is_enum.h"
+#include "src/__support/CPP/type_traits/is_fixed_point.h"
+#include "src/__support/CPP/type_traits/is_floating_point.h"
+#include "src/__support/CPP/type_traits/is_function.h"
+#include "src/__support/CPP/type_traits/is_integral.h"
+#include "src/__support/CPP/type_traits/is_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/is_member_pointer.h"
+#include "src/__support/CPP/type_traits/is_move_assignable.h"
+#include "src/__support/CPP/type_traits/is_move_constructible.h"
+#include "src/__support/CPP/type_traits/is_null_pointer.h"
+#include "src/__support/CPP/type_traits/is_object.h"
+#include "src/__support/CPP/type_traits/is_pointer.h"
+#include "src/__support/CPP/type_traits/is_reference.h"
+#include "src/__support/CPP/type_traits/is_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/is_scalar.h"
+#include "src/__support/CPP/type_traits/is_signed.h"
+#include "src/__support/CPP/type_traits/is_trivially_constructible.h"
+#include "src/__support/CPP/type_traits/is_trivially_copyable.h"
+#include "src/__support/CPP/type_traits/is_trivially_destructible.h"
+#include "src/__support/CPP/type_traits/is_union.h"
+#include "src/__support/CPP/type_traits/is_unsigned.h"
+#include "src/__support/CPP/type_traits/is_void.h"
+#include "src/__support/CPP/type_traits/make_signed.h"
+#include "src/__support/CPP/type_traits/make_unsigned.h"
+#include "src/__support/CPP/type_traits/remove_all_extents.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/CPP/type_traits/remove_cvref.h"
+#include "src/__support/CPP/type_traits/remove_extent.h"
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/CPP/type_traits/void_t.h"
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/add_lvalue_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/add_lvalue_reference.h
new file mode 100644
index 0000000000..6f5fc6b0a4
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/add_lvalue_reference.h
@@ -0,0 +1,33 @@
+//===-- add_lvalue_reference type_traits ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_LVALUE_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_LVALUE_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// add_lvalue_reference
+namespace detail {
+template <class T> // Note that `cv void&` is a substitution failure
+auto try_add_lvalue_reference(int) -> cpp::type_identity<T &>;
+template <class T> // Handle T = cv void case
+auto try_add_lvalue_reference(...) -> cpp::type_identity<T>;
+} // namespace detail
+template <class T>
+struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {
+};
+template <class T>
+using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_LVALUE_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/add_pointer.h b/lib/libcxx/libc/src/__support/CPP/type_traits/add_pointer.h
new file mode 100644
index 0000000000..2568a35653
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/add_pointer.h
@@ -0,0 +1,30 @@
+//===-- add_pointer type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_POINTER_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_POINTER_H
+
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// add_pointer
+namespace detail {
+template <class T>
+auto try_add_pointer(int) -> cpp::type_identity<cpp::remove_reference_t<T> *>;
+template <class T> auto try_add_pointer(...) -> cpp::type_identity<T>;
+} // namespace detail
+template <class T>
+struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
+template <class T> using add_pointer_t = typename add_pointer<T>::type;
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_POINTER_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/add_rvalue_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/add_rvalue_reference.h
new file mode 100644
index 0000000000..f51ebf46d7
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/add_rvalue_reference.h
@@ -0,0 +1,32 @@
+//===-- add_rvalue_reference type_traits ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_RVALUE_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_RVALUE_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// add_rvalue_reference
+namespace detail {
+template <class T>
+auto try_add_rvalue_reference(int) -> cpp::type_identity<T &&>;
+template <class T> auto try_add_rvalue_reference(...) -> cpp::type_identity<T>;
+} // namespace detail
+template <class T>
+struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {
+};
+template <class T>
+using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ADD_RVALUE_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/aligned_storage.h b/lib/libcxx/libc/src/__support/CPP/type_traits/aligned_storage.h
new file mode 100644
index 0000000000..69ad4cc847
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/aligned_storage.h
@@ -0,0 +1,30 @@
+//===-- aligned_storage type_traits --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALIGNED_STORAGE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALIGNED_STORAGE_H
+
+#include "src/__support/macros/config.h"
+#include <stddef.h> // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <size_t Len, size_t Align> struct aligned_storage {
+ struct type {
+ alignas(Align) unsigned char data[Len];
+ };
+};
+
+template <size_t Len, size_t Align>
+using aligned_storage_t = typename aligned_storage<Len, Align>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALIGNED_STORAGE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/always_false.h b/lib/libcxx/libc/src/__support/CPP/type_traits/always_false.h
new file mode 100644
index 0000000000..218eb9d577
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/always_false.h
@@ -0,0 +1,32 @@
+//===-- convenient static_assert(false) helper ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
+
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// This is technically not part of the standard but it come often enough that
+// it's convenient to have around.
+//
+// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html#valid-workaround
+//
+// This will be fixed in C++23 according to [CWG
+// 2518](https://cplusplus.github.io/CWG/issues/2518.html).
+
+// Usage `static_assert(cpp::always_false<T>, "error message");`
+template <typename...> LIBC_INLINE_VAR constexpr bool always_false = false;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/bool_constant.h b/lib/libcxx/libc/src/__support/CPP/type_traits/bool_constant.h
new file mode 100644
index 0000000000..e61a81a84b
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/bool_constant.h
@@ -0,0 +1,23 @@
+//===-- bool_constant type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_BOOL_CONSTANT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_BOOL_CONSTANT_H
+
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// bool_constant
+template <bool V> using bool_constant = cpp::integral_constant<bool, V>;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_BOOL_CONSTANT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/conditional.h b/lib/libcxx/libc/src/__support/CPP/type_traits/conditional.h
new file mode 100644
index 0000000000..effcda02da
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/conditional.h
@@ -0,0 +1,28 @@
+//===-- conditional type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_CONDITIONAL_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_CONDITIONAL_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// conditional
+template <bool B, typename T, typename F>
+struct conditional : type_identity<T> {};
+template <typename T, typename F>
+struct conditional<false, T, F> : type_identity<F> {};
+template <bool B, typename T, typename F>
+using conditional_t = typename conditional<B, T, F>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_CONDITIONAL_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/decay.h b/lib/libcxx/libc/src/__support/CPP/type_traits/decay.h
new file mode 100644
index 0000000000..c07e9e8557
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/decay.h
@@ -0,0 +1,40 @@
+//===-- decay type_traits ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H
+
+#include "src/__support/macros/attributes.h"
+
+#include "src/__support/CPP/type_traits/add_pointer.h"
+#include "src/__support/CPP/type_traits/conditional.h"
+#include "src/__support/CPP/type_traits/is_array.h"
+#include "src/__support/CPP/type_traits/is_function.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/CPP/type_traits/remove_extent.h"
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// decay
+template <class T> class decay {
+ using U = cpp::remove_reference_t<T>;
+
+public:
+ using type = conditional_t<
+ cpp::is_array_v<U>, cpp::add_pointer_t<cpp::remove_extent_t<U>>,
+ cpp::conditional_t<cpp::is_function_v<U>, cpp::add_pointer_t<U>,
+ cpp::remove_cv_t<U>>>;
+};
+template <class T> using decay_t = typename decay<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/enable_if.h b/lib/libcxx/libc/src/__support/CPP/type_traits/enable_if.h
new file mode 100644
index 0000000000..a2ce2037eb
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/enable_if.h
@@ -0,0 +1,26 @@
+//===-- enable_if type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ENABLE_IF_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ENABLE_IF_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// enable_if
+template <bool B, typename T = void> struct enable_if;
+template <typename T> struct enable_if<true, T> : type_identity<T> {};
+template <bool B, typename T = void>
+using enable_if_t = typename enable_if<B, T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_ENABLE_IF_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/false_type.h b/lib/libcxx/libc/src/__support/CPP/type_traits/false_type.h
new file mode 100644
index 0000000000..65934b96ba
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/false_type.h
@@ -0,0 +1,23 @@
+//===-- false_type type_traits ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_FALSE_TYPE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_FALSE_TYPE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// false_type
+using false_type = cpp::bool_constant<false>;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_FALSE_TYPE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/has_unique_object_representations.h b/lib/libcxx/libc/src/__support/CPP/type_traits/has_unique_object_representations.h
new file mode 100644
index 0000000000..639fb69d27
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/has_unique_object_representations.h
@@ -0,0 +1,30 @@
+//===-- has_unique_object_representations type_traits ------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_H
+
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/CPP/type_traits/remove_all_extents.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <class T>
+struct has_unique_object_representations
+ : public integral_constant<bool, __has_unique_object_representations(
+ remove_all_extents_t<T>)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool has_unique_object_representations_v =
+ has_unique_object_representations<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/integral_constant.h b/lib/libcxx/libc/src/__support/CPP/type_traits/integral_constant.h
new file mode 100644
index 0000000000..931a9b98a6
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/integral_constant.h
@@ -0,0 +1,26 @@
+//===-- integral_constant type_traits ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INTEGRAL_CONSTANT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INTEGRAL_CONSTANT_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE_VAR
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// integral_constant
+template <typename T, T v> struct integral_constant {
+ using value_type = T;
+ LIBC_INLINE_VAR static constexpr T value = v;
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INTEGRAL_CONSTANT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/invoke.h b/lib/libcxx/libc/src/__support/CPP/type_traits/invoke.h
new file mode 100644
index 0000000000..e4d9be74d1
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/invoke.h
@@ -0,0 +1,67 @@
+//===-- invoke type_traits --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_H
+
+#include "src/__support/CPP/type_traits/always_false.h"
+#include "src/__support/CPP/type_traits/decay.h"
+#include "src/__support/CPP/type_traits/enable_if.h"
+#include "src/__support/CPP/type_traits/is_base_of.h"
+#include "src/__support/CPP/type_traits/is_pointer.h"
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/utility/forward.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+namespace detail {
+
+// Catch all function and functor types.
+template <class FunctionPtrType> struct invoke_dispatcher {
+ template <class T, class... Args,
+ typename = cpp::enable_if_t<
+ cpp::is_same_v<cpp::decay_t<T>, FunctionPtrType>>>
+ LIBC_INLINE static decltype(auto) call(T &&fun, Args &&...args) {
+ return cpp::forward<T>(fun)(cpp::forward<Args>(args)...);
+ }
+};
+
+// Catch pointer to member function types.
+template <class Class, class FunctionReturnType>
+struct invoke_dispatcher<FunctionReturnType Class::*> {
+ using FunctionPtrType = FunctionReturnType Class::*;
+
+ template <class T, class... Args, class DecayT = cpp::decay_t<T>>
+ LIBC_INLINE static decltype(auto) call(FunctionPtrType fun, T &&t1,
+ Args &&...args) {
+ if constexpr (cpp::is_base_of_v<Class, DecayT>) {
+ // T is a (possibly cv ref) type.
+ return (cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...);
+ } else if constexpr (cpp::is_pointer_v<T>) {
+ // T is a pointer type.
+ return (*cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...);
+ } else {
+ static_assert(cpp::always_false<T>);
+ }
+ }
+};
+
+} // namespace detail
+template <class Function, class... Args>
+decltype(auto) invoke(Function &&fun, Args &&...args) {
+ return detail::invoke_dispatcher<cpp::decay_t<Function>>::call(
+ cpp::forward<Function>(fun), cpp::forward<Args>(args)...);
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/invoke_result.h b/lib/libcxx/libc/src/__support/CPP/type_traits/invoke_result.h
new file mode 100644
index 0000000000..71d848b77f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/invoke_result.h
@@ -0,0 +1,29 @@
+//===-- invoke_result type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
+
+#include "src/__support/CPP/type_traits/invoke.h"
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/CPP/utility/declval.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <class F, class... Args>
+struct invoke_result : cpp::type_identity<decltype(cpp::invoke(
+ cpp::declval<F>(), cpp::declval<Args>()...))> {};
+
+template <class F, class... Args>
+using invoke_result_t = typename invoke_result<F, Args...>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_arithmetic.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_arithmetic.h
new file mode 100644
index 0000000000..33671b0def
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_arithmetic.h
@@ -0,0 +1,30 @@
+//===-- is_arithmetic type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARITHMETIC_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARITHMETIC_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_floating_point.h"
+#include "src/__support/CPP/type_traits/is_integral.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_arithmetic
+template <typename T>
+struct is_arithmetic : cpp::bool_constant<(cpp::is_integral_v<T> ||
+ cpp::is_floating_point_v<T>)> {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARITHMETIC_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_array.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_array.h
new file mode 100644
index 0000000000..f0ab100fd5
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_array.h
@@ -0,0 +1,31 @@
+//===-- is_array type_traits ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARRAY_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARRAY_H
+
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+#include <stddef.h> // For size_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_array
+template <class T> struct is_array : false_type {};
+template <class T> struct is_array<T[]> : true_type {};
+template <class T, size_t N> struct is_array<T[N]> : true_type {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_array_v = is_array<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ARRAY_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_base_of.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_base_of.h
new file mode 100644
index 0000000000..2efd1bf3f1
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_base_of.h
@@ -0,0 +1,47 @@
+//===-- is_base_of type_traits ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_BASE_OF_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_BASE_OF_H
+
+#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/is_class.h"
+#include "src/__support/CPP/type_traits/remove_all_extents.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_base_of
+namespace detail {
+template <typename B> cpp::true_type __test_ptr_conv(const volatile B *);
+template <typename> cpp::false_type __test_ptr_conv(const volatile void *);
+
+template <typename B, typename D>
+auto is_base_of(int) -> decltype(__test_ptr_conv<B>(static_cast<D *>(nullptr)));
+
+template <typename, typename>
+auto is_base_of(...) -> cpp::true_type; // private or ambiguous base
+
+} // namespace detail
+
+template <typename Base, typename Derived>
+struct is_base_of
+ : cpp::bool_constant<
+ cpp::is_class_v<Base> &&
+ cpp::is_class_v<Derived> &&decltype(detail::is_base_of<Base, Derived>(
+ 0))::value> {};
+template <typename Base, typename Derived>
+LIBC_INLINE_VAR constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_BASE_OF_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_class.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_class.h
new file mode 100644
index 0000000000..fe12f7d276
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_class.h
@@ -0,0 +1,32 @@
+//===-- is_class type_traits ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CLASS_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CLASS_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/is_union.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_class
+namespace detail {
+template <class T> cpp::bool_constant<!cpp::is_union_v<T>> test(int T::*);
+template <class> cpp::false_type test(...);
+} // namespace detail
+template <class T> struct is_class : decltype(detail::test<T>(nullptr)) {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_class_v = is_class<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CLASS_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h
new file mode 100644
index 0000000000..23f05c08cc
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h
@@ -0,0 +1,53 @@
+//===-- is_complex type_traits ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+// LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128
+#include "src/__support/macros/properties/complex_types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_complex
+template <typename T> struct is_complex {
+private:
+ template <typename Head, typename... Args>
+ LIBC_INLINE_VAR static constexpr bool __is_unqualified_any_of() {
+ return (... || is_same_v<remove_cv_t<Head>, Args>);
+ }
+
+public:
+ LIBC_INLINE_VAR static constexpr bool value =
+ __is_unqualified_any_of<T, _Complex float, _Complex double,
+ _Complex long double
+#ifdef LIBC_TYPES_HAS_CFLOAT16
+ ,
+ cfloat16
+#endif
+#ifdef LIBC_TYPES_HAS_CFLOAT128
+ ,
+ cfloat128
+#endif
+ >();
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value;
+template <typename T1, typename T2>
+LIBC_INLINE_VAR constexpr bool is_complex_type_same() {
+ return is_same_v<remove_cv_t<T1>, T2>;
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_const.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_const.h
new file mode 100644
index 0000000000..b8e60f79a6
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_const.h
@@ -0,0 +1,28 @@
+//===-- is_const type_traits ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONST_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONST_H
+
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_const
+template <class T> struct is_const : cpp::false_type {};
+template <class T> struct is_const<const T> : cpp::true_type {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_const_v = is_const<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONST_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h
new file mode 100644
index 0000000000..0bb2d0806c
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h
@@ -0,0 +1,24 @@
+//===-- is_constant_evaluated type_traits -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H
+
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+LIBC_INLINE constexpr bool is_constant_evaluated() {
+ return __builtin_is_constant_evaluated();
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_convertible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_convertible.h
new file mode 100644
index 0000000000..a9f94cbb95
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_convertible.h
@@ -0,0 +1,48 @@
+//===-- is_convertible type_traits ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONVERTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONVERTIBLE_H
+
+#include "src/__support/CPP/type_traits/is_void.h"
+#include "src/__support/CPP/utility/declval.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_convertible
+namespace detail {
+template <class T>
+auto test_returnable(int)
+ -> decltype(void(static_cast<T (*)()>(nullptr)), cpp::true_type{});
+template <class> auto test_returnable(...) -> cpp::false_type;
+
+template <class From, class To>
+auto test_implicitly_convertible(int)
+ -> decltype(void(cpp::declval<void (&)(To)>()(cpp::declval<From>())),
+ cpp::true_type{});
+template <class, class>
+auto test_implicitly_convertible(...) -> cpp::false_type;
+} // namespace detail
+
+template <class From, class To>
+struct is_convertible
+ : cpp::bool_constant<
+ (decltype(detail::test_returnable<To>(0))::value &&
+ decltype(detail::test_implicitly_convertible<From, To>(0))::value) ||
+ (cpp::is_void_v<From> && cpp::is_void_v<To>)> {};
+
+template <class From, class To>
+LIBC_INLINE_VAR constexpr bool is_convertible_v =
+ is_convertible<From, To>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONVERTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h
new file mode 100644
index 0000000000..9beb93d146
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h
@@ -0,0 +1,32 @@
+//===-- is_copy_assignable type_traits --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H
+
+#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is copy assignable
+template <class T>
+struct is_copy_assignable
+ : public integral_constant<
+ bool, __is_assignable(cpp::add_lvalue_reference_t<T>,
+ cpp::add_lvalue_reference_t<const T>)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_copy_assignable_v =
+ is_copy_assignable<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h
new file mode 100644
index 0000000000..d8eb9ad350
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h
@@ -0,0 +1,31 @@
+//===-- is_copy_constructible type_traits -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H
+
+#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is copy constructible
+template <class T>
+struct is_copy_constructible
+ : public integral_constant<
+ bool, __is_constructible(T, cpp::add_lvalue_reference_t<const T>)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_copy_constructible_v =
+ is_copy_constructible<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h
new file mode 100644
index 0000000000..830f22efaf
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h
@@ -0,0 +1,68 @@
+//===-- is_destructible type_traits -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_DESTRUCTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_DESTRUCTIBLE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/is_function.h"
+#include "src/__support/CPP/type_traits/is_reference.h"
+#include "src/__support/CPP/type_traits/remove_all_extents.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_destructible
+#if __has_builtin(__is_destructible)
+template <typename T>
+struct is_destructible : bool_constant<__is_destructible(T)> {};
+#else
+// if it's a reference, return true
+// if it's a function, return false
+// if it's void, return false
+// if it's an array of unknown bound, return false
+// Otherwise, return "declval<T&>().~T()" is well-formed
+// where T is remove_all_extents<T>::type
+template <typename> struct __is_destructible_apply : cpp::type_identity<int> {};
+template <typename T> struct __is_destructor_wellformed {
+ template <typename T1>
+ static cpp::true_type __test(
+ typename __is_destructible_apply<decltype(declval<T1 &>().~T1())>::type);
+ template <typename T1> static cpp::false_type __test(...);
+ static const bool value = decltype(__test<T>(12))::value;
+};
+template <typename T, bool> struct __destructible_imp;
+template <typename T>
+struct __destructible_imp<T, false>
+ : public bool_constant<
+ __is_destructor_wellformed<cpp::remove_all_extents_t<T>>::value> {};
+template <typename T>
+struct __destructible_imp<T, true> : public cpp::true_type {};
+template <typename T, bool> struct __destructible_false;
+template <typename T>
+struct __destructible_false<T, false>
+ : public __destructible_imp<T, is_reference<T>::value> {};
+template <typename T>
+struct __destructible_false<T, true> : public cpp::false_type {};
+template <typename T>
+struct is_destructible : public __destructible_false<T, is_function<T>::value> {
+};
+template <typename T> struct is_destructible<T[]> : public false_type {};
+template <> struct is_destructible<void> : public false_type {};
+#endif
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_destructible_v = is_destructible<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_DESTRUCTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_enum.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_enum.h
new file mode 100644
index 0000000000..623ae072af
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_enum.h
@@ -0,0 +1,26 @@
+//===-- is_enum type_traits -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ENUM_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ENUM_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_enum
+template <typename T> struct is_enum : bool_constant<__is_enum(T)> {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_enum_v = is_enum<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ENUM_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_fixed_point.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_fixed_point.h
new file mode 100644
index 0000000000..9df2a7727c
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_fixed_point.h
@@ -0,0 +1,49 @@
+//===-- is_fixed_point type_traits ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FIXED_POINT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FIXED_POINT_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_fixed_point
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+template <typename T> struct is_fixed_point {
+private:
+ template <typename Head, typename... Args>
+ LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
+ return (... || is_same_v<remove_cv_t<Head>, Args>);
+ }
+
+public:
+ LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of<
+ T, short fract, fract, long fract, unsigned short fract, unsigned fract,
+ unsigned long fract, short accum, accum, long accum, unsigned short accum,
+ unsigned accum, unsigned long accum, short sat fract, sat fract,
+ long sat fract, unsigned short sat fract, unsigned sat fract,
+ unsigned long sat fract, short sat accum, sat accum, long sat accum,
+ unsigned short sat accum, unsigned sat accum, unsigned long sat accum>();
+};
+#else
+template <typename T> struct is_fixed_point : false_type {};
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_fixed_point_v = is_fixed_point<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FIXED_POINT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_floating_point.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_floating_point.h
new file mode 100644
index 0000000000..11ffbfabe6
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -0,0 +1,48 @@
+//===-- is_floating_point type_traits ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FLOATING_POINT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FLOATING_POINT_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_FLOAT128
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_floating_point
+template <typename T> struct is_floating_point {
+private:
+ template <typename Head, typename... Args>
+ LIBC_INLINE_VAR static constexpr bool __is_unqualified_any_of() {
+ return (... || is_same_v<remove_cv_t<Head>, Args>);
+ }
+
+public:
+ LIBC_INLINE_VAR static constexpr bool value =
+ __is_unqualified_any_of<T, float, double, long double
+#ifdef LIBC_TYPES_HAS_FLOAT16
+ ,
+ float16
+#endif
+#ifdef LIBC_TYPES_HAS_FLOAT128
+ ,
+ float128
+#endif
+ >();
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_floating_point_v =
+ is_floating_point<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FLOATING_POINT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_function.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_function.h
new file mode 100644
index 0000000000..f7717f0a4d
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_function.h
@@ -0,0 +1,35 @@
+//===-- is_function type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FUNCTION_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FUNCTION_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_const.h"
+#include "src/__support/CPP/type_traits/is_reference.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_function
+#if __has_builtin(__is_function)
+template <typename T>
+struct is_function : integral_constant<bool, __is_function(T)> {};
+#else
+template <typename T>
+struct is_function
+ : public bool_constant<!(is_reference_v<T> || is_const_v<const T>)> {};
+#endif
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_function_v = is_function<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_FUNCTION_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h
new file mode 100644
index 0000000000..96ba09a07d
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h
@@ -0,0 +1,43 @@
+//===-- is_integral type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_INTEGRAL_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_INTEGRAL_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_integral
+template <typename T> struct is_integral {
+private:
+ template <typename Head, typename... Args>
+ LIBC_INLINE_VAR static constexpr bool __is_unqualified_any_of() {
+ return (... || is_same_v<remove_cv_t<Head>, Args>);
+ }
+
+public:
+ LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of<
+ T,
+#ifdef LIBC_TYPES_HAS_INT128
+ __int128_t, __uint128_t,
+#endif
+ char, signed char, unsigned char, short, unsigned short, int,
+ unsigned int, long, unsigned long, long long, unsigned long long, bool>();
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_integral_v = is_integral<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_INTEGRAL_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_lvalue_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_lvalue_reference.h
new file mode 100644
index 0000000000..e0bfbebdaa
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_lvalue_reference.h
@@ -0,0 +1,35 @@
+//===-- is_lvalue_reference type_traits -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_LVALUE_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_LVALUE_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_lvalue_reference
+#if __has_builtin(__is_lvalue_reference)
+template <typename T>
+struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {};
+#else
+template <typename T> struct is_lvalue_reference : public false_type {};
+template <typename T> struct is_lvalue_reference<T &> : public true_type {};
+#endif
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_lvalue_reference_v =
+ is_lvalue_reference<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_LVALUE_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_member_pointer.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_member_pointer.h
new file mode 100644
index 0000000000..f445670039
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_member_pointer.h
@@ -0,0 +1,33 @@
+//===-- is_member_pointer type_traits ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MEMBER_POINTER_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MEMBER_POINTER_H
+
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_member_pointer
+template <class T> struct is_member_pointer_helper : cpp::false_type {};
+template <class T, class U>
+struct is_member_pointer_helper<T U::*> : cpp::true_type {};
+template <class T>
+struct is_member_pointer : is_member_pointer_helper<cpp::remove_cv_t<T>> {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_member_pointer_v =
+ is_member_pointer<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MEMBER_POINTER_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h
new file mode 100644
index 0000000000..a788bd9074
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h
@@ -0,0 +1,33 @@
+//===-- is_move_assignable type_traits --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H
+
+#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is move assignable
+template <class T>
+struct is_move_assignable
+ : public integral_constant<bool, __is_assignable(
+ cpp::add_lvalue_reference_t<T>,
+ cpp::add_rvalue_reference_t<T>)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_move_assignable_v =
+ is_move_assignable<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h
new file mode 100644
index 0000000000..c898960546
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h
@@ -0,0 +1,31 @@
+//===-- is_move_constructible type_traits ------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H
+
+#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is move constructible
+template <class T>
+struct is_move_constructible
+ : public integral_constant<bool, __is_constructible(
+ T, cpp::add_rvalue_reference_t<T>)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_move_constructible_v =
+ is_move_constructible<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_null_pointer.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_null_pointer.h
new file mode 100644
index 0000000000..acf341311b
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_null_pointer.h
@@ -0,0 +1,29 @@
+//===-- is_null_pointer type_traits -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_NULL_POINTER_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_NULL_POINTER_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_null_pointer
+using nullptr_t = decltype(nullptr);
+template <class T>
+struct is_null_pointer : cpp::is_same<cpp::nullptr_t, cpp::remove_cv_t<T>> {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_null_pointer_v = is_null_pointer<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_NULL_POINTER_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_object.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_object.h
new file mode 100644
index 0000000000..16799fb8f2
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_object.h
@@ -0,0 +1,33 @@
+//===-- is_object type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_array.h"
+#include "src/__support/CPP/type_traits/is_class.h"
+#include "src/__support/CPP/type_traits/is_scalar.h"
+#include "src/__support/CPP/type_traits/is_union.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_object
+template <class T>
+struct is_object
+ : cpp::bool_constant<cpp::is_scalar_v<T> || cpp::is_array_v<T> ||
+ cpp::is_union_v<T> || cpp::is_class_v<T>> {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_object_v = is_object<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_pointer.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_pointer.h
new file mode 100644
index 0000000000..606c8e9e8c
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_pointer.h
@@ -0,0 +1,31 @@
+//===-- is_pointer type_traits ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_POINTER_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_POINTER_H
+
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_pointer
+template <typename T> struct is_pointer : cpp::false_type {};
+template <typename T> struct is_pointer<T *> : cpp::true_type {};
+template <typename T> struct is_pointer<T *const> : cpp::true_type {};
+template <typename T> struct is_pointer<T *volatile> : cpp::true_type {};
+template <typename T> struct is_pointer<T *const volatile> : cpp::true_type {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_pointer_v = is_pointer<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_POINTER_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_reference.h
new file mode 100644
index 0000000000..12da81778f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_reference.h
@@ -0,0 +1,34 @@
+//===-- is_reference type_traits --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_reference
+#if __has_builtin(__is_reference)
+template <typename T> struct is_reference : bool_constant<__is_reference(T)> {};
+#else
+template <typename T> struct is_reference : public false_type {};
+template <typename T> struct is_reference<T &> : public true_type {};
+template <typename T> struct is_reference<T &&> : public true_type {};
+#endif
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_reference_v = is_reference<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_rvalue_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_rvalue_reference.h
new file mode 100644
index 0000000000..998b6353af
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_rvalue_reference.h
@@ -0,0 +1,35 @@
+//===-- is_rvalue_reference type_traits -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_RVALUE_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_RVALUE_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_rvalue_reference
+#if __has_builtin(__is_rvalue_reference)
+template <typename T>
+struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {};
+#else
+template <typename T> struct is_rvalue_reference : public false_type {};
+template <typename T> struct is_rvalue_reference<T &&> : public true_type {};
+#endif
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_rvalue_reference_v =
+ is_rvalue_reference<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_RVALUE_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_same.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_same.h
new file mode 100644
index 0000000000..306d16b86f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_same.h
@@ -0,0 +1,28 @@
+//===-- is_same type_traits -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SAME_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SAME_H
+
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_same
+template <typename T, typename U> struct is_same : cpp::false_type {};
+template <typename T> struct is_same<T, T> : cpp::true_type {};
+template <typename T, typename U>
+LIBC_INLINE_VAR constexpr bool is_same_v = is_same<T, U>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SAME_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_scalar.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_scalar.h
new file mode 100644
index 0000000000..7f8a750cd7
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_scalar.h
@@ -0,0 +1,35 @@
+//===-- is_scalar type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SCALAR_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SCALAR_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_arithmetic.h"
+#include "src/__support/CPP/type_traits/is_enum.h"
+#include "src/__support/CPP/type_traits/is_member_pointer.h"
+#include "src/__support/CPP/type_traits/is_null_pointer.h"
+#include "src/__support/CPP/type_traits/is_pointer.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_scalar
+template <class T>
+struct is_scalar
+ : cpp::bool_constant<cpp::is_arithmetic_v<T> || cpp::is_enum_v<T> ||
+ cpp::is_pointer_v<T> || cpp::is_member_pointer_v<T> ||
+ cpp::is_null_pointer_v<T>> {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_scalar_v = is_scalar<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SCALAR_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_signed.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_signed.h
new file mode 100644
index 0000000000..3f56fb38aa
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_signed.h
@@ -0,0 +1,31 @@
+//===-- is_signed type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_arithmetic.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_signed
+template <typename T>
+struct is_signed : bool_constant<(is_arithmetic_v<T> && (T(-1) < T(0)))> {
+ LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
+ LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_constructible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_constructible.h
new file mode 100644
index 0000000000..b801911038
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_constructible.h
@@ -0,0 +1,25 @@
+//===-- is_trivially_constructible type_traits ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_CONSTRUCTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_CONSTRUCTIBLE_H
+
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_trivially_constructible
+template <class T, class... Args>
+struct is_trivially_constructible
+ : integral_constant<bool, __is_trivially_constructible(T, Args...)> {};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_CONSTRUCTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_copyable.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_copyable.h
new file mode 100644
index 0000000000..a3e786fe1d
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_copyable.h
@@ -0,0 +1,29 @@
+//===-- is_trivially_copyable type_traits -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H
+
+#include "src/__support/CPP/type_traits/integral_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_trivially_copyable
+template <class T>
+struct is_trivially_copyable
+ : public integral_constant<bool, __is_trivially_copyable(T)> {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_trivially_copyable_v =
+ is_trivially_copyable<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_destructible.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_destructible.h
new file mode 100644
index 0000000000..d727a0ec3a
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_trivially_destructible.h
@@ -0,0 +1,37 @@
+//===-- is_trivially_destructible type_traits -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_DESTRUCTIBLE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_DESTRUCTIBLE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_destructible.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_trivially_destructible
+#if __has_builtin(__is_trivially_destructible)
+template <typename T>
+struct is_trivially_destructible
+ : public bool_constant<__is_trivially_destructible(T)> {};
+#else
+template <typename T>
+struct is_trivially_destructible
+ : public bool_constant<cpp::is_destructible_v<T> &&__has_trivial_destructor(
+ T)> {};
+#endif // __has_builtin(__is_trivially_destructible)
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_trivially_destructible_v =
+ is_trivially_destructible<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_DESTRUCTIBLE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_union.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_union.h
new file mode 100644
index 0000000000..00ca11a351
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_union.h
@@ -0,0 +1,26 @@
+//===-- is_union type_traits ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNION_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNION_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_union
+template <class T> struct is_union : bool_constant<__is_union(T)> {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_union_v = is_union<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNION_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h
new file mode 100644
index 0000000000..eed519b1c0
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h
@@ -0,0 +1,31 @@
+//===-- is_unsigned type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_arithmetic.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_unsigned
+template <typename T>
+struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
+ LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
+ LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/is_void.h b/lib/libcxx/libc/src/__support/CPP/type_traits/is_void.h
new file mode 100644
index 0000000000..30459dcf91
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/is_void.h
@@ -0,0 +1,27 @@
+//===-- is_void type_traits -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_VOID_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_VOID_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_void
+template <typename T> struct is_void : is_same<void, remove_cv_t<T>> {};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_void_v = is_void<T>::value;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_VOID_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/make_signed.h b/lib/libcxx/libc/src/__support/CPP/type_traits/make_signed.h
new file mode 100644
index 0000000000..00bc6be8fc
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/make_signed.h
@@ -0,0 +1,41 @@
+//===-- make_signed type_traits ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_SIGNED_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_SIGNED_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// make_signed
+template <typename T> struct make_signed;
+template <> struct make_signed<char> : type_identity<char> {};
+template <> struct make_signed<signed char> : type_identity<char> {};
+template <> struct make_signed<short> : type_identity<short> {};
+template <> struct make_signed<int> : type_identity<int> {};
+template <> struct make_signed<long> : type_identity<long> {};
+template <> struct make_signed<long long> : type_identity<long long> {};
+template <> struct make_signed<unsigned char> : type_identity<char> {};
+template <> struct make_signed<unsigned short> : type_identity<short> {};
+template <> struct make_signed<unsigned int> : type_identity<int> {};
+template <> struct make_signed<unsigned long> : type_identity<long> {};
+template <>
+struct make_signed<unsigned long long> : type_identity<long long> {};
+#ifdef LIBC_TYPES_HAS_INT128
+template <> struct make_signed<__int128_t> : type_identity<__int128_t> {};
+template <> struct make_signed<__uint128_t> : type_identity<__int128_t> {};
+#endif
+template <typename T> using make_signed_t = typename make_signed<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_SIGNED_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/make_unsigned.h b/lib/libcxx/libc/src/__support/CPP/type_traits/make_unsigned.h
new file mode 100644
index 0000000000..e5f60ae665
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/make_unsigned.h
@@ -0,0 +1,46 @@
+//===-- make_unsigned type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_UNSIGNED_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_UNSIGNED_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// make_unsigned
+
+template <typename T> struct make_unsigned;
+template <> struct make_unsigned<char> : type_identity<unsigned char> {};
+template <> struct make_unsigned<signed char> : type_identity<unsigned char> {};
+template <> struct make_unsigned<short> : type_identity<unsigned short> {};
+template <> struct make_unsigned<int> : type_identity<unsigned int> {};
+template <> struct make_unsigned<long> : type_identity<unsigned long> {};
+template <>
+struct make_unsigned<long long> : type_identity<unsigned long long> {};
+template <>
+struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
+template <>
+struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
+template <> struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
+template <>
+struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
+template <>
+struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
+#ifdef LIBC_TYPES_HAS_INT128
+template <> struct make_unsigned<__int128_t> : type_identity<__uint128_t> {};
+template <> struct make_unsigned<__uint128_t> : type_identity<__uint128_t> {};
+#endif
+template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_UNSIGNED_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/remove_all_extents.h b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_all_extents.h
new file mode 100644
index 0000000000..bc577ca6f4
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_all_extents.h
@@ -0,0 +1,41 @@
+//===-- remove_all_extents type_traits --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+#include <stddef.h> // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// remove_all_extents
+#if __has_builtin(__remove_all_extents)
+template <typename T> using remove_all_extents_t = __remove_all_extents(T);
+template <typename T>
+struct remove_all_extents : cpp::type_identity<remove_all_extents_t<T>> {};
+#else
+template <typename T> struct remove_all_extents {
+ using type = T;
+};
+template <typename T> struct remove_all_extents<T[]> {
+ using type = typename remove_all_extents<T>::type;
+};
+template <typename T, size_t _Np> struct remove_all_extents<T[_Np]> {
+ using type = typename remove_all_extents<T>::type;
+};
+template <typename T>
+using remove_all_extents_t = typename remove_all_extents<T>::type;
+#endif
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cv.h b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cv.h
new file mode 100644
index 0000000000..2e843e0b43
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cv.h
@@ -0,0 +1,28 @@
+//===-- remove_cv type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CV_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CV_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// remove_cv
+template <class T> struct remove_cv : cpp::type_identity<T> {};
+template <class T> struct remove_cv<const T> : cpp::type_identity<T> {};
+template <class T> struct remove_cv<volatile T> : cpp::type_identity<T> {};
+template <class T>
+struct remove_cv<const volatile T> : cpp::type_identity<T> {};
+template <class T> using remove_cv_t = typename remove_cv<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CV_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cvref.h b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cvref.h
new file mode 100644
index 0000000000..27591783fd
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_cvref.h
@@ -0,0 +1,27 @@
+//===-- remove_cvref type_traits --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CVREF_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CVREF_H
+
+#include "src/__support/CPP/type_traits/remove_cv.h"
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// remove_cvref
+template <typename T> struct remove_cvref {
+ using type = remove_cv_t<remove_reference_t<T>>;
+};
+template <typename T> using remove_cvref_t = typename remove_cvref<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_CVREF_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/remove_extent.h b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_extent.h
new file mode 100644
index 0000000000..4f5ffd3453
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_extent.h
@@ -0,0 +1,28 @@
+//===-- remove_extent type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_EXTENT_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_EXTENT_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+#include "stddef.h" // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// remove_extent
+template <class T> struct remove_extent : cpp::type_identity<T> {};
+template <class T> struct remove_extent<T[]> : cpp::type_identity<T> {};
+template <class T, size_t N>
+struct remove_extent<T[N]> : cpp::type_identity<T> {};
+template <class T> using remove_extent_t = typename remove_extent<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_EXTENT_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/remove_reference.h b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_reference.h
new file mode 100644
index 0000000000..26ded0879f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/remove_reference.h
@@ -0,0 +1,27 @@
+//===-- remove_reference type_traits ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_REFERENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_REFERENCE_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// remove_reference
+template <class T> struct remove_reference : cpp::type_identity<T> {};
+template <class T> struct remove_reference<T &> : cpp::type_identity<T> {};
+template <class T> struct remove_reference<T &&> : cpp::type_identity<T> {};
+template <class T>
+using remove_reference_t = typename remove_reference<T>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_REFERENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/true_type.h b/lib/libcxx/libc/src/__support/CPP/type_traits/true_type.h
new file mode 100644
index 0000000000..55f8a535d0
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/true_type.h
@@ -0,0 +1,23 @@
+//===-- true_type type_traits -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TRUE_TYPE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TRUE_TYPE_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// true_type
+using true_type = cpp::bool_constant<true>;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TRUE_TYPE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/type_identity.h b/lib/libcxx/libc/src/__support/CPP/type_traits/type_identity.h
new file mode 100644
index 0000000000..304a1ed2ce
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/type_identity.h
@@ -0,0 +1,24 @@
+//===-- type_identity type_traits -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TYPE_IDENTITY_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TYPE_IDENTITY_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// type_identity
+template <typename T> struct type_identity {
+ using type = T;
+};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_TYPE_IDENTITY_H
diff --git a/lib/libcxx/libc/src/__support/CPP/type_traits/void_t.h b/lib/libcxx/libc/src/__support/CPP/type_traits/void_t.h
new file mode 100644
index 0000000000..9018860a83
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/type_traits/void_t.h
@@ -0,0 +1,29 @@
+//===-- void_t type_traits --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_VOID_T_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_VOID_T_H
+
+#include "src/__support/CPP/type_traits/type_identity.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// void_t
+
+namespace detail {
+template <typename... Ts> struct make_void : cpp::type_identity<void> {};
+} // namespace detail
+
+template <typename... Ts>
+using void_t = typename detail::make_void<Ts...>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_VOID_T_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility.h b/lib/libcxx/libc/src/__support/CPP/utility.h
new file mode 100644
index 0000000000..083b4877c3
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility.h
@@ -0,0 +1,18 @@
+//===-- Analogous to <utility> ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_H
+
+#include "src/__support/CPP/utility/declval.h"
+#include "src/__support/CPP/utility/forward.h"
+#include "src/__support/CPP/utility/in_place.h"
+#include "src/__support/CPP/utility/integer_sequence.h"
+#include "src/__support/CPP/utility/move.h"
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility/declval.h b/lib/libcxx/libc/src/__support/CPP/utility/declval.h
new file mode 100644
index 0000000000..9b963b9220
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility/declval.h
@@ -0,0 +1,27 @@
+//===-- declval utility -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_DECLVAL_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_DECLVAL_H
+
+#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
+#include "src/__support/CPP/type_traits/always_false.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// declval
+template <typename T> cpp::add_rvalue_reference_t<T> declval() {
+ static_assert(cpp::always_false<T>,
+ "declval not allowed in an evaluated context");
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_DECLVAL_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility/forward.h b/lib/libcxx/libc/src/__support/CPP/utility/forward.h
new file mode 100644
index 0000000000..085b3d16f9
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility/forward.h
@@ -0,0 +1,35 @@
+//===-- forward utility -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_FORWARD_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_FORWARD_H
+
+#include "src/__support/CPP/type_traits/is_lvalue_reference.h"
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// forward
+template <typename T>
+LIBC_INLINE constexpr T &&forward(remove_reference_t<T> &value) {
+ return static_cast<T &&>(value);
+}
+
+template <typename T>
+LIBC_INLINE constexpr T &&forward(remove_reference_t<T> &&value) {
+ static_assert(!is_lvalue_reference_v<T>,
+ "cannot forward an rvalue as an lvalue");
+ return static_cast<T &&>(value);
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_FORWARD_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility/in_place.h b/lib/libcxx/libc/src/__support/CPP/utility/in_place.h
new file mode 100644
index 0000000000..3967eb1c53
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility/in_place.h
@@ -0,0 +1,39 @@
+//===-- in_place utility ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_IN_PLACE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_IN_PLACE_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+#include "src/__support/macros/config.h"
+
+#include <stddef.h> // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// in_place
+struct in_place_t {
+ LIBC_INLINE explicit in_place_t() = default;
+};
+LIBC_INLINE_VAR constexpr in_place_t in_place{};
+
+template <class T> struct in_place_type_t {
+ LIBC_INLINE explicit in_place_type_t() = default;
+};
+template <class T> LIBC_INLINE_VAR constexpr in_place_type_t<T> in_place_type{};
+
+template <size_t IDX> struct in_place_index_t {
+ LIBC_INLINE explicit in_place_index_t() = default;
+};
+template <size_t IDX>
+LIBC_INLINE_VAR constexpr in_place_index_t<IDX> in_place_index{};
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_IN_PLACE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h b/lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h
new file mode 100644
index 0000000000..06643d505a
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h
@@ -0,0 +1,40 @@
+//===-- integer_sequence utility --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H
+
+#include "src/__support/CPP/type_traits/is_integral.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// integer_sequence
+template <typename T, T... Ints> struct integer_sequence {
+ static_assert(cpp::is_integral_v<T>);
+ template <T Next> using append = integer_sequence<T, Ints..., Next>;
+};
+
+namespace detail {
+template <typename T, int N> struct make_integer_sequence {
+ using type =
+ typename make_integer_sequence<T, N - 1>::type::template append<N>;
+};
+template <typename T> struct make_integer_sequence<T, -1> {
+ using type = integer_sequence<T>;
+};
+} // namespace detail
+
+template <typename T, int N>
+using make_integer_sequence =
+ typename detail::make_integer_sequence<T, N - 1>::type;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H
diff --git a/lib/libcxx/libc/src/__support/CPP/utility/move.h b/lib/libcxx/libc/src/__support/CPP/utility/move.h
new file mode 100644
index 0000000000..b61f723e8d
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/CPP/utility/move.h
@@ -0,0 +1,27 @@
+//===-- move utility --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_MOVE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_MOVE_H
+
+#include "src/__support/CPP/type_traits/remove_reference.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// move
+template <class T>
+LIBC_INLINE constexpr cpp::remove_reference_t<T> &&move(T &&t) {
+ return static_cast<typename cpp::remove_reference_t<T> &&>(t);
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_MOVE_H
diff --git a/lib/libcxx/libc/src/__support/FPUtil/FPBits.h b/lib/libcxx/libc/src/__support/FPUtil/FPBits.h
new file mode 100644
index 0000000000..90b6e406e0
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/FPUtil/FPBits.h
@@ -0,0 +1,846 @@
+//===-- Abstract class for bit manipulation of float numbers. ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This file is shared with libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
+
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_assert.h" // LIBC_ASSERT
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_FLOAT128
+#include "src/__support/math_extras.h" // mask_trailing_ones
+#include "src/__support/sign.h" // Sign
+#include "src/__support/uint128.h"
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+// The supported floating point types.
+enum class FPType {
+ IEEE754_Binary16,
+ IEEE754_Binary32,
+ IEEE754_Binary64,
+ IEEE754_Binary128,
+ X86_Binary80,
+};
+
+// The classes hierarchy is as follows:
+//
+// ┌───────────────────┐
+// │ FPLayout<FPType> │
+// └─────────▲─────────┘
+// │
+// ┌─────────┴─────────┐
+// │ FPStorage<FPType> │
+// └─────────▲─────────┘
+// │
+// ┌────────────┴─────────────┐
+// │ │
+// ┌────────┴─────────┐ ┌──────────────┴──────────────────┐
+// │ FPRepSem<FPType> │ │ FPRepSem<FPType::X86_Binary80 │
+// └────────▲─────────┘ └──────────────▲──────────────────┘
+// │ │
+// └────────────┬─────────────┘
+// │
+// ┌───────┴───────┐
+// │ FPRepImpl<T> │
+// └───────▲───────┘
+// │
+// ┌────────┴────────┐
+// ┌─────┴─────┐ ┌─────┴─────┐
+// │ FPRep<T> │ │ FPBits<T> │
+// └───────────┘ └───────────┘
+//
+// - 'FPLayout' defines only a few constants, namely the 'StorageType' and
+// length of the sign, the exponent, fraction and significand parts.
+// - 'FPStorage' builds more constants on top of those from 'FPLayout' like
+// exponent bias and masks. It also holds the bit representation of the
+// floating point as a 'StorageType' type and defines tools to assemble or
+// test these parts.
+// - 'FPRepSem' defines functions to interact semantically with the floating
+// point representation. The default implementation is the one for 'IEEE754',
+// a specialization is provided for X86 Extended Precision.
+// - 'FPRepImpl' derives from 'FPRepSem' and adds functions that are common to
+// all implementations or build on the ones in 'FPRepSem'.
+// - 'FPRep' exposes all functions from 'FPRepImpl' and returns 'FPRep'
+// instances when using Builders (static functions to create values).
+// - 'FPBits' exposes all the functions from 'FPRepImpl' but operates on the
+// native C++ floating point type instead of 'FPType'. An additional 'get_val'
+// function allows getting the C++ floating point type value back. Builders
+// called from 'FPBits' return 'FPBits' instances.
+
+namespace internal {
+
+// Defines the layout (sign, exponent, significand) of a floating point type in
+// memory. It also defines its associated StorageType, i.e., the unsigned
+// integer type used to manipulate its representation.
+// Additionally we provide the fractional part length, i.e., the number of bits
+// after the decimal dot when the number is in normal form.
+template <FPType> struct FPLayout {};
+
+template <> struct FPLayout<FPType::IEEE754_Binary16> {
+ using StorageType = uint16_t;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int EXP_LEN = 5;
+ LIBC_INLINE_VAR static constexpr int SIG_LEN = 10;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
+template <> struct FPLayout<FPType::IEEE754_Binary32> {
+ using StorageType = uint32_t;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
+ LIBC_INLINE_VAR static constexpr int SIG_LEN = 23;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
+template <> struct FPLayout<FPType::IEEE754_Binary64> {
+ using StorageType = uint64_t;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int EXP_LEN = 11;
+ LIBC_INLINE_VAR static constexpr int SIG_LEN = 52;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
+template <> struct FPLayout<FPType::IEEE754_Binary128> {
+ using StorageType = UInt128;
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
+ LIBC_INLINE_VAR static constexpr int SIG_LEN = 112;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
+template <> struct FPLayout<FPType::X86_Binary80> {
+#if __SIZEOF_LONG_DOUBLE__ == 12
+ using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+#else
+ using StorageType = UInt128;
+#endif
+ LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+ LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
+ LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
+ LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;
+};
+
+// FPStorage derives useful constants from the FPLayout above.
+template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
+ using UP = FPLayout<fp_type>;
+
+ using UP::EXP_LEN; // The number of bits for the *exponent* part
+ using UP::SIG_LEN; // The number of bits for the *significand* part
+ using UP::SIGN_LEN; // The number of bits for the *sign* part
+ // For convenience, the sum of `SIG_LEN`, `EXP_LEN`, and `SIGN_LEN`.
+ LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + EXP_LEN + SIG_LEN;
+
+ // The number of bits after the decimal dot when the number is in normal form.
+ using UP::FRACTION_LEN;
+
+ // An unsigned integer that is wide enough to contain all of the floating
+ // point bits.
+ using StorageType = typename UP::StorageType;
+
+ // The number of bits in StorageType.
+ LIBC_INLINE_VAR static constexpr int STORAGE_LEN =
+ sizeof(StorageType) * CHAR_BIT;
+ static_assert(STORAGE_LEN >= TOTAL_LEN);
+
+ // The exponent bias. Always positive.
+ LIBC_INLINE_VAR static constexpr int32_t EXP_BIAS =
+ (1U << (EXP_LEN - 1U)) - 1U;
+ static_assert(EXP_BIAS > 0);
+
+ // The bit pattern that keeps only the *significand* part.
+ LIBC_INLINE_VAR static constexpr StorageType SIG_MASK =
+ mask_trailing_ones<StorageType, SIG_LEN>();
+ // The bit pattern that keeps only the *exponent* part.
+ LIBC_INLINE_VAR static constexpr StorageType EXP_MASK =
+ mask_trailing_ones<StorageType, EXP_LEN>() << SIG_LEN;
+ // The bit pattern that keeps only the *sign* part.
+ LIBC_INLINE_VAR static constexpr StorageType SIGN_MASK =
+ mask_trailing_ones<StorageType, SIGN_LEN>() << (EXP_LEN + SIG_LEN);
+ // The bit pattern that keeps only the *exponent + significand* part.
+ LIBC_INLINE_VAR static constexpr StorageType EXP_SIG_MASK =
+ mask_trailing_ones<StorageType, EXP_LEN + SIG_LEN>();
+ // The bit pattern that keeps only the *sign + exponent + significand* part.
+ LIBC_INLINE_VAR static constexpr StorageType FP_MASK =
+ mask_trailing_ones<StorageType, TOTAL_LEN>();
+ // The bit pattern that keeps only the *fraction* part.
+ // i.e., the *significand* without the leading one.
+ LIBC_INLINE_VAR static constexpr StorageType FRACTION_MASK =
+ mask_trailing_ones<StorageType, FRACTION_LEN>();
+
+ static_assert((SIG_MASK & EXP_MASK & SIGN_MASK) == 0, "masks disjoint");
+ static_assert((SIG_MASK | EXP_MASK | SIGN_MASK) == FP_MASK, "masks cover");
+
+protected:
+ // Merge bits from 'a' and 'b' values according to 'mask'.
+ // Use 'a' bits when corresponding 'mask' bits are zeroes and 'b' bits when
+ // corresponding bits are ones.
+ LIBC_INLINE static constexpr StorageType merge(StorageType a, StorageType b,
+ StorageType mask) {
+ // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
+ return a ^ ((a ^ b) & mask);
+ }
+
+ // A stongly typed integer that prevents mixing and matching integers with
+ // different semantics.
+ template <typename T> struct TypedInt {
+ using value_type = T;
+ LIBC_INLINE constexpr explicit TypedInt(T value) : value(value) {}
+ LIBC_INLINE constexpr TypedInt(const TypedInt &value) = default;
+ LIBC_INLINE constexpr TypedInt &operator=(const TypedInt &value) = default;
+
+ LIBC_INLINE constexpr explicit operator T() const { return value; }
+
+ LIBC_INLINE constexpr StorageType to_storage_type() const {
+ return StorageType(value);
+ }
+
+ LIBC_INLINE friend constexpr bool operator==(TypedInt a, TypedInt b) {
+ return a.value == b.value;
+ }
+ LIBC_INLINE friend constexpr bool operator!=(TypedInt a, TypedInt b) {
+ return a.value != b.value;
+ }
+
+ protected:
+ T value;
+ };
+
+ // An opaque type to store a floating point exponent.
+ // We define special values but it is valid to create arbitrary values as long
+ // as they are in the range [min, max].
+ struct Exponent : public TypedInt<int32_t> {
+ using UP = TypedInt<int32_t>;
+ using UP::UP;
+ LIBC_INLINE static constexpr auto subnormal() {
+ return Exponent(-EXP_BIAS);
+ }
+ LIBC_INLINE static constexpr auto min() { return Exponent(1 - EXP_BIAS); }
+ LIBC_INLINE static constexpr auto zero() { return Exponent(0); }
+ LIBC_INLINE static constexpr auto max() { return Exponent(EXP_BIAS); }
+ LIBC_INLINE static constexpr auto inf() { return Exponent(EXP_BIAS + 1); }
+ };
+
+ // An opaque type to store a floating point biased exponent.
+ // We define special values but it is valid to create arbitrary values as long
+ // as they are in the range [zero, bits_all_ones].
+ // Values greater than bits_all_ones are truncated.
+ struct BiasedExponent : public TypedInt<uint32_t> {
+ using UP = TypedInt<uint32_t>;
+ using UP::UP;
+
+ LIBC_INLINE constexpr BiasedExponent(Exponent exp)
+ : UP(static_cast<int32_t>(exp) + EXP_BIAS) {}
+
+ // Cast operator to get convert from BiasedExponent to Exponent.
+ LIBC_INLINE constexpr operator Exponent() const {
+ return Exponent(UP::value - EXP_BIAS);
+ }
+
+ LIBC_INLINE constexpr BiasedExponent &operator++() {
+ LIBC_ASSERT(*this != BiasedExponent(Exponent::inf()));
+ ++UP::value;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BiasedExponent &operator--() {
+ LIBC_ASSERT(*this != BiasedExponent(Exponent::subnormal()));
+ --UP::value;
+ return *this;
+ }
+ };
+
+ // An opaque type to store a floating point significand.
+ // We define special values but it is valid to create arbitrary values as long
+ // as they are in the range [zero, bits_all_ones].
+ // Note that the semantics of the Significand are implementation dependent.
+ // Values greater than bits_all_ones are truncated.
+ struct Significand : public TypedInt<StorageType> {
+ using UP = TypedInt<StorageType>;
+ using UP::UP;
+
+ LIBC_INLINE friend constexpr Significand operator|(const Significand a,
+ const Significand b) {
+ return Significand(
+ StorageType(a.to_storage_type() | b.to_storage_type()));
+ }
+ LIBC_INLINE friend constexpr Significand operator^(const Significand a,
+ const Significand b) {
+ return Significand(
+ StorageType(a.to_storage_type() ^ b.to_storage_type()));
+ }
+ LIBC_INLINE friend constexpr Significand operator>>(const Significand a,
+ int shift) {
+ return Significand(StorageType(a.to_storage_type() >> shift));
+ }
+
+ LIBC_INLINE static constexpr auto zero() {
+ return Significand(StorageType(0));
+ }
+ LIBC_INLINE static constexpr auto lsb() {
+ return Significand(StorageType(1));
+ }
+ LIBC_INLINE static constexpr auto msb() {
+ return Significand(StorageType(1) << (SIG_LEN - 1));
+ }
+ LIBC_INLINE static constexpr auto bits_all_ones() {
+ return Significand(SIG_MASK);
+ }
+ };
+
+ LIBC_INLINE static constexpr StorageType encode(BiasedExponent exp) {
+ return (exp.to_storage_type() << SIG_LEN) & EXP_MASK;
+ }
+
+ LIBC_INLINE static constexpr StorageType encode(Significand value) {
+ return value.to_storage_type() & SIG_MASK;
+ }
+
+ LIBC_INLINE static constexpr StorageType encode(BiasedExponent exp,
+ Significand sig) {
+ return encode(exp) | encode(sig);
+ }
+
+ LIBC_INLINE static constexpr StorageType encode(Sign sign, BiasedExponent exp,
+ Significand sig) {
+ if (sign.is_neg())
+ return SIGN_MASK | encode(exp, sig);
+ return encode(exp, sig);
+ }
+
+ // The floating point number representation as an unsigned integer.
+ StorageType bits{};
+
+ LIBC_INLINE constexpr FPStorage() : bits(0) {}
+ LIBC_INLINE constexpr FPStorage(StorageType value) : bits(value) {}
+
+ // Observers
+ LIBC_INLINE constexpr StorageType exp_bits() const { return bits & EXP_MASK; }
+ LIBC_INLINE constexpr StorageType sig_bits() const { return bits & SIG_MASK; }
+ LIBC_INLINE constexpr StorageType exp_sig_bits() const {
+ return bits & EXP_SIG_MASK;
+ }
+
+ // Parts
+ LIBC_INLINE constexpr BiasedExponent biased_exponent() const {
+ return BiasedExponent(static_cast<uint32_t>(exp_bits() >> SIG_LEN));
+ }
+ LIBC_INLINE constexpr void set_biased_exponent(BiasedExponent biased) {
+ bits = merge(bits, encode(biased), EXP_MASK);
+ }
+
+public:
+ LIBC_INLINE constexpr Sign sign() const {
+ return (bits & SIGN_MASK) ? Sign::NEG : Sign::POS;
+ }
+ LIBC_INLINE constexpr void set_sign(Sign signVal) {
+ if (sign() != signVal)
+ bits ^= SIGN_MASK;
+ }
+};
+
+// This layer defines all functions that are specific to how the the floating
+// point type is encoded. It enables constructions, modification and observation
+// of values manipulated as 'StorageType'.
+template <FPType fp_type, typename RetT>
+struct FPRepSem : public FPStorage<fp_type> {
+ using UP = FPStorage<fp_type>;
+ using typename UP::StorageType;
+ using UP::FRACTION_LEN;
+ using UP::FRACTION_MASK;
+
+protected:
+ using typename UP::Exponent;
+ using typename UP::Significand;
+ using UP::bits;
+ using UP::encode;
+ using UP::exp_bits;
+ using UP::exp_sig_bits;
+ using UP::sig_bits;
+ using UP::UP;
+
+public:
+ // Builders
+ LIBC_INLINE static constexpr RetT zero(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::subnormal(), Significand::zero()));
+ }
+ LIBC_INLINE static constexpr RetT one(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::zero(), Significand::zero()));
+ }
+ LIBC_INLINE static constexpr RetT min_subnormal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::subnormal(), Significand::lsb()));
+ }
+ LIBC_INLINE static constexpr RetT max_subnormal(Sign sign = Sign::POS) {
+ return RetT(
+ encode(sign, Exponent::subnormal(), Significand::bits_all_ones()));
+ }
+ LIBC_INLINE static constexpr RetT min_normal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::min(), Significand::zero()));
+ }
+ LIBC_INLINE static constexpr RetT max_normal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::max(), Significand::bits_all_ones()));
+ }
+ LIBC_INLINE static constexpr RetT inf(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::inf(), Significand::zero()));
+ }
+ LIBC_INLINE static constexpr RetT signaling_nan(Sign sign = Sign::POS,
+ StorageType v = 0) {
+ return RetT(encode(sign, Exponent::inf(),
+ (v ? Significand(v) : (Significand::msb() >> 1))));
+ }
+ LIBC_INLINE static constexpr RetT quiet_nan(Sign sign = Sign::POS,
+ StorageType v = 0) {
+ return RetT(
+ encode(sign, Exponent::inf(), Significand::msb() | Significand(v)));
+ }
+
+ // Observers
+ LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; }
+ LIBC_INLINE constexpr bool is_nan() const {
+ return exp_sig_bits() > encode(Exponent::inf(), Significand::zero());
+ }
+ LIBC_INLINE constexpr bool is_quiet_nan() const {
+ return exp_sig_bits() >= encode(Exponent::inf(), Significand::msb());
+ }
+ LIBC_INLINE constexpr bool is_signaling_nan() const {
+ return is_nan() && !is_quiet_nan();
+ }
+ LIBC_INLINE constexpr bool is_inf() const {
+ return exp_sig_bits() == encode(Exponent::inf(), Significand::zero());
+ }
+ LIBC_INLINE constexpr bool is_finite() const {
+ return exp_bits() != encode(Exponent::inf());
+ }
+ LIBC_INLINE
+ constexpr bool is_subnormal() const {
+ return exp_bits() == encode(Exponent::subnormal());
+ }
+ LIBC_INLINE constexpr bool is_normal() const {
+ return is_finite() && !is_subnormal();
+ }
+ LIBC_INLINE constexpr RetT next_toward_inf() const {
+ if (is_finite())
+ return RetT(bits + StorageType(1));
+ return RetT(bits);
+ }
+
+ // Returns the mantissa with the implicit bit set iff the current
+ // value is a valid normal number.
+ LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
+ if (is_subnormal())
+ return sig_bits();
+ return (StorageType(1) << UP::SIG_LEN) | sig_bits();
+ }
+};
+
+// Specialization for the X86 Extended Precision type.
+template <typename RetT>
+struct FPRepSem<FPType::X86_Binary80, RetT>
+ : public FPStorage<FPType::X86_Binary80> {
+ using UP = FPStorage<FPType::X86_Binary80>;
+ using typename UP::StorageType;
+ using UP::FRACTION_LEN;
+ using UP::FRACTION_MASK;
+
+ // The x86 80 bit float represents the leading digit of the mantissa
+ // explicitly. This is the mask for that bit.
+ static constexpr StorageType EXPLICIT_BIT_MASK = StorageType(1)
+ << FRACTION_LEN;
+ // The X80 significand is made of an explicit bit and the fractional part.
+ static_assert((EXPLICIT_BIT_MASK & FRACTION_MASK) == 0,
+ "the explicit bit and the fractional part should not overlap");
+ static_assert((EXPLICIT_BIT_MASK | FRACTION_MASK) == SIG_MASK,
+ "the explicit bit and the fractional part should cover the "
+ "whole significand");
+
+protected:
+ using typename UP::Exponent;
+ using typename UP::Significand;
+ using UP::encode;
+ using UP::UP;
+
+public:
+ // Builders
+ LIBC_INLINE static constexpr RetT zero(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::subnormal(), Significand::zero()));
+ }
+ LIBC_INLINE static constexpr RetT one(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::zero(), Significand::msb()));
+ }
+ LIBC_INLINE static constexpr RetT min_subnormal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::subnormal(), Significand::lsb()));
+ }
+ LIBC_INLINE static constexpr RetT max_subnormal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::subnormal(),
+ Significand::bits_all_ones() ^ Significand::msb()));
+ }
+ LIBC_INLINE static constexpr RetT min_normal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::min(), Significand::msb()));
+ }
+ LIBC_INLINE static constexpr RetT max_normal(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::max(), Significand::bits_all_ones()));
+ }
+ LIBC_INLINE static constexpr RetT inf(Sign sign = Sign::POS) {
+ return RetT(encode(sign, Exponent::inf(), Significand::msb()));
+ }
+ LIBC_INLINE static constexpr RetT signaling_nan(Sign sign = Sign::POS,
+ StorageType v = 0) {
+ return RetT(encode(sign, Exponent::inf(),
+ Significand::msb() |
+ (v ? Significand(v) : (Significand::msb() >> 2))));
+ }
+ LIBC_INLINE static constexpr RetT quiet_nan(Sign sign = Sign::POS,
+ StorageType v = 0) {
+ return RetT(encode(sign, Exponent::inf(),
+ Significand::msb() | (Significand::msb() >> 1) |
+ Significand(v)));
+ }
+
+ // Observers
+ LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; }
+ LIBC_INLINE constexpr bool is_nan() const {
+ // Most encoding forms from the table found in
+ // https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format
+ // are interpreted as NaN.
+ // More precisely :
+ // - Pseudo-Infinity
+ // - Pseudo Not a Number
+ // - Signalling Not a Number
+ // - Floating-point Indefinite
+ // - Quiet Not a Number
+ // - Unnormal
+ // This can be reduced to the following logic:
+ if (exp_bits() == encode(Exponent::inf()))
+ return !is_inf();
+ if (exp_bits() != encode(Exponent::subnormal()))
+ return (sig_bits() & encode(Significand::msb())) == 0;
+ return false;
+ }
+ LIBC_INLINE constexpr bool is_quiet_nan() const {
+ return exp_sig_bits() >=
+ encode(Exponent::inf(),
+ Significand::msb() | (Significand::msb() >> 1));
+ }
+ LIBC_INLINE constexpr bool is_signaling_nan() const {
+ return is_nan() && !is_quiet_nan();
+ }
+ LIBC_INLINE constexpr bool is_inf() const {
+ return exp_sig_bits() == encode(Exponent::inf(), Significand::msb());
+ }
+ LIBC_INLINE constexpr bool is_finite() const {
+ return !is_inf() && !is_nan();
+ }
+ LIBC_INLINE
+ constexpr bool is_subnormal() const {
+ return exp_bits() == encode(Exponent::subnormal());
+ }
+ LIBC_INLINE constexpr bool is_normal() const {
+ const auto exp = exp_bits();
+ if (exp == encode(Exponent::subnormal()) || exp == encode(Exponent::inf()))
+ return false;
+ return get_implicit_bit();
+ }
+ LIBC_INLINE constexpr RetT next_toward_inf() const {
+ if (is_finite()) {
+ if (exp_sig_bits() == max_normal().uintval()) {
+ return inf(sign());
+ } else if (exp_sig_bits() == max_subnormal().uintval()) {
+ return min_normal(sign());
+ } else if (sig_bits() == SIG_MASK) {
+ return RetT(encode(sign(), ++biased_exponent(), Significand::zero()));
+ } else {
+ return RetT(bits + StorageType(1));
+ }
+ }
+ return RetT(bits);
+ }
+
+ LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
+ return sig_bits();
+ }
+
+ // This functions is specific to FPRepSem<FPType::X86_Binary80>.
+ // TODO: Remove if possible.
+ LIBC_INLINE constexpr bool get_implicit_bit() const {
+ return static_cast<bool>(bits & EXPLICIT_BIT_MASK);
+ }
+
+ // This functions is specific to FPRepSem<FPType::X86_Binary80>.
+ // TODO: Remove if possible.
+ LIBC_INLINE constexpr void set_implicit_bit(bool implicitVal) {
+ if (get_implicit_bit() != implicitVal)
+ bits ^= EXPLICIT_BIT_MASK;
+ }
+};
+
+// 'FPRepImpl' is the bottom of the class hierarchy that only deals with
+// 'FPType'. The operations dealing with specific float semantics are
+// implemented by 'FPRepSem' above and specialized when needed.
+//
+// The 'RetT' type is being propagated up to 'FPRepSem' so that the functions
+// creating new values (Builders) can return the appropriate type. That is, when
+// creating a value through 'FPBits' below the builder will return an 'FPBits'
+// value.
+// FPBits<float>::zero(); // returns an FPBits<>
+//
+// When we don't care about specific C++ floating point type we can use
+// 'FPRep' and specify the 'FPType' directly.
+// FPRep<FPType::IEEE754_Binary32:>::zero() // returns an FPRep<>
+template <FPType fp_type, typename RetT>
+struct FPRepImpl : public FPRepSem<fp_type, RetT> {
+ using UP = FPRepSem<fp_type, RetT>;
+ using StorageType = typename UP::StorageType;
+
+protected:
+ using UP::bits;
+ using UP::encode;
+ using UP::exp_bits;
+ using UP::exp_sig_bits;
+
+ using typename UP::BiasedExponent;
+ using typename UP::Exponent;
+ using typename UP::Significand;
+
+ using UP::FP_MASK;
+
+public:
+ // Constants.
+ using UP::EXP_BIAS;
+ using UP::EXP_MASK;
+ using UP::FRACTION_MASK;
+ using UP::SIG_LEN;
+ using UP::SIG_MASK;
+ using UP::SIGN_MASK;
+ LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
+ (1 << UP::EXP_LEN) - 1;
+
+ // CTors
+ LIBC_INLINE constexpr FPRepImpl() = default;
+ LIBC_INLINE constexpr explicit FPRepImpl(StorageType x) : UP(x) {}
+
+ // Comparison
+ LIBC_INLINE constexpr friend bool operator==(FPRepImpl a, FPRepImpl b) {
+ return a.uintval() == b.uintval();
+ }
+ LIBC_INLINE constexpr friend bool operator!=(FPRepImpl a, FPRepImpl b) {
+ return a.uintval() != b.uintval();
+ }
+
+ // Representation
+ LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
+ LIBC_INLINE constexpr void set_uintval(StorageType value) {
+ bits = (value & FP_MASK);
+ }
+
+ // Builders
+ using UP::inf;
+ using UP::max_normal;
+ using UP::max_subnormal;
+ using UP::min_normal;
+ using UP::min_subnormal;
+ using UP::one;
+ using UP::quiet_nan;
+ using UP::signaling_nan;
+ using UP::zero;
+
+ // Modifiers
+ LIBC_INLINE constexpr RetT abs() const {
+ return RetT(static_cast<StorageType>(bits & UP::EXP_SIG_MASK));
+ }
+
+ // Observers
+ using UP::get_explicit_mantissa;
+ using UP::is_finite;
+ using UP::is_inf;
+ using UP::is_nan;
+ using UP::is_normal;
+ using UP::is_quiet_nan;
+ using UP::is_signaling_nan;
+ using UP::is_subnormal;
+ using UP::is_zero;
+ using UP::next_toward_inf;
+ using UP::sign;
+ LIBC_INLINE constexpr bool is_inf_or_nan() const { return !is_finite(); }
+ LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }
+ LIBC_INLINE constexpr bool is_pos() const { return sign().is_pos(); }
+
+ LIBC_INLINE constexpr uint16_t get_biased_exponent() const {
+ return static_cast<uint16_t>(static_cast<uint32_t>(UP::biased_exponent()));
+ }
+
+ LIBC_INLINE constexpr void set_biased_exponent(StorageType biased) {
+ UP::set_biased_exponent(BiasedExponent((int32_t)biased));
+ }
+
+ LIBC_INLINE constexpr int get_exponent() const {
+ return static_cast<int32_t>(Exponent(UP::biased_exponent()));
+ }
+
+ // If the number is subnormal, the exponent is treated as if it were the
+ // minimum exponent for a normal number. This is to keep continuity between
+ // the normal and subnormal ranges, but it causes problems for functions where
+ // values are calculated from the exponent, since just subtracting the bias
+ // will give a slightly incorrect result. Additionally, zero has an exponent
+ // of zero, and that should actually be treated as zero.
+ LIBC_INLINE constexpr int get_explicit_exponent() const {
+ Exponent exponent(UP::biased_exponent());
+ if (is_zero())
+ exponent = Exponent::zero();
+ if (exponent == Exponent::subnormal())
+ exponent = Exponent::min();
+ return static_cast<int32_t>(exponent);
+ }
+
+ LIBC_INLINE constexpr StorageType get_mantissa() const {
+ return bits & FRACTION_MASK;
+ }
+
+ LIBC_INLINE constexpr void set_mantissa(StorageType mantVal) {
+ bits = UP::merge(bits, mantVal, FRACTION_MASK);
+ }
+
+ LIBC_INLINE constexpr void set_significand(StorageType sigVal) {
+ bits = UP::merge(bits, sigVal, SIG_MASK);
+ }
+ // Unsafe function to create a floating point representation.
+ // It simply packs the sign, biased exponent and mantissa values without
+ // checking bound nor normalization.
+ //
+ // WARNING: For X86 Extended Precision, implicit bit needs to be set correctly
+ // in the 'mantissa' by the caller. This function will not check for its
+ // validity.
+ //
+ // FIXME: Use an uint32_t for 'biased_exp'.
+ LIBC_INLINE static constexpr RetT
+ create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
+ return RetT(encode(sign, BiasedExponent(static_cast<uint32_t>(biased_exp)),
+ Significand(mantissa)));
+ }
+
+ // The function converts integer number and unbiased exponent to proper
+ // float T type:
+ // Result = number * 2^(ep+1 - exponent_bias)
+ // Be careful!
+ // 1) "ep" is the raw exponent value.
+ // 2) The function adds +1 to ep for seamless normalized to denormalized
+ // transition.
+ // 3) The function does not check exponent high limit.
+ // 4) "number" zero value is not processed correctly.
+ // 5) Number is unsigned, so the result can be only positive.
+ LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) {
+ FPRepImpl result(0);
+ int lz =
+ UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number));
+
+ number <<= lz;
+ ep -= lz;
+
+ if (LIBC_LIKELY(ep >= 0)) {
+ // Implicit number bit will be removed by mask
+ result.set_significand(number);
+ result.set_biased_exponent(static_cast<StorageType>(ep + 1));
+ } else {
+ result.set_significand(number >> -ep);
+ }
+ return RetT(result.uintval());
+ }
+};
+
+// A generic class to manipulate floating point formats.
+// It derives its functionality to FPRepImpl above.
+template <FPType fp_type>
+struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> {
+ using UP = FPRepImpl<fp_type, FPRep<fp_type>>;
+ using StorageType = typename UP::StorageType;
+ using UP::UP;
+
+ LIBC_INLINE constexpr explicit operator StorageType() const {
+ return UP::uintval();
+ }
+};
+
+} // namespace internal
+
+// Returns the FPType corresponding to C++ type T on the host.
+template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
+ using UnqualT = cpp::remove_cv_t<T>;
+ if constexpr (cpp::is_same_v<UnqualT, float> && __FLT_MANT_DIG__ == 24)
+ return FPType::IEEE754_Binary32;
+ else if constexpr (cpp::is_same_v<UnqualT, double> && __DBL_MANT_DIG__ == 53)
+ return FPType::IEEE754_Binary64;
+ else if constexpr (cpp::is_same_v<UnqualT, long double>) {
+ if constexpr (__LDBL_MANT_DIG__ == 53)
+ return FPType::IEEE754_Binary64;
+ else if constexpr (__LDBL_MANT_DIG__ == 64)
+ return FPType::X86_Binary80;
+ else if constexpr (__LDBL_MANT_DIG__ == 113)
+ return FPType::IEEE754_Binary128;
+ }
+#if defined(LIBC_TYPES_HAS_FLOAT16)
+ else if constexpr (cpp::is_same_v<UnqualT, float16>)
+ return FPType::IEEE754_Binary16;
+#endif
+#if defined(LIBC_TYPES_HAS_FLOAT128)
+ else if constexpr (cpp::is_same_v<UnqualT, float128>)
+ return FPType::IEEE754_Binary128;
+#endif
+ else
+ static_assert(cpp::always_false<UnqualT>, "Unsupported type");
+}
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+// A generic class to manipulate C++ floating point formats.
+// It derives its functionality to FPRepImpl above.
+template <typename T>
+struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> {
+ static_assert(cpp::is_floating_point_v<T>,
+ "FPBits instantiated with invalid type.");
+ using UP = internal::FPRepImpl<get_fp_type<T>(), FPBits<T>>;
+ using StorageType = typename UP::StorageType;
+
+ // Constructors.
+ LIBC_INLINE constexpr FPBits() = default;
+
+ template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
+ using Unqual = typename cpp::remove_cv_t<XType>;
+ if constexpr (cpp::is_same_v<Unqual, T>) {
+ UP::bits = cpp::bit_cast<StorageType>(x);
+ } else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
+ UP::bits = x;
+ } else {
+ // We don't want accidental type promotions/conversions, so we require
+ // exact type match.
+ static_assert(cpp::always_false<XType>);
+ }
+ }
+
+ // Floating-point conversions.
+ LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); }
+};
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
diff --git a/lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h b/lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h
new file mode 100644
index 0000000000..bc66d09b94
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h
@@ -0,0 +1,81 @@
+//===---- Free-standing function to detect rounding mode --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
+
+#include "hdr/fenv_macros.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+// Quick free-standing test whether fegetround() == FE_UPWARD.
+// Using the following observation:
+// 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
+// = 0x1.000002f for FE_UPWARD.
+LIBC_INLINE bool fenv_is_round_up() {
+ volatile float x = 0x1.0p-25f;
+ return (1.0f + x != 1.0f);
+}
+
+// Quick free-standing test whether fegetround() == FE_DOWNWARD.
+// Using the following observation:
+// -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
+// = -0x1.000002f for FE_DOWNWARD.
+LIBC_INLINE bool fenv_is_round_down() {
+ volatile float x = 0x1.0p-25f;
+ return (-1.0f - x != -1.0f);
+}
+
+// Quick free-standing test whether fegetround() == FE_TONEAREST.
+// Using the following observation:
+// 1.5f + 2^-24 = 1.5f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
+// = 0x1.100002p0f for FE_UPWARD,
+// 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD
+// = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
+LIBC_INLINE bool fenv_is_round_to_nearest() {
+ static volatile float x = 0x1.0p-24f;
+ float y = x;
+ return (1.5f + y == 1.5f - y);
+}
+
+// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
+// Using the following observation:
+// 1.0f + 2^-23 + 2^-24 = 0x1.000002p0f for FE_DOWNWARD, FE_TOWARDZERO
+// = 0x1.000004p0f for FE_TONEAREST, FE_UPWARD,
+// -1.0f - 2^-24 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
+// = -0x1.000002p0f for FE_DOWNWARD
+// So:
+// (0x1.000002p0f + 2^-24) + (-1.0f - 2^-24) = 2^-23 for FE_TOWARDZERO
+// = 2^-22 for FE_TONEAREST, FE_UPWARD
+// = 0 for FE_DOWNWARD
+LIBC_INLINE bool fenv_is_round_to_zero() {
+ static volatile float x = 0x1.0p-24f;
+ float y = x;
+ return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
+}
+
+// Quick free standing get rounding mode based on the above observations.
+LIBC_INLINE int quick_get_round() {
+ static volatile float x = 0x1.0p-24f;
+ float y = x;
+ float z = (0x1.000002p0f + y) + (-1.0f - y);
+
+ if (z == 0.0f)
+ return FE_DOWNWARD;
+ if (z == 0x1.0p-23f)
+ return FE_TOWARDZERO;
+ return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+}
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
diff --git a/lib/libcxx/libc/src/__support/big_int.h b/lib/libcxx/libc/src/__support/big_int.h
new file mode 100644
index 0000000000..a95ab4ff8e
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/big_int.h
@@ -0,0 +1,1384 @@
+//===-- A class to manipulate wide integers. --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
+#define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
+
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/bit.h" // countl_zero
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128, LIBC_TYPES_HAS_INT64
+#include "src/__support/math_extras.h" // add_with_carry, sub_with_borrow
+#include "src/__support/number_pair.h"
+
+#include <stddef.h> // For size_t
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace multiword {
+
+// A type trait mapping unsigned integers to their half-width unsigned
+// counterparts.
+template <typename T> struct half_width;
+template <> struct half_width<uint16_t> : cpp::type_identity<uint8_t> {};
+template <> struct half_width<uint32_t> : cpp::type_identity<uint16_t> {};
+#ifdef LIBC_TYPES_HAS_INT64
+template <> struct half_width<uint64_t> : cpp::type_identity<uint32_t> {};
+#ifdef LIBC_TYPES_HAS_INT128
+template <> struct half_width<__uint128_t> : cpp::type_identity<uint64_t> {};
+#endif // LIBC_TYPES_HAS_INT128
+#endif // LIBC_TYPES_HAS_INT64
+template <typename T> using half_width_t = typename half_width<T>::type;
+
+// An array of two elements that can be used in multiword operations.
+template <typename T> struct DoubleWide final : cpp::array<T, 2> {
+ using UP = cpp::array<T, 2>;
+ using UP::UP;
+ LIBC_INLINE constexpr DoubleWide(T lo, T hi) : UP({lo, hi}) {}
+};
+
+// Converts an unsigned value into a DoubleWide<half_width_t<T>>.
+template <typename T> LIBC_INLINE constexpr auto split(T value) {
+ static_assert(cpp::is_unsigned_v<T>);
+ using half_type = half_width_t<T>;
+ return DoubleWide<half_type>(
+ half_type(value),
+ half_type(value >> cpp::numeric_limits<half_type>::digits));
+}
+
+// The low part of a DoubleWide value.
+template <typename T> LIBC_INLINE constexpr T lo(const DoubleWide<T> &value) {
+ return value[0];
+}
+// The high part of a DoubleWide value.
+template <typename T> LIBC_INLINE constexpr T hi(const DoubleWide<T> &value) {
+ return value[1];
+}
+// The low part of an unsigned value.
+template <typename T> LIBC_INLINE constexpr half_width_t<T> lo(T value) {
+ return lo(split(value));
+}
+// The high part of an unsigned value.
+template <typename T> LIBC_INLINE constexpr half_width_t<T> hi(T value) {
+ return hi(split(value));
+}
+
+// Returns 'a' times 'b' in a DoubleWide<word>. Cannot overflow by construction.
+template <typename word>
+LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) {
+ if constexpr (cpp::is_same_v<word, uint8_t>) {
+ return split<uint16_t>(uint16_t(a) * uint16_t(b));
+ } else if constexpr (cpp::is_same_v<word, uint16_t>) {
+ return split<uint32_t>(uint32_t(a) * uint32_t(b));
+ }
+#ifdef LIBC_TYPES_HAS_INT64
+ else if constexpr (cpp::is_same_v<word, uint32_t>) {
+ return split<uint64_t>(uint64_t(a) * uint64_t(b));
+ }
+#endif
+#ifdef LIBC_TYPES_HAS_INT128
+ else if constexpr (cpp::is_same_v<word, uint64_t>) {
+ return split<__uint128_t>(__uint128_t(a) * __uint128_t(b));
+ }
+#endif
+ else {
+ using half_word = half_width_t<word>;
+ const auto shiftl = [](word value) -> word {
+ return value << cpp::numeric_limits<half_word>::digits;
+ };
+ const auto shiftr = [](word value) -> word {
+ return value >> cpp::numeric_limits<half_word>::digits;
+ };
+ // Here we do a one digit multiplication where 'a' and 'b' are of type
+ // word. We split 'a' and 'b' into half words and perform the classic long
+ // multiplication with 'a' and 'b' being two-digit numbers.
+
+ // a a_hi a_lo
+ // x b => x b_hi b_lo
+ // ---- -----------
+ // c result
+ // We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication
+ // doesn't overflow.
+ const word a_lo = lo(a);
+ const word b_lo = lo(b);
+ const word a_hi = hi(a);
+ const word b_hi = hi(b);
+ const word step1 = b_lo * a_lo; // no overflow;
+ const word step2 = b_lo * a_hi; // no overflow;
+ const word step3 = b_hi * a_lo; // no overflow;
+ const word step4 = b_hi * a_hi; // no overflow;
+ word lo_digit = step1;
+ word hi_digit = step4;
+ const word no_carry = 0;
+ word carry;
+ word _; // unused carry variable.
+ lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry);
+ hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _);
+ lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry);
+ hi_digit = add_with_carry<word>(hi_digit, shiftr(step3), carry, _);
+ return DoubleWide<word>(lo_digit, hi_digit);
+ }
+}
+
+// In-place 'dst op= rhs' with operation with carry propagation. Returns carry.
+template <typename Function, typename word, size_t N, size_t M>
+LIBC_INLINE constexpr word inplace_binop(Function op_with_carry,
+ cpp::array<word, N> &dst,
+ const cpp::array<word, M> &rhs) {
+ static_assert(N >= M);
+ word carry_out = 0;
+ for (size_t i = 0; i < N; ++i) {
+ const bool has_rhs_value = i < M;
+ const word rhs_value = has_rhs_value ? rhs[i] : 0;
+ const word carry_in = carry_out;
+ dst[i] = op_with_carry(dst[i], rhs_value, carry_in, carry_out);
+ // stop early when rhs is over and no carry is to be propagated.
+ if (!has_rhs_value && carry_out == 0)
+ break;
+ }
+ return carry_out;
+}
+
+// In-place addition. Returns carry.
+template <typename word, size_t N, size_t M>
+LIBC_INLINE constexpr word add_with_carry(cpp::array<word, N> &dst,
+ const cpp::array<word, M> &rhs) {
+ return inplace_binop(LIBC_NAMESPACE::add_with_carry<word>, dst, rhs);
+}
+
+// In-place subtraction. Returns borrow.
+template <typename word, size_t N, size_t M>
+LIBC_INLINE constexpr word sub_with_borrow(cpp::array<word, N> &dst,
+ const cpp::array<word, M> &rhs) {
+ return inplace_binop(LIBC_NAMESPACE::sub_with_borrow<word>, dst, rhs);
+}
+
+// In-place multiply-add. Returns carry.
+// i.e., 'dst += b * c'
+template <typename word, size_t N>
+LIBC_INLINE constexpr word mul_add_with_carry(cpp::array<word, N> &dst, word b,
+ word c) {
+ return add_with_carry(dst, mul2(b, c));
+}
+
+// An array of two elements serving as an accumulator during multiword
+// computations.
+template <typename T> struct Accumulator final : cpp::array<T, 2> {
+ using UP = cpp::array<T, 2>;
+ LIBC_INLINE constexpr Accumulator() : UP({0, 0}) {}
+ LIBC_INLINE constexpr T advance(T carry_in) {
+ auto result = UP::front();
+ UP::front() = UP::back();
+ UP::back() = carry_in;
+ return result;
+ }
+ LIBC_INLINE constexpr T sum() const { return UP::front(); }
+ LIBC_INLINE constexpr T carry() const { return UP::back(); }
+};
+
+// In-place multiplication by a single word. Returns carry.
+template <typename word, size_t N>
+LIBC_INLINE constexpr word scalar_multiply_with_carry(cpp::array<word, N> &dst,
+ word x) {
+ Accumulator<word> acc;
+ for (auto &val : dst) {
+ const word carry = mul_add_with_carry(acc, val, x);
+ val = acc.advance(carry);
+ }
+ return acc.carry();
+}
+
+// Multiplication of 'lhs' by 'rhs' into 'dst'. Returns carry.
+// This function is safe to use for signed numbers.
+// https://stackoverflow.com/a/20793834
+// https://pages.cs.wisc.edu/%7Emarkhill/cs354/Fall2008/beyond354/int.mult.html
+template <typename word, size_t O, size_t M, size_t N>
+LIBC_INLINE constexpr word multiply_with_carry(cpp::array<word, O> &dst,
+ const cpp::array<word, M> &lhs,
+ const cpp::array<word, N> &rhs) {
+ static_assert(O >= M + N);
+ Accumulator<word> acc;
+ for (size_t i = 0; i < O; ++i) {
+ const size_t lower_idx = i < N ? 0 : i - N + 1;
+ const size_t upper_idx = i < M ? i : M - 1;
+ word carry = 0;
+ for (size_t j = lower_idx; j <= upper_idx; ++j)
+ carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);
+ dst[i] = acc.advance(carry);
+ }
+ return acc.carry();
+}
+
+template <typename word, size_t N>
+LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
+ const cpp::array<word, N> &lhs,
+ const cpp::array<word, N> &rhs) {
+ Accumulator<word> acc;
+ word carry = 0;
+ // First round of accumulation for those at N - 1 in the full product.
+ for (size_t i = 0; i < N; ++i)
+ carry += mul_add_with_carry(acc, lhs[i], rhs[N - 1 - i]);
+ for (size_t i = N; i < 2 * N - 1; ++i) {
+ acc.advance(carry);
+ carry = 0;
+ for (size_t j = i - N + 1; j < N; ++j)
+ carry += mul_add_with_carry(acc, lhs[j], rhs[i - j]);
+ dst[i - N] = acc.sum();
+ }
+ dst.back() = acc.carry();
+}
+
+template <typename word, size_t N>
+LIBC_INLINE constexpr bool is_negative(cpp::array<word, N> &array) {
+ using signed_word = cpp::make_signed_t<word>;
+ return cpp::bit_cast<signed_word>(array.back()) < 0;
+}
+
+// An enum for the shift function below.
+enum Direction { LEFT, RIGHT };
+
+// A bitwise shift on an array of elements.
+// 'offset' must be less than TOTAL_BITS (i.e., sizeof(word) * CHAR_BIT * N)
+// otherwise the behavior is undefined.
+template <Direction direction, bool is_signed, typename word, size_t N>
+LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
+ size_t offset) {
+ static_assert(direction == LEFT || direction == RIGHT);
+ constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
+#ifdef LIBC_TYPES_HAS_INT128
+ constexpr size_t TOTAL_BITS = N * WORD_BITS;
+ if constexpr (TOTAL_BITS == 128) {
+ using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>;
+ auto tmp = cpp::bit_cast<type>(array);
+ if constexpr (direction == LEFT)
+ tmp <<= offset;
+ else
+ tmp >>= offset;
+ return cpp::bit_cast<cpp::array<word, N>>(tmp);
+ }
+#endif
+ if (LIBC_UNLIKELY(offset == 0))
+ return array;
+ const bool is_neg = is_signed && is_negative(array);
+ constexpr auto at = [](size_t index) -> int {
+ // reverse iteration when direction == LEFT.
+ if constexpr (direction == LEFT)
+ return int(N) - int(index) - 1;
+ return int(index);
+ };
+ const auto safe_get_at = [&](size_t index) -> word {
+ // return appropriate value when accessing out of bound elements.
+ const int i = at(index);
+ if (i < 0)
+ return 0;
+ if (i >= int(N))
+ return is_neg ? -1 : 0;
+ return array[i];
+ };
+ const size_t index_offset = offset / WORD_BITS;
+ const size_t bit_offset = offset % WORD_BITS;
+#ifdef LIBC_COMPILER_IS_CLANG
+ __builtin_assume(index_offset < N);
+#endif
+ cpp::array<word, N> out = {};
+ for (size_t index = 0; index < N; ++index) {
+ const word part1 = safe_get_at(index + index_offset);
+ const word part2 = safe_get_at(index + index_offset + 1);
+ word &dst = out[at(index)];
+ if (bit_offset == 0)
+ dst = part1; // no crosstalk between parts.
+ else if constexpr (direction == LEFT)
+ dst = static_cast<word>((part1 << bit_offset) |
+ (part2 >> (WORD_BITS - bit_offset)));
+ else
+ dst = static_cast<word>((part1 >> bit_offset) |
+ (part2 << (WORD_BITS - bit_offset)));
+ }
+ return out;
+}
+
+#define DECLARE_COUNTBIT(NAME, INDEX_EXPR) \
+ template <typename word, size_t N> \
+ LIBC_INLINE constexpr int NAME(const cpp::array<word, N> &val) { \
+ int bit_count = 0; \
+ for (size_t i = 0; i < N; ++i) { \
+ const int word_count = cpp::NAME<word>(val[INDEX_EXPR]); \
+ bit_count += word_count; \
+ if (word_count != cpp::numeric_limits<word>::digits) \
+ break; \
+ } \
+ return bit_count; \
+ }
+
+DECLARE_COUNTBIT(countr_zero, i) // iterating forward
+DECLARE_COUNTBIT(countr_one, i) // iterating forward
+DECLARE_COUNTBIT(countl_zero, N - i - 1) // iterating backward
+DECLARE_COUNTBIT(countl_one, N - i - 1) // iterating backward
+
+} // namespace multiword
+
+template <size_t Bits, bool Signed, typename WordType = uint64_t>
+struct BigInt {
+private:
+ static_assert(cpp::is_integral_v<WordType> && cpp::is_unsigned_v<WordType>,
+ "WordType must be unsigned integer.");
+
+ struct Division {
+ BigInt quotient;
+ BigInt remainder;
+ };
+
+public:
+ using word_type = WordType;
+ using unsigned_type = BigInt<Bits, false, word_type>;
+ using signed_type = BigInt<Bits, true, word_type>;
+
+ LIBC_INLINE_VAR static constexpr bool SIGNED = Signed;
+ LIBC_INLINE_VAR static constexpr size_t BITS = Bits;
+ LIBC_INLINE_VAR
+ static constexpr size_t WORD_SIZE = sizeof(WordType) * CHAR_BIT;
+
+ static_assert(Bits > 0 && Bits % WORD_SIZE == 0,
+ "Number of bits in BigInt should be a multiple of WORD_SIZE.");
+
+ LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE;
+
+ cpp::array<WordType, WORD_COUNT> val{}; // zero initialized.
+
+ LIBC_INLINE constexpr BigInt() = default;
+
+ LIBC_INLINE constexpr BigInt(const BigInt &other) = default;
+
+ template <size_t OtherBits, bool OtherSigned, typename OtherWordType>
+ LIBC_INLINE constexpr BigInt(
+ const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {
+ using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;
+ const bool should_sign_extend = Signed && other.is_neg();
+
+ static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&
+ "This is currently untested for casting between bigints with "
+ "the same bit width but different word sizes.");
+
+ if constexpr (BigIntOther::WORD_SIZE < WORD_SIZE) {
+ // OtherWordType is smaller
+ constexpr size_t WORD_SIZE_RATIO = WORD_SIZE / BigIntOther::WORD_SIZE;
+ static_assert(
+ (WORD_SIZE % BigIntOther::WORD_SIZE) == 0 &&
+ "Word types must be multiples of each other for correct conversion.");
+ if constexpr (OtherBits >= Bits) { // truncate
+ // for each big word
+ for (size_t i = 0; i < WORD_COUNT; ++i) {
+ WordType cur_word = 0;
+ // combine WORD_SIZE_RATIO small words into a big word
+ for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)
+ cur_word |= static_cast<WordType>(other[(i * WORD_SIZE_RATIO) + j])
+ << (BigIntOther::WORD_SIZE * j);
+
+ val[i] = cur_word;
+ }
+ } else { // zero or sign extend
+ size_t i = 0;
+ WordType cur_word = 0;
+ // for each small word
+ for (; i < BigIntOther::WORD_COUNT; ++i) {
+ // combine WORD_SIZE_RATIO small words into a big word
+ cur_word |= static_cast<WordType>(other[i])
+ << (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));
+ // if we've completed a big word, copy it into place and reset
+ if ((i % WORD_SIZE_RATIO) == WORD_SIZE_RATIO - 1) {
+ val[i / WORD_SIZE_RATIO] = cur_word;
+ cur_word = 0;
+ }
+ }
+ // Pretend there are extra words of the correct sign extension as needed
+
+ const WordType extension_bits =
+ should_sign_extend ? cpp::numeric_limits<WordType>::max()
+ : cpp::numeric_limits<WordType>::min();
+ if ((i % WORD_SIZE_RATIO) != 0) {
+ cur_word |= static_cast<WordType>(extension_bits)
+ << (BigIntOther::WORD_SIZE * (i % WORD_SIZE_RATIO));
+ }
+ // Copy the last word into place.
+ val[(i / WORD_SIZE_RATIO)] = cur_word;
+ extend((i / WORD_SIZE_RATIO) + 1, should_sign_extend);
+ }
+ } else if constexpr (BigIntOther::WORD_SIZE == WORD_SIZE) {
+ if constexpr (OtherBits >= Bits) { // truncate
+ for (size_t i = 0; i < WORD_COUNT; ++i)
+ val[i] = other[i];
+ } else { // zero or sign extend
+ size_t i = 0;
+ for (; i < BigIntOther::WORD_COUNT; ++i)
+ val[i] = other[i];
+ extend(i, should_sign_extend);
+ }
+ } else {
+ // OtherWordType is bigger.
+ constexpr size_t WORD_SIZE_RATIO = BigIntOther::WORD_SIZE / WORD_SIZE;
+ static_assert(
+ (BigIntOther::WORD_SIZE % WORD_SIZE) == 0 &&
+ "Word types must be multiples of each other for correct conversion.");
+ if constexpr (OtherBits >= Bits) { // truncate
+ // for each small word
+ for (size_t i = 0; i < WORD_COUNT; ++i) {
+ // split each big word into WORD_SIZE_RATIO small words
+ val[i] = static_cast<WordType>(other[i / WORD_SIZE_RATIO] >>
+ ((i % WORD_SIZE_RATIO) * WORD_SIZE));
+ }
+ } else { // zero or sign extend
+ size_t i = 0;
+ // for each big word
+ for (; i < BigIntOther::WORD_COUNT; ++i) {
+ // split each big word into WORD_SIZE_RATIO small words
+ for (size_t j = 0; j < WORD_SIZE_RATIO; ++j)
+ val[(i * WORD_SIZE_RATIO) + j] =
+ static_cast<WordType>(other[i] >> (j * WORD_SIZE));
+ }
+ extend(i * WORD_SIZE_RATIO, should_sign_extend);
+ }
+ }
+ }
+
+ // Construct a BigInt from a C array.
+ template <size_t N> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) {
+ static_assert(N == WORD_COUNT);
+ for (size_t i = 0; i < WORD_COUNT; ++i)
+ val[i] = nums[i];
+ }
+
+ LIBC_INLINE constexpr explicit BigInt(
+ const cpp::array<WordType, WORD_COUNT> &words) {
+ val = words;
+ }
+
+ // Initialize the first word to |v| and the rest to 0.
+ template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
+ !cpp::is_same_v<T, bool>>>
+ LIBC_INLINE constexpr BigInt(T v) {
+ constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
+ const bool is_neg = v < 0;
+ for (size_t i = 0; i < WORD_COUNT; ++i) {
+ if (v == 0) {
+ extend(i, is_neg);
+ return;
+ }
+ val[i] = static_cast<WordType>(v);
+ if constexpr (T_SIZE > WORD_SIZE)
+ v >>= WORD_SIZE;
+ else
+ v = 0;
+ }
+ }
+ LIBC_INLINE constexpr BigInt &operator=(const BigInt &other) = default;
+
+ // constants
+ LIBC_INLINE static constexpr BigInt zero() { return BigInt(); }
+ LIBC_INLINE static constexpr BigInt one() { return BigInt(1); }
+ LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); }
+ LIBC_INLINE static constexpr BigInt min() {
+ BigInt out;
+ if constexpr (SIGNED)
+ out.set_msb();
+ return out;
+ }
+ LIBC_INLINE static constexpr BigInt max() {
+ BigInt out = all_ones();
+ if constexpr (SIGNED)
+ out.clear_msb();
+ return out;
+ }
+
+ // TODO: Reuse the Sign type.
+ LIBC_INLINE constexpr bool is_neg() const { return SIGNED && get_msb(); }
+
+ template <size_t OtherBits, bool OtherSigned, typename OtherWordType>
+ LIBC_INLINE constexpr explicit
+ operator BigInt<OtherBits, OtherSigned, OtherWordType>() const {
+ return BigInt<OtherBits, OtherSigned, OtherWordType>(this);
+ }
+
+ template <typename T> LIBC_INLINE constexpr explicit operator T() const {
+ return to<T>();
+ }
+
+ template <typename T>
+ LIBC_INLINE constexpr cpp::enable_if_t<
+ cpp::is_integral_v<T> && !cpp::is_same_v<T, bool>, T>
+ to() const {
+ constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
+ T lo = static_cast<T>(val[0]);
+ if constexpr (T_SIZE <= WORD_SIZE)
+ return lo;
+ constexpr size_t MAX_COUNT =
+ T_SIZE > Bits ? WORD_COUNT : T_SIZE / WORD_SIZE;
+ for (size_t i = 1; i < MAX_COUNT; ++i)
+ lo += static_cast<T>(static_cast<T>(val[i]) << (WORD_SIZE * i));
+ if constexpr (Signed && (T_SIZE > Bits)) {
+ // Extend sign for negative numbers.
+ constexpr T MASK = (~T(0) << Bits);
+ if (is_neg())
+ lo |= MASK;
+ }
+ return lo;
+ }
+
+ LIBC_INLINE constexpr explicit operator bool() const { return !is_zero(); }
+
+ LIBC_INLINE constexpr bool is_zero() const {
+ for (auto part : val)
+ if (part != 0)
+ return false;
+ return true;
+ }
+
+ // Add 'rhs' to this number and store the result in this number.
+ // Returns the carry value produced by the addition operation.
+ LIBC_INLINE constexpr WordType add_overflow(const BigInt &rhs) {
+ return multiword::add_with_carry(val, rhs.val);
+ }
+
+ LIBC_INLINE constexpr BigInt operator+(const BigInt &other) const {
+ BigInt result = *this;
+ result.add_overflow(other);
+ return result;
+ }
+
+ // This will only apply when initializing a variable from constant values, so
+ // it will always use the constexpr version of add_with_carry.
+ LIBC_INLINE constexpr BigInt operator+(BigInt &&other) const {
+ // We use addition commutativity to reuse 'other' and prevent allocation.
+ other.add_overflow(*this); // Returned carry value is ignored.
+ return other;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator+=(const BigInt &other) {
+ add_overflow(other); // Returned carry value is ignored.
+ return *this;
+ }
+
+ // Subtract 'rhs' to this number and store the result in this number.
+ // Returns the carry value produced by the subtraction operation.
+ LIBC_INLINE constexpr WordType sub_overflow(const BigInt &rhs) {
+ return multiword::sub_with_borrow(val, rhs.val);
+ }
+
+ LIBC_INLINE constexpr BigInt operator-(const BigInt &other) const {
+ BigInt result = *this;
+ result.sub_overflow(other); // Returned carry value is ignored.
+ return result;
+ }
+
+ LIBC_INLINE constexpr BigInt operator-(BigInt &&other) const {
+ BigInt result = *this;
+ result.sub_overflow(other); // Returned carry value is ignored.
+ return result;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator-=(const BigInt &other) {
+ // TODO(lntue): Set overflow flag / errno when carry is true.
+ sub_overflow(other); // Returned carry value is ignored.
+ return *this;
+ }
+
+ // Multiply this number with x and store the result in this number.
+ LIBC_INLINE constexpr WordType mul(WordType x) {
+ return multiword::scalar_multiply_with_carry(val, x);
+ }
+
+ // Return the full product.
+ template <size_t OtherBits>
+ LIBC_INLINE constexpr auto
+ ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const {
+ BigInt<Bits + OtherBits, Signed, WordType> result;
+ multiword::multiply_with_carry(result.val, val, other.val);
+ return result;
+ }
+
+ LIBC_INLINE constexpr BigInt operator*(const BigInt &other) const {
+ // Perform full mul and truncate.
+ return BigInt(ful_mul(other));
+ }
+
+ // Fast hi part of the full product. The normal product `operator*` returns
+ // `Bits` least significant bits of the full product, while this function will
+ // approximate `Bits` most significant bits of the full product with errors
+ // bounded by:
+ // 0 <= (a.full_mul(b) >> Bits) - a.quick_mul_hi(b)) <= WORD_COUNT - 1.
+ //
+ // An example usage of this is to quickly (but less accurately) compute the
+ // product of (normalized) mantissas of floating point numbers:
+ // (mant_1, mant_2) -> quick_mul_hi -> normalize leading bit
+ // is much more efficient than:
+ // (mant_1, mant_2) -> ful_mul -> normalize leading bit
+ // -> convert back to same Bits width by shifting/rounding,
+ // especially for higher precisions.
+ //
+ // Performance summary:
+ // Number of 64-bit x 64-bit -> 128-bit multiplications performed.
+ // Bits WORD_COUNT ful_mul quick_mul_hi Error bound
+ // 128 2 4 3 1
+ // 196 3 9 6 2
+ // 256 4 16 10 3
+ // 512 8 64 36 7
+ LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const {
+ BigInt result;
+ multiword::quick_mul_hi(result.val, val, other.val);
+ return result;
+ }
+
+ // BigInt(x).pow_n(n) computes x ^ n.
+ // Note 0 ^ 0 == 1.
+ LIBC_INLINE constexpr void pow_n(uint64_t power) {
+ static_assert(!Signed);
+ BigInt result = one();
+ BigInt cur_power = *this;
+ while (power > 0) {
+ if ((power % 2) > 0)
+ result *= cur_power;
+ power >>= 1;
+ cur_power *= cur_power;
+ }
+ *this = result;
+ }
+
+ // Performs inplace signed / unsigned division. Returns remainder if not
+ // dividing by zero.
+ // For signed numbers it behaves like C++ signed integer division.
+ // That is by truncating the fractionnal part
+ // https://stackoverflow.com/a/3602857
+ LIBC_INLINE constexpr cpp::optional<BigInt> div(const BigInt &divider) {
+ if (LIBC_UNLIKELY(divider.is_zero()))
+ return cpp::nullopt;
+ if (LIBC_UNLIKELY(divider == BigInt::one()))
+ return BigInt::zero();
+ Division result;
+ if constexpr (SIGNED)
+ result = divide_signed(*this, divider);
+ else
+ result = divide_unsigned(*this, divider);
+ *this = result.quotient;
+ return result.remainder;
+ }
+
+ // Efficiently perform BigInt / (x * 2^e), where x is a half-word-size
+ // unsigned integer, and return the remainder. The main idea is as follow:
+ // Let q = y / (x * 2^e) be the quotient, and
+ // r = y % (x * 2^e) be the remainder.
+ // First, notice that:
+ // r % (2^e) = y % (2^e),
+ // so we just need to focus on all the bits of y that is >= 2^e.
+ // To speed up the shift-and-add steps, we only use x as the divisor, and
+ // performing 32-bit shiftings instead of bit-by-bit shiftings.
+ // Since the remainder of each division step < x < 2^(WORD_SIZE / 2), the
+ // computation of each step is now properly contained within WordType.
+ // And finally we perform some extra alignment steps for the remaining bits.
+ LIBC_INLINE constexpr cpp::optional<BigInt>
+ div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) {
+ BigInt remainder;
+ if (x == 0)
+ return cpp::nullopt;
+ if (e >= Bits) {
+ remainder = *this;
+ *this = BigInt<Bits, false, WordType>();
+ return remainder;
+ }
+ BigInt quotient;
+ WordType x_word = static_cast<WordType>(x);
+ constexpr size_t LOG2_WORD_SIZE = cpp::bit_width(WORD_SIZE) - 1;
+ constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;
+ constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);
+ // lower = smallest multiple of WORD_SIZE that is >= e.
+ size_t lower = ((e >> LOG2_WORD_SIZE) + ((e & (WORD_SIZE - 1)) != 0))
+ << LOG2_WORD_SIZE;
+ // lower_pos is the index of the closest WORD_SIZE-bit chunk >= 2^e.
+ size_t lower_pos = lower / WORD_SIZE;
+ // Keep track of current remainder mod x * 2^(32*i)
+ WordType rem = 0;
+ // pos is the index of the current 64-bit chunk that we are processing.
+ size_t pos = WORD_COUNT;
+
+ // TODO: look into if constexpr(Bits > 256) skip leading zeroes.
+
+ for (size_t q_pos = WORD_COUNT - lower_pos; q_pos > 0; --q_pos) {
+ // q_pos is 1 + the index of the current WORD_SIZE-bit chunk of the
+ // quotient being processed. Performing the division / modulus with
+ // divisor:
+ // x * 2^(WORD_SIZE*q_pos - WORD_SIZE/2),
+ // i.e. using the upper (WORD_SIZE/2)-bit of the current WORD_SIZE-bit
+ // chunk.
+ rem <<= HALF_WORD_SIZE;
+ rem += val[--pos] >> HALF_WORD_SIZE;
+ WordType q_tmp = rem / x_word;
+ rem %= x_word;
+
+ // Performing the division / modulus with divisor:
+ // x * 2^(WORD_SIZE*(q_pos - 1)),
+ // i.e. using the lower (WORD_SIZE/2)-bit of the current WORD_SIZE-bit
+ // chunk.
+ rem <<= HALF_WORD_SIZE;
+ rem += val[pos] & HALF_MASK;
+ quotient.val[q_pos - 1] = (q_tmp << HALF_WORD_SIZE) + rem / x_word;
+ rem %= x_word;
+ }
+
+ // So far, what we have is:
+ // quotient = y / (x * 2^lower), and
+ // rem = (y % (x * 2^lower)) / 2^lower.
+ // If (lower > e), we will need to perform an extra adjustment of the
+ // quotient and remainder, namely:
+ // y / (x * 2^e) = [ y / (x * 2^lower) ] * 2^(lower - e) +
+ // + (rem * 2^(lower - e)) / x
+ // (y % (x * 2^e)) / 2^e = (rem * 2^(lower - e)) % x
+ size_t last_shift = lower - e;
+
+ if (last_shift > 0) {
+ // quotient * 2^(lower - e)
+ quotient <<= last_shift;
+ WordType q_tmp = 0;
+ WordType d = val[--pos];
+ if (last_shift >= HALF_WORD_SIZE) {
+ // The shifting (rem * 2^(lower - e)) might overflow WordTyoe, so we
+ // perform a HALF_WORD_SIZE-bit shift first.
+ rem <<= HALF_WORD_SIZE;
+ rem += d >> HALF_WORD_SIZE;
+ d &= HALF_MASK;
+ q_tmp = rem / x_word;
+ rem %= x_word;
+ last_shift -= HALF_WORD_SIZE;
+ } else {
+ // Only use the upper HALF_WORD_SIZE-bit of the current WORD_SIZE-bit
+ // chunk.
+ d >>= HALF_WORD_SIZE;
+ }
+
+ if (last_shift > 0) {
+ rem <<= HALF_WORD_SIZE;
+ rem += d;
+ q_tmp <<= last_shift;
+ x_word <<= HALF_WORD_SIZE - last_shift;
+ q_tmp += rem / x_word;
+ rem %= x_word;
+ }
+
+ quotient.val[0] += q_tmp;
+
+ if (lower - e <= HALF_WORD_SIZE) {
+ // The remainder rem * 2^(lower - e) might overflow to the higher
+ // WORD_SIZE-bit chunk.
+ if (pos < WORD_COUNT - 1) {
+ remainder[pos + 1] = rem >> HALF_WORD_SIZE;
+ }
+ remainder[pos] = (rem << HALF_WORD_SIZE) + (val[pos] & HALF_MASK);
+ } else {
+ remainder[pos] = rem;
+ }
+
+ } else {
+ remainder[pos] = rem;
+ }
+
+ // Set the remaining lower bits of the remainder.
+ for (; pos > 0; --pos) {
+ remainder[pos - 1] = val[pos - 1];
+ }
+
+ *this = quotient;
+ return remainder;
+ }
+
+ LIBC_INLINE constexpr BigInt operator/(const BigInt &other) const {
+ BigInt result(*this);
+ result.div(other);
+ return result;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator/=(const BigInt &other) {
+ div(other);
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt operator%(const BigInt &other) const {
+ BigInt result(*this);
+ return *result.div(other);
+ }
+
+ LIBC_INLINE constexpr BigInt operator%=(const BigInt &other) {
+ *this = *this % other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator*=(const BigInt &other) {
+ *this = *this * other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator<<=(size_t s) {
+ val = multiword::shift<multiword::LEFT, SIGNED>(val, s);
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt operator<<(size_t s) const {
+ return BigInt(multiword::shift<multiword::LEFT, SIGNED>(val, s));
+ }
+
+ LIBC_INLINE constexpr BigInt &operator>>=(size_t s) {
+ val = multiword::shift<multiword::RIGHT, SIGNED>(val, s);
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt operator>>(size_t s) const {
+ return BigInt(multiword::shift<multiword::RIGHT, SIGNED>(val, s));
+ }
+
+#define DEFINE_BINOP(OP) \
+ LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \
+ const BigInt &rhs) { \
+ BigInt result; \
+ for (size_t i = 0; i < WORD_COUNT; ++i) \
+ result[i] = lhs[i] OP rhs[i]; \
+ return result; \
+ } \
+ LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \
+ const BigInt &rhs) { \
+ for (size_t i = 0; i < WORD_COUNT; ++i) \
+ lhs[i] OP## = rhs[i]; \
+ return lhs; \
+ }
+
+ DEFINE_BINOP(&) // & and &=
+ DEFINE_BINOP(|) // | and |=
+ DEFINE_BINOP(^) // ^ and ^=
+#undef DEFINE_BINOP
+
+ LIBC_INLINE constexpr BigInt operator~() const {
+ BigInt result;
+ for (size_t i = 0; i < WORD_COUNT; ++i)
+ result[i] = ~val[i];
+ return result;
+ }
+
+ LIBC_INLINE constexpr BigInt operator-() const {
+ BigInt result(*this);
+ result.negate();
+ return result;
+ }
+
+ LIBC_INLINE friend constexpr bool operator==(const BigInt &lhs,
+ const BigInt &rhs) {
+ for (size_t i = 0; i < WORD_COUNT; ++i)
+ if (lhs.val[i] != rhs.val[i])
+ return false;
+ return true;
+ }
+
+ LIBC_INLINE friend constexpr bool operator!=(const BigInt &lhs,
+ const BigInt &rhs) {
+ return !(lhs == rhs);
+ }
+
+ LIBC_INLINE friend constexpr bool operator>(const BigInt &lhs,
+ const BigInt &rhs) {
+ return cmp(lhs, rhs) > 0;
+ }
+ LIBC_INLINE friend constexpr bool operator>=(const BigInt &lhs,
+ const BigInt &rhs) {
+ return cmp(lhs, rhs) >= 0;
+ }
+ LIBC_INLINE friend constexpr bool operator<(const BigInt &lhs,
+ const BigInt &rhs) {
+ return cmp(lhs, rhs) < 0;
+ }
+ LIBC_INLINE friend constexpr bool operator<=(const BigInt &lhs,
+ const BigInt &rhs) {
+ return cmp(lhs, rhs) <= 0;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator++() {
+ increment();
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt operator++(int) {
+ BigInt oldval(*this);
+ increment();
+ return oldval;
+ }
+
+ LIBC_INLINE constexpr BigInt &operator--() {
+ decrement();
+ return *this;
+ }
+
+ LIBC_INLINE constexpr BigInt operator--(int) {
+ BigInt oldval(*this);
+ decrement();
+ return oldval;
+ }
+
+ // Return the i-th word of the number.
+ LIBC_INLINE constexpr const WordType &operator[](size_t i) const {
+ return val[i];
+ }
+
+ // Return the i-th word of the number.
+ LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }
+
+private:
+ LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {
+ constexpr auto compare = [](WordType a, WordType b) {
+ return a == b ? 0 : a > b ? 1 : -1;
+ };
+ if constexpr (Signed) {
+ const bool lhs_is_neg = lhs.is_neg();
+ const bool rhs_is_neg = rhs.is_neg();
+ if (lhs_is_neg != rhs_is_neg)
+ return rhs_is_neg ? 1 : -1;
+ }
+ for (size_t i = WORD_COUNT; i-- > 0;)
+ if (auto cmp = compare(lhs[i], rhs[i]); cmp != 0)
+ return cmp;
+ return 0;
+ }
+
+ LIBC_INLINE constexpr void bitwise_not() {
+ for (auto &part : val)
+ part = ~part;
+ }
+
+ LIBC_INLINE constexpr void negate() {
+ bitwise_not();
+ increment();
+ }
+
+ LIBC_INLINE constexpr void increment() {
+ multiword::add_with_carry(val, cpp::array<WordType, 1>{1});
+ }
+
+ LIBC_INLINE constexpr void decrement() {
+ multiword::add_with_carry(val, cpp::array<WordType, 1>{1});
+ }
+
+ LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {
+ const WordType value = is_neg ? cpp::numeric_limits<WordType>::max()
+ : cpp::numeric_limits<WordType>::min();
+ for (size_t i = index; i < WORD_COUNT; ++i)
+ val[i] = value;
+ }
+
+ LIBC_INLINE constexpr bool get_msb() const {
+ return val.back() >> (WORD_SIZE - 1);
+ }
+
+ LIBC_INLINE constexpr void set_msb() {
+ val.back() |= mask_leading_ones<WordType, 1>();
+ }
+
+ LIBC_INLINE constexpr void clear_msb() {
+ val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();
+ }
+
+ LIBC_INLINE constexpr void set_bit(size_t i) {
+ const size_t word_index = i / WORD_SIZE;
+ val[word_index] |= WordType(1) << (i % WORD_SIZE);
+ }
+
+ LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,
+ const BigInt &divider) {
+ BigInt remainder = dividend;
+ BigInt quotient;
+ if (remainder >= divider) {
+ BigInt subtractor = divider;
+ int cur_bit = multiword::countl_zero(subtractor.val) -
+ multiword::countl_zero(remainder.val);
+ subtractor <<= cur_bit;
+ for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {
+ if (remainder < subtractor)
+ continue;
+ remainder -= subtractor;
+ quotient.set_bit(cur_bit);
+ }
+ }
+ return Division{quotient, remainder};
+ }
+
+ LIBC_INLINE constexpr static Division divide_signed(const BigInt &dividend,
+ const BigInt &divider) {
+ // Special case because it is not possible to negate the min value of a
+ // signed integer.
+ if (dividend == min() && divider == min())
+ return Division{one(), zero()};
+ // 1. Convert the dividend and divisor to unsigned representation.
+ unsigned_type udividend(dividend);
+ unsigned_type udivider(divider);
+ // 2. Negate the dividend if it's negative, and similarly for the divisor.
+ const bool dividend_is_neg = dividend.is_neg();
+ const bool divider_is_neg = divider.is_neg();
+ if (dividend_is_neg)
+ udividend.negate();
+ if (divider_is_neg)
+ udivider.negate();
+ // 3. Use unsigned multiword division algorithm.
+ const auto unsigned_result = divide_unsigned(udividend, udivider);
+ // 4. Convert the quotient and remainder to signed representation.
+ Division result;
+ result.quotient = signed_type(unsigned_result.quotient);
+ result.remainder = signed_type(unsigned_result.remainder);
+ // 5. Negate the quotient if the dividend and divisor had opposite signs.
+ if (dividend_is_neg != divider_is_neg)
+ result.quotient.negate();
+ // 6. Negate the remainder if the dividend was negative.
+ if (dividend_is_neg)
+ result.remainder.negate();
+ return result;
+ }
+
+ friend signed_type;
+ friend unsigned_type;
+};
+
+namespace internal {
+// We default BigInt's WordType to 'uint64_t' or 'uint32_t' depending on type
+// availability.
+template <size_t Bits>
+struct WordTypeSelector : cpp::type_identity<
+#ifdef LIBC_TYPES_HAS_INT64
+ uint64_t
+#else
+ uint32_t
+#endif // LIBC_TYPES_HAS_INT64
+ > {
+};
+// Except if we request 16 or 32 bits explicitly.
+template <> struct WordTypeSelector<16> : cpp::type_identity<uint16_t> {};
+template <> struct WordTypeSelector<32> : cpp::type_identity<uint32_t> {};
+template <> struct WordTypeSelector<96> : cpp::type_identity<uint32_t> {};
+
+template <size_t Bits>
+using WordTypeSelectorT = typename WordTypeSelector<Bits>::type;
+} // namespace internal
+
+template <size_t Bits>
+using UInt = BigInt<Bits, false, internal::WordTypeSelectorT<Bits>>;
+
+template <size_t Bits>
+using Int = BigInt<Bits, true, internal::WordTypeSelectorT<Bits>>;
+
+// Provides limits of BigInt.
+template <size_t Bits, bool Signed, typename T>
+struct cpp::numeric_limits<BigInt<Bits, Signed, T>> {
+ LIBC_INLINE static constexpr BigInt<Bits, Signed, T> max() {
+ return BigInt<Bits, Signed, T>::max();
+ }
+ LIBC_INLINE static constexpr BigInt<Bits, Signed, T> min() {
+ return BigInt<Bits, Signed, T>::min();
+ }
+ // Meant to match std::numeric_limits interface.
+ // NOLINTNEXTLINE(readability-identifier-naming)
+ LIBC_INLINE_VAR static constexpr int digits = Bits - Signed;
+};
+
+// type traits to determine whether a T is a BigInt.
+template <typename T> struct is_big_int : cpp::false_type {};
+
+template <size_t Bits, bool Signed, typename T>
+struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {};
+
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value;
+
+// extensions of type traits to include BigInt
+
+// is_integral_or_big_int
+template <typename T>
+struct is_integral_or_big_int
+ : cpp::bool_constant<(cpp::is_integral_v<T> || is_big_int_v<T>)> {};
+
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_integral_or_big_int_v =
+ is_integral_or_big_int<T>::value;
+
+// make_big_int_unsigned
+template <typename T> struct make_big_int_unsigned;
+
+template <size_t Bits, bool Signed, typename T>
+struct make_big_int_unsigned<BigInt<Bits, Signed, T>>
+ : cpp::type_identity<BigInt<Bits, false, T>> {};
+
+template <typename T>
+using make_big_int_unsigned_t = typename make_big_int_unsigned<T>::type;
+
+// make_big_int_signed
+template <typename T> struct make_big_int_signed;
+
+template <size_t Bits, bool Signed, typename T>
+struct make_big_int_signed<BigInt<Bits, Signed, T>>
+ : cpp::type_identity<BigInt<Bits, true, T>> {};
+
+template <typename T>
+using make_big_int_signed_t = typename make_big_int_signed<T>::type;
+
+// make_integral_or_big_int_unsigned
+template <typename T, class = void> struct make_integral_or_big_int_unsigned;
+
+template <typename T>
+struct make_integral_or_big_int_unsigned<
+ T, cpp::enable_if_t<cpp::is_integral_v<T>>> : cpp::make_unsigned<T> {};
+
+template <typename T>
+struct make_integral_or_big_int_unsigned<T, cpp::enable_if_t<is_big_int_v<T>>>
+ : make_big_int_unsigned<T> {};
+
+template <typename T>
+using make_integral_or_big_int_unsigned_t =
+ typename make_integral_or_big_int_unsigned<T>::type;
+
+// make_integral_or_big_int_signed
+template <typename T, class = void> struct make_integral_or_big_int_signed;
+
+template <typename T>
+struct make_integral_or_big_int_signed<T,
+ cpp::enable_if_t<cpp::is_integral_v<T>>>
+ : cpp::make_signed<T> {};
+
+template <typename T>
+struct make_integral_or_big_int_signed<T, cpp::enable_if_t<is_big_int_v<T>>>
+ : make_big_int_signed<T> {};
+
+template <typename T>
+using make_integral_or_big_int_signed_t =
+ typename make_integral_or_big_int_signed<T>::type;
+
+// is_unsigned_integral_or_big_int
+template <typename T>
+struct is_unsigned_integral_or_big_int
+ : cpp::bool_constant<
+ cpp::is_same_v<T, make_integral_or_big_int_unsigned_t<T>>> {};
+
+template <typename T>
+// Meant to look like <type_traits> helper variable templates.
+// NOLINTNEXTLINE(readability-identifier-naming)
+LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v =
+ is_unsigned_integral_or_big_int<T>::value;
+
+namespace cpp {
+
+// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
+template <typename To, typename From>
+LIBC_INLINE constexpr cpp::enable_if_t<
+ (sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value &&
+ cpp::is_trivially_copyable<From>::value && is_big_int<To>::value,
+ To>
+bit_cast(const From &from) {
+ To out;
+ using Storage = decltype(out.val);
+ out.val = cpp::bit_cast<Storage>(from);
+ return out;
+}
+
+// Specialization of cpp::bit_cast ('bit.h') from BigInt to T.
+template <typename To, size_t Bits>
+LIBC_INLINE constexpr cpp::enable_if_t<
+ sizeof(To) == sizeof(UInt<Bits>) &&
+ cpp::is_trivially_constructible<To>::value &&
+ cpp::is_trivially_copyable<To>::value &&
+ cpp::is_trivially_copyable<UInt<Bits>>::value,
+ To>
+bit_cast(const UInt<Bits> &from) {
+ return cpp::bit_cast<To>(from.val);
+}
+
+// Specialization of cpp::popcount ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+popcount(T value) {
+ int bits = 0;
+ for (auto word : value.val)
+ if (word)
+ bits += popcount(word);
+ return bits;
+}
+
+// Specialization of cpp::has_single_bit ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool>
+has_single_bit(T value) {
+ int bits = 0;
+ for (auto word : value.val) {
+ if (word == 0)
+ continue;
+ bits += popcount(word);
+ if (bits > 1)
+ return false;
+ }
+ return bits == 1;
+}
+
+// Specialization of cpp::countr_zero ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+countr_zero(const T &value) {
+ return multiword::countr_zero(value.val);
+}
+
+// Specialization of cpp::countl_zero ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+countl_zero(const T &value) {
+ return multiword::countl_zero(value.val);
+}
+
+// Specialization of cpp::countl_one ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+countl_one(T value) {
+ return multiword::countl_one(value.val);
+}
+
+// Specialization of cpp::countr_one ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+countr_one(T value) {
+ return multiword::countr_one(value.val);
+}
+
+// Specialization of cpp::bit_width ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+bit_width(T value) {
+ return cpp::numeric_limits<T>::digits - cpp::countl_zero(value);
+}
+
+// Forward-declare rotr so that rotl can use it.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+rotr(T value, int rotate);
+
+// Specialization of cpp::rotl ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+rotl(T value, int rotate) {
+ constexpr unsigned N = cpp::numeric_limits<T>::digits;
+ rotate = rotate % N;
+ if (!rotate)
+ return value;
+ if (rotate < 0)
+ return cpp::rotr<T>(value, -rotate);
+ return (value << rotate) | (value >> (N - rotate));
+}
+
+// Specialization of cpp::rotr ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+rotr(T value, int rotate) {
+ constexpr unsigned N = cpp::numeric_limits<T>::digits;
+ rotate = rotate % N;
+ if (!rotate)
+ return value;
+ if (rotate < 0)
+ return cpp::rotl<T>(value, -rotate);
+ return (value >> rotate) | (value << (N - rotate));
+}
+
+} // namespace cpp
+
+// Specialization of mask_trailing_ones ('math_extras.h') for BigInt.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+mask_trailing_ones() {
+ static_assert(!T::SIGNED && count <= T::BITS);
+ if (count == T::BITS)
+ return T::all_ones();
+ constexpr size_t QUOTIENT = count / T::WORD_SIZE;
+ constexpr size_t REMAINDER = count % T::WORD_SIZE;
+ T out; // zero initialized
+ for (size_t i = 0; i <= QUOTIENT; ++i)
+ out[i] = i < QUOTIENT
+ ? -1
+ : mask_trailing_ones<typename T::word_type, REMAINDER>();
+ return out;
+}
+
+// Specialization of mask_leading_ones ('math_extras.h') for BigInt.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
+ static_assert(!T::SIGNED && count <= T::BITS);
+ if (count == T::BITS)
+ return T::all_ones();
+ constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE;
+ constexpr size_t REMAINDER = count % T::WORD_SIZE;
+ T out; // zero initialized
+ for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)
+ out[i] = i > QUOTIENT
+ ? -1
+ : mask_leading_ones<typename T::word_type, REMAINDER>();
+ return out;
+}
+
+// Specialization of mask_trailing_zeros ('math_extras.h') for BigInt.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+mask_trailing_zeros() {
+ return mask_leading_ones<T, T::BITS - count>();
+}
+
+// Specialization of mask_leading_zeros ('math_extras.h') for BigInt.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
+mask_leading_zeros() {
+ return mask_trailing_ones<T, T::BITS - count>();
+}
+
+// Specialization of count_zeros ('math_extras.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+count_zeros(T value) {
+ return cpp::popcount(~value);
+}
+
+// Specialization of first_leading_zero ('math_extras.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+first_leading_zero(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countl_one(value) + 1;
+}
+
+// Specialization of first_leading_one ('math_extras.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+first_leading_one(T value) {
+ return first_leading_zero(~value);
+}
+
+// Specialization of first_trailing_zero ('math_extras.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+first_trailing_zero(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countr_zero(~value) + 1;
+}
+
+// Specialization of first_trailing_one ('math_extras.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+first_trailing_one(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countr_zero(value) + 1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
diff --git a/lib/libcxx/libc/src/__support/common.h b/lib/libcxx/libc/src/__support/common.h
new file mode 100644
index 0000000000..42e8a79187
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/common.h
@@ -0,0 +1,82 @@
+//===-- Common internal contructs -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_COMMON_H
+#define LLVM_LIBC_SRC___SUPPORT_COMMON_H
+
+#ifndef LIBC_NAMESPACE
+#error "LIBC_NAMESPACE macro is not defined."
+#endif
+
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#ifndef LLVM_LIBC_FUNCTION_ATTR
+#define LLVM_LIBC_FUNCTION_ATTR
+#endif
+
+// clang-format off
+// Allow each function `func` to have extra attributes specified by defining:
+// `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with
+// "LLVM_LIBC_EMPTY, "
+//
+// For examples:
+// #define LLVM_LIBC_FUNCTION_ATTR_memcpy LLVM_LIBC_EMPTY, [[gnu::weak]]
+// #define LLVM_LIBC_FUNCTION_ATTR_memchr LLVM_LIBC_EMPTY, [[gnu::weak]] [[gnu::visibility("default")]]
+// clang-format on
+#define LLVM_LIBC_EMPTY
+
+#define GET_SECOND(first, second, ...) second
+#define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY)
+
+#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)
+
+// MacOS needs to be excluded because it does not support aliasing.
+#if defined(LIBC_COPT_PUBLIC_PACKAGING) && (!defined(__APPLE__))
+#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
+ LLVM_LIBC_ATTR(name) \
+ LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \
+ __##name##_impl__ __asm__(#name); \
+ decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
+ type __##name##_impl__ arglist
+#else
+#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist
+#endif
+
+// This extra layer of macro allows `name` to be a macro to rename a function.
+#define LLVM_LIBC_FUNCTION(type, name, arglist) \
+ LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) {
+ for (; *lhs || *rhs; ++lhs, ++rhs)
+ if (*lhs != *rhs)
+ return false;
+ return true;
+}
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#define __LIBC_MACRO_TO_STRING(str) #str
+#define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str)
+
+// LLVM_LIBC_IS_DEFINED checks whether a particular macro is defined.
+// Usage: constexpr bool kUseAvx = LLVM_LIBC_IS_DEFINED(__AVX__);
+//
+// This works by comparing the stringified version of the macro with and without
+// evaluation. If FOO is not undefined both stringifications yield "FOO". If FOO
+// is defined, one stringification yields "FOO" while the other yields its
+// stringified value "1".
+#define LLVM_LIBC_IS_DEFINED(macro) \
+ !LIBC_NAMESPACE::internal::same_string( \
+ LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(macro), #macro)
+#define LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(s) #s
+
+#endif // LLVM_LIBC_SRC___SUPPORT_COMMON_H
diff --git a/lib/libcxx/libc/src/__support/ctype_utils.h b/lib/libcxx/libc/src/__support/ctype_utils.h
new file mode 100644
index 0000000000..be0f25330a
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/ctype_utils.h
@@ -0,0 +1,584 @@
+//===-- Collection of utils for implementing ctype functions-------*-C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H
+#define LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H
+
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+// -----------------------------------------------------------------------------
+// ****************** WARNING ******************
+// ****************** DO NOT TRY TO OPTIMIZE THESE FUNCTIONS! ******************
+// -----------------------------------------------------------------------------
+// This switch/case form is easier for the compiler to understand, and is
+// optimized into a form that is almost always the same as or better than
+// versions written by hand (see https://godbolt.org/z/qvrebqvvr). Also this
+// form makes these functions encoding independent. If you want to rewrite these
+// functions, make sure you have benchmarks to show your new solution is faster,
+// as well as a way to support non-ASCII character encodings.
+
+// Similarly, do not change these functions to use case ranges. e.g.
+// bool islower(int ch) {
+// switch(ch) {
+// case 'a'...'z':
+// return true;
+// }
+// }
+// This assumes the character ranges are contiguous, which they aren't in
+// EBCDIC. Technically we could use some smaller ranges, but that's even harder
+// to read.
+
+LIBC_INLINE static constexpr bool islower(int ch) {
+ switch (ch) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ return true;
+ default:
+ return false;
+ }
+}
+
+LIBC_INLINE static constexpr bool isupper(int ch) {
+ switch (ch) {
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ return true;
+ default:
+ return false;
+ }
+}
+
+LIBC_INLINE static constexpr bool isdigit(int ch) {
+ switch (ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return true;
+ default:
+ return false;
+ }
+}
+
+LIBC_INLINE static constexpr int tolower(int ch) {
+ switch (ch) {
+ case 'A':
+ return 'a';
+ case 'B':
+ return 'b';
+ case 'C':
+ return 'c';
+ case 'D':
+ return 'd';
+ case 'E':
+ return 'e';
+ case 'F':
+ return 'f';
+ case 'G':
+ return 'g';
+ case 'H':
+ return 'h';
+ case 'I':
+ return 'i';
+ case 'J':
+ return 'j';
+ case 'K':
+ return 'k';
+ case 'L':
+ return 'l';
+ case 'M':
+ return 'm';
+ case 'N':
+ return 'n';
+ case 'O':
+ return 'o';
+ case 'P':
+ return 'p';
+ case 'Q':
+ return 'q';
+ case 'R':
+ return 'r';
+ case 'S':
+ return 's';
+ case 'T':
+ return 't';
+ case 'U':
+ return 'u';
+ case 'V':
+ return 'v';
+ case 'W':
+ return 'w';
+ case 'X':
+ return 'x';
+ case 'Y':
+ return 'y';
+ case 'Z':
+ return 'z';
+ default:
+ return ch;
+ }
+}
+
+LIBC_INLINE static constexpr int toupper(int ch) {
+ switch (ch) {
+ case 'a':
+ return 'A';
+ case 'b':
+ return 'B';
+ case 'c':
+ return 'C';
+ case 'd':
+ return 'D';
+ case 'e':
+ return 'E';
+ case 'f':
+ return 'F';
+ case 'g':
+ return 'G';
+ case 'h':
+ return 'H';
+ case 'i':
+ return 'I';
+ case 'j':
+ return 'J';
+ case 'k':
+ return 'K';
+ case 'l':
+ return 'L';
+ case 'm':
+ return 'M';
+ case 'n':
+ return 'N';
+ case 'o':
+ return 'O';
+ case 'p':
+ return 'P';
+ case 'q':
+ return 'Q';
+ case 'r':
+ return 'R';
+ case 's':
+ return 'S';
+ case 't':
+ return 'T';
+ case 'u':
+ return 'U';
+ case 'v':
+ return 'V';
+ case 'w':
+ return 'W';
+ case 'x':
+ return 'X';
+ case 'y':
+ return 'Y';
+ case 'z':
+ return 'Z';
+ default:
+ return ch;
+ }
+}
+
+LIBC_INLINE static constexpr bool isalpha(int ch) {
+ switch (ch) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ return true;
+ default:
+ return false;
+ }
+}
+
+LIBC_INLINE static constexpr bool isalnum(int ch) {
+ switch (ch) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return true;
+ default:
+ return false;
+ }
+}
+
+LIBC_INLINE static constexpr int b36_char_to_int(int ch) {
+ switch (ch) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ case 'g':
+ case 'G':
+ return 16;
+ case 'h':
+ case 'H':
+ return 17;
+ case 'i':
+ case 'I':
+ return 18;
+ case 'j':
+ case 'J':
+ return 19;
+ case 'k':
+ case 'K':
+ return 20;
+ case 'l':
+ case 'L':
+ return 21;
+ case 'm':
+ case 'M':
+ return 22;
+ case 'n':
+ case 'N':
+ return 23;
+ case 'o':
+ case 'O':
+ return 24;
+ case 'p':
+ case 'P':
+ return 25;
+ case 'q':
+ case 'Q':
+ return 26;
+ case 'r':
+ case 'R':
+ return 27;
+ case 's':
+ case 'S':
+ return 28;
+ case 't':
+ case 'T':
+ return 29;
+ case 'u':
+ case 'U':
+ return 30;
+ case 'v':
+ case 'V':
+ return 31;
+ case 'w':
+ case 'W':
+ return 32;
+ case 'x':
+ case 'X':
+ return 33;
+ case 'y':
+ case 'Y':
+ return 34;
+ case 'z':
+ case 'Z':
+ return 35;
+ default:
+ return 0;
+ }
+}
+
+LIBC_INLINE static constexpr int int_to_b36_char(int num) {
+ // Can't actually use LIBC_ASSERT here because it depends on integer_to_string
+ // which depends on this.
+
+ // LIBC_ASSERT(num < 36);
+ switch (num) {
+ case 0:
+ return '0';
+ case 1:
+ return '1';
+ case 2:
+ return '2';
+ case 3:
+ return '3';
+ case 4:
+ return '4';
+ case 5:
+ return '5';
+ case 6:
+ return '6';
+ case 7:
+ return '7';
+ case 8:
+ return '8';
+ case 9:
+ return '9';
+ case 10:
+ return 'a';
+ case 11:
+ return 'b';
+ case 12:
+ return 'c';
+ case 13:
+ return 'd';
+ case 14:
+ return 'e';
+ case 15:
+ return 'f';
+ case 16:
+ return 'g';
+ case 17:
+ return 'h';
+ case 18:
+ return 'i';
+ case 19:
+ return 'j';
+ case 20:
+ return 'k';
+ case 21:
+ return 'l';
+ case 22:
+ return 'm';
+ case 23:
+ return 'n';
+ case 24:
+ return 'o';
+ case 25:
+ return 'p';
+ case 26:
+ return 'q';
+ case 27:
+ return 'r';
+ case 28:
+ return 's';
+ case 29:
+ return 't';
+ case 30:
+ return 'u';
+ case 31:
+ return 'v';
+ case 32:
+ return 'w';
+ case 33:
+ return 'x';
+ case 34:
+ return 'y';
+ case 35:
+ return 'z';
+ default:
+ return '!';
+ }
+}
+
+LIBC_INLINE static constexpr bool isspace(int ch) {
+ switch (ch) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ return true;
+ default:
+ return false;
+ }
+}
+
+// not yet encoding independent.
+LIBC_INLINE static constexpr bool isgraph(int ch) {
+ return 0x20 < ch && ch < 0x7f;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H
diff --git a/lib/libcxx/libc/src/__support/detailed_powers_of_ten.h b/lib/libcxx/libc/src/__support/detailed_powers_of_ten.h
new file mode 100644
index 0000000000..28741b8a3f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/detailed_powers_of_ten.h
@@ -0,0 +1,740 @@
+//===-- detailed powers of ten ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H
+#define LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+// TODO(michaelrj): write a script that will generate this table.
+
+// This table was generated by
+// https://github.com/google/wuffs/blob/788479dd64f35cb6b4e998a851acb06ee962435b/script/print-mpb-powers-of-10.go
+// and contains the 128 bit mantissa approximations of the powers of 10 from
+// -348 to 347. The exponents are implied by a linear expression with slope
+// 217706.0/65536.0 ≈ log(10)/log(2). This is used by the Eisel-Lemire algorithm
+// in str_to_float.h.
+
+constexpr int32_t DETAILED_POWERS_OF_TEN_MIN_EXP_10 = -348;
+constexpr int32_t DETAILED_POWERS_OF_TEN_MAX_EXP_10 = 347;
+
+// This rescales the base 10 exponent by a factor of log(10)/log(2).
+LIBC_INLINE int32_t exp10_to_exp2(int32_t exp10) {
+ // Valid if exp10 < 646 456 636.
+ return static_cast<int32_t>((217706 * static_cast<int64_t>(exp10)) >> 16);
+}
+
+static constexpr uint64_t DETAILED_POWERS_OF_TEN[696][2] = {
+ {0x1732C869CD60E453, 0xFA8FD5A0081C0288}, // 1e-348
+ {0x0E7FBD42205C8EB4, 0x9C99E58405118195}, // 1e-347
+ {0x521FAC92A873B261, 0xC3C05EE50655E1FA}, // 1e-346
+ {0xE6A797B752909EF9, 0xF4B0769E47EB5A78}, // 1e-345
+ {0x9028BED2939A635C, 0x98EE4A22ECF3188B}, // 1e-344
+ {0x7432EE873880FC33, 0xBF29DCABA82FDEAE}, // 1e-343
+ {0x113FAA2906A13B3F, 0xEEF453D6923BD65A}, // 1e-342
+ {0x4AC7CA59A424C507, 0x9558B4661B6565F8}, // 1e-341
+ {0x5D79BCF00D2DF649, 0xBAAEE17FA23EBF76}, // 1e-340
+ {0xF4D82C2C107973DC, 0xE95A99DF8ACE6F53}, // 1e-339
+ {0x79071B9B8A4BE869, 0x91D8A02BB6C10594}, // 1e-338
+ {0x9748E2826CDEE284, 0xB64EC836A47146F9}, // 1e-337
+ {0xFD1B1B2308169B25, 0xE3E27A444D8D98B7}, // 1e-336
+ {0xFE30F0F5E50E20F7, 0x8E6D8C6AB0787F72}, // 1e-335
+ {0xBDBD2D335E51A935, 0xB208EF855C969F4F}, // 1e-334
+ {0xAD2C788035E61382, 0xDE8B2B66B3BC4723}, // 1e-333
+ {0x4C3BCB5021AFCC31, 0x8B16FB203055AC76}, // 1e-332
+ {0xDF4ABE242A1BBF3D, 0xADDCB9E83C6B1793}, // 1e-331
+ {0xD71D6DAD34A2AF0D, 0xD953E8624B85DD78}, // 1e-330
+ {0x8672648C40E5AD68, 0x87D4713D6F33AA6B}, // 1e-329
+ {0x680EFDAF511F18C2, 0xA9C98D8CCB009506}, // 1e-328
+ {0x0212BD1B2566DEF2, 0xD43BF0EFFDC0BA48}, // 1e-327
+ {0x014BB630F7604B57, 0x84A57695FE98746D}, // 1e-326
+ {0x419EA3BD35385E2D, 0xA5CED43B7E3E9188}, // 1e-325
+ {0x52064CAC828675B9, 0xCF42894A5DCE35EA}, // 1e-324
+ {0x7343EFEBD1940993, 0x818995CE7AA0E1B2}, // 1e-323
+ {0x1014EBE6C5F90BF8, 0xA1EBFB4219491A1F}, // 1e-322
+ {0xD41A26E077774EF6, 0xCA66FA129F9B60A6}, // 1e-321
+ {0x8920B098955522B4, 0xFD00B897478238D0}, // 1e-320
+ {0x55B46E5F5D5535B0, 0x9E20735E8CB16382}, // 1e-319
+ {0xEB2189F734AA831D, 0xC5A890362FDDBC62}, // 1e-318
+ {0xA5E9EC7501D523E4, 0xF712B443BBD52B7B}, // 1e-317
+ {0x47B233C92125366E, 0x9A6BB0AA55653B2D}, // 1e-316
+ {0x999EC0BB696E840A, 0xC1069CD4EABE89F8}, // 1e-315
+ {0xC00670EA43CA250D, 0xF148440A256E2C76}, // 1e-314
+ {0x380406926A5E5728, 0x96CD2A865764DBCA}, // 1e-313
+ {0xC605083704F5ECF2, 0xBC807527ED3E12BC}, // 1e-312
+ {0xF7864A44C633682E, 0xEBA09271E88D976B}, // 1e-311
+ {0x7AB3EE6AFBE0211D, 0x93445B8731587EA3}, // 1e-310
+ {0x5960EA05BAD82964, 0xB8157268FDAE9E4C}, // 1e-309
+ {0x6FB92487298E33BD, 0xE61ACF033D1A45DF}, // 1e-308
+ {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307
+ {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306
+ {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305
+ {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304
+ {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303
+ {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302
+ {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301
+ {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300
+ {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299
+ {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298
+ {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297
+ {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296
+ {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295
+ {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294
+ {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293
+ {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292
+ {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291
+ {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290
+ {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289
+ {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288
+ {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287
+ {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286
+ {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285
+ {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284
+ {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283
+ {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282
+ {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281
+ {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280
+ {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279
+ {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278
+ {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277
+ {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276
+ {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275
+ {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274
+ {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273
+ {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272
+ {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271
+ {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270
+ {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269
+ {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268
+ {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267
+ {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266
+ {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265
+ {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264
+ {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263
+ {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262
+ {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261
+ {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260
+ {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259
+ {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258
+ {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257
+ {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256
+ {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255
+ {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254
+ {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253
+ {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252
+ {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251
+ {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250
+ {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249
+ {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248
+ {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247
+ {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246
+ {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245
+ {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244
+ {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243
+ {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242
+ {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241
+ {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240
+ {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239
+ {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238
+ {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237
+ {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236
+ {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235
+ {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234
+ {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233
+ {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232
+ {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231
+ {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230
+ {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229
+ {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228
+ {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227
+ {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226
+ {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225
+ {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224
+ {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223
+ {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222
+ {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221
+ {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220
+ {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219
+ {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218
+ {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217
+ {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216
+ {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215
+ {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214
+ {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213
+ {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212
+ {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211
+ {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210
+ {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209
+ {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208
+ {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207
+ {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206
+ {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205
+ {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204
+ {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203
+ {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202
+ {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201
+ {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200
+ {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199
+ {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198
+ {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197
+ {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196
+ {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195
+ {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194
+ {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193
+ {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192
+ {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191
+ {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190
+ {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189
+ {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188
+ {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187
+ {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186
+ {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185
+ {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184
+ {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183
+ {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182
+ {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181
+ {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180
+ {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179
+ {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178
+ {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177
+ {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176
+ {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175
+ {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174
+ {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173
+ {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172
+ {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171
+ {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170
+ {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169
+ {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168
+ {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167
+ {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166
+ {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165
+ {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164
+ {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163
+ {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162
+ {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161
+ {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160
+ {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159
+ {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158
+ {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157
+ {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156
+ {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155
+ {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154
+ {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153
+ {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152
+ {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151
+ {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150
+ {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149
+ {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148
+ {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147
+ {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146
+ {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145
+ {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144
+ {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143
+ {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142
+ {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141
+ {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140
+ {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139
+ {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138
+ {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137
+ {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136
+ {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135
+ {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134
+ {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133
+ {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132
+ {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131
+ {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130
+ {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129
+ {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128
+ {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127
+ {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126
+ {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125
+ {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124
+ {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123
+ {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122
+ {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121
+ {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120
+ {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119
+ {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118
+ {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117
+ {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116
+ {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115
+ {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114
+ {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113
+ {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112
+ {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111
+ {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110
+ {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109
+ {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108
+ {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107
+ {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106
+ {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105
+ {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104
+ {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103
+ {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102
+ {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101
+ {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100
+ {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99
+ {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98
+ {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97
+ {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96
+ {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95
+ {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94
+ {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93
+ {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92
+ {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91
+ {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90
+ {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89
+ {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88
+ {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87
+ {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86
+ {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85
+ {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84
+ {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83
+ {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82
+ {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81
+ {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80
+ {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79
+ {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78
+ {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77
+ {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76
+ {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75
+ {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74
+ {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73
+ {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72
+ {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71
+ {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70
+ {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69
+ {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68
+ {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67
+ {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66
+ {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65
+ {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64
+ {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63
+ {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62
+ {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61
+ {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60
+ {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59
+ {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58
+ {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57
+ {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56
+ {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55
+ {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54
+ {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53
+ {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52
+ {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51
+ {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50
+ {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49
+ {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48
+ {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47
+ {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46
+ {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45
+ {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44
+ {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43
+ {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42
+ {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41
+ {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40
+ {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39
+ {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38
+ {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37
+ {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36
+ {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35
+ {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34
+ {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33
+ {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32
+ {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31
+ {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30
+ {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29
+ {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28
+ {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27
+ {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26
+ {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25
+ {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24
+ {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23
+ {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22
+ {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21
+ {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20
+ {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19
+ {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18
+ {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17
+ {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16
+ {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15
+ {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14
+ {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13
+ {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12
+ {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11
+ {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10
+ {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9
+ {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8
+ {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7
+ {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6
+ {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5
+ {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4
+ {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3
+ {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2
+ {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1
+ {0x0000000000000000, 0x8000000000000000}, // 1e0
+ {0x0000000000000000, 0xA000000000000000}, // 1e1
+ {0x0000000000000000, 0xC800000000000000}, // 1e2
+ {0x0000000000000000, 0xFA00000000000000}, // 1e3
+ {0x0000000000000000, 0x9C40000000000000}, // 1e4
+ {0x0000000000000000, 0xC350000000000000}, // 1e5
+ {0x0000000000000000, 0xF424000000000000}, // 1e6
+ {0x0000000000000000, 0x9896800000000000}, // 1e7
+ {0x0000000000000000, 0xBEBC200000000000}, // 1e8
+ {0x0000000000000000, 0xEE6B280000000000}, // 1e9
+ {0x0000000000000000, 0x9502F90000000000}, // 1e10
+ {0x0000000000000000, 0xBA43B74000000000}, // 1e11
+ {0x0000000000000000, 0xE8D4A51000000000}, // 1e12
+ {0x0000000000000000, 0x9184E72A00000000}, // 1e13
+ {0x0000000000000000, 0xB5E620F480000000}, // 1e14
+ {0x0000000000000000, 0xE35FA931A0000000}, // 1e15
+ {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16
+ {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17
+ {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18
+ {0x0000000000000000, 0x8AC7230489E80000}, // 1e19
+ {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20
+ {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21
+ {0x0000000000000000, 0x878678326EAC9000}, // 1e22
+ {0x0000000000000000, 0xA968163F0A57B400}, // 1e23
+ {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24
+ {0x0000000000000000, 0x84595161401484A0}, // 1e25
+ {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26
+ {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27
+ {0x4000000000000000, 0x813F3978F8940984}, // 1e28
+ {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29
+ {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30
+ {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31
+ {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32
+ {0x6C28000000000000, 0xC5371912364CE305}, // 1e33
+ {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34
+ {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35
+ {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36
+ {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37
+ {0x1314448000000000, 0x96769950B50D88F4}, // 1e38
+ {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39
+ {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40
+ {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41
+ {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42
+ {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43
+ {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44
+ {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45
+ {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46
+ {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47
+ {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48
+ {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49
+ {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50
+ {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51
+ {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52
+ {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53
+ {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54
+ {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55
+ {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56
+ {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57
+ {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58
+ {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59
+ {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60
+ {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61
+ {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62
+ {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63
+ {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64
+ {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65
+ {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66
+ {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67
+ {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68
+ {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69
+ {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70
+ {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71
+ {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72
+ {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73
+ {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74
+ {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75
+ {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76
+ {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77
+ {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78
+ {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79
+ {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80
+ {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81
+ {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82
+ {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83
+ {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84
+ {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85
+ {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86
+ {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87
+ {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88
+ {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89
+ {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90
+ {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91
+ {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92
+ {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93
+ {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94
+ {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95
+ {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96
+ {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97
+ {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98
+ {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99
+ {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100
+ {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101
+ {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102
+ {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103
+ {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104
+ {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105
+ {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106
+ {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107
+ {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108
+ {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109
+ {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110
+ {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111
+ {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112
+ {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113
+ {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114
+ {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115
+ {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116
+ {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117
+ {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118
+ {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119
+ {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120
+ {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121
+ {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122
+ {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123
+ {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124
+ {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125
+ {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126
+ {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127
+ {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128
+ {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129
+ {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130
+ {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131
+ {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132
+ {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133
+ {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134
+ {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135
+ {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136
+ {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137
+ {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138
+ {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139
+ {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140
+ {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141
+ {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142
+ {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143
+ {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144
+ {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145
+ {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146
+ {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147
+ {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148
+ {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149
+ {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150
+ {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151
+ {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152
+ {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153
+ {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154
+ {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155
+ {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156
+ {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157
+ {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158
+ {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159
+ {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160
+ {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161
+ {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162
+ {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163
+ {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164
+ {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165
+ {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166
+ {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167
+ {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168
+ {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169
+ {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170
+ {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171
+ {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172
+ {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173
+ {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174
+ {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175
+ {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176
+ {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177
+ {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178
+ {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179
+ {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180
+ {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181
+ {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182
+ {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183
+ {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184
+ {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185
+ {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186
+ {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187
+ {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188
+ {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189
+ {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190
+ {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191
+ {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192
+ {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193
+ {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194
+ {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195
+ {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196
+ {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197
+ {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198
+ {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199
+ {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200
+ {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201
+ {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202
+ {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203
+ {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204
+ {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205
+ {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206
+ {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207
+ {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208
+ {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209
+ {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210
+ {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211
+ {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212
+ {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213
+ {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214
+ {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215
+ {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216
+ {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217
+ {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218
+ {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219
+ {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220
+ {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221
+ {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222
+ {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223
+ {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224
+ {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225
+ {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226
+ {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227
+ {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228
+ {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229
+ {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230
+ {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231
+ {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232
+ {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233
+ {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234
+ {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235
+ {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236
+ {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237
+ {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238
+ {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239
+ {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240
+ {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241
+ {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242
+ {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243
+ {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244
+ {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245
+ {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246
+ {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247
+ {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248
+ {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249
+ {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250
+ {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251
+ {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252
+ {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253
+ {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254
+ {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255
+ {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256
+ {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257
+ {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258
+ {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259
+ {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260
+ {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261
+ {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262
+ {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263
+ {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264
+ {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265
+ {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266
+ {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267
+ {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268
+ {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269
+ {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270
+ {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271
+ {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272
+ {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273
+ {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274
+ {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275
+ {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276
+ {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277
+ {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278
+ {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279
+ {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280
+ {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281
+ {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282
+ {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283
+ {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284
+ {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285
+ {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286
+ {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287
+ {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288
+ {0xC831FD53C5FF7EAB, 0x83585D8FD9C25DB7}, // 1e289
+ {0xBA3E7CA8B77F5E55, 0xA42E74F3D032F525}, // 1e290
+ {0x28CE1BD2E55F35EB, 0xCD3A1230C43FB26F}, // 1e291
+ {0x7980D163CF5B81B3, 0x80444B5E7AA7CF85}, // 1e292
+ {0xD7E105BCC332621F, 0xA0555E361951C366}, // 1e293
+ {0x8DD9472BF3FEFAA7, 0xC86AB5C39FA63440}, // 1e294
+ {0xB14F98F6F0FEB951, 0xFA856334878FC150}, // 1e295
+ {0x6ED1BF9A569F33D3, 0x9C935E00D4B9D8D2}, // 1e296
+ {0x0A862F80EC4700C8, 0xC3B8358109E84F07}, // 1e297
+ {0xCD27BB612758C0FA, 0xF4A642E14C6262C8}, // 1e298
+ {0x8038D51CB897789C, 0x98E7E9CCCFBD7DBD}, // 1e299
+ {0xE0470A63E6BD56C3, 0xBF21E44003ACDD2C}, // 1e300
+ {0x1858CCFCE06CAC74, 0xEEEA5D5004981478}, // 1e301
+ {0x0F37801E0C43EBC8, 0x95527A5202DF0CCB}, // 1e302
+ {0xD30560258F54E6BA, 0xBAA718E68396CFFD}, // 1e303
+ {0x47C6B82EF32A2069, 0xE950DF20247C83FD}, // 1e304
+ {0x4CDC331D57FA5441, 0x91D28B7416CDD27E}, // 1e305
+ {0xE0133FE4ADF8E952, 0xB6472E511C81471D}, // 1e306
+ {0x58180FDDD97723A6, 0xE3D8F9E563A198E5}, // 1e307
+ {0x570F09EAA7EA7648, 0x8E679C2F5E44FF8F}, // 1e308
+ {0x2CD2CC6551E513DA, 0xB201833B35D63F73}, // 1e309
+ {0xF8077F7EA65E58D1, 0xDE81E40A034BCF4F}, // 1e310
+ {0xFB04AFAF27FAF782, 0x8B112E86420F6191}, // 1e311
+ {0x79C5DB9AF1F9B563, 0xADD57A27D29339F6}, // 1e312
+ {0x18375281AE7822BC, 0xD94AD8B1C7380874}, // 1e313
+ {0x8F2293910D0B15B5, 0x87CEC76F1C830548}, // 1e314
+ {0xB2EB3875504DDB22, 0xA9C2794AE3A3C69A}, // 1e315
+ {0x5FA60692A46151EB, 0xD433179D9C8CB841}, // 1e316
+ {0xDBC7C41BA6BCD333, 0x849FEEC281D7F328}, // 1e317
+ {0x12B9B522906C0800, 0xA5C7EA73224DEFF3}, // 1e318
+ {0xD768226B34870A00, 0xCF39E50FEAE16BEF}, // 1e319
+ {0xE6A1158300D46640, 0x81842F29F2CCE375}, // 1e320
+ {0x60495AE3C1097FD0, 0xA1E53AF46F801C53}, // 1e321
+ {0x385BB19CB14BDFC4, 0xCA5E89B18B602368}, // 1e322
+ {0x46729E03DD9ED7B5, 0xFCF62C1DEE382C42}, // 1e323
+ {0x6C07A2C26A8346D1, 0x9E19DB92B4E31BA9}, // 1e324
+ {0xC7098B7305241885, 0xC5A05277621BE293}, // 1e325
+ {0xB8CBEE4FC66D1EA7, 0xF70867153AA2DB38}, // 1e326
+ {0x737F74F1DC043328, 0x9A65406D44A5C903}, // 1e327
+ {0x505F522E53053FF2, 0xC0FE908895CF3B44}, // 1e328
+ {0x647726B9E7C68FEF, 0xF13E34AABB430A15}, // 1e329
+ {0x5ECA783430DC19F5, 0x96C6E0EAB509E64D}, // 1e330
+ {0xB67D16413D132072, 0xBC789925624C5FE0}, // 1e331
+ {0xE41C5BD18C57E88F, 0xEB96BF6EBADF77D8}, // 1e332
+ {0x8E91B962F7B6F159, 0x933E37A534CBAAE7}, // 1e333
+ {0x723627BBB5A4ADB0, 0xB80DC58E81FE95A1}, // 1e334
+ {0xCEC3B1AAA30DD91C, 0xE61136F2227E3B09}, // 1e335
+ {0x213A4F0AA5E8A7B1, 0x8FCAC257558EE4E6}, // 1e336
+ {0xA988E2CD4F62D19D, 0xB3BD72ED2AF29E1F}, // 1e337
+ {0x93EB1B80A33B8605, 0xE0ACCFA875AF45A7}, // 1e338
+ {0xBC72F130660533C3, 0x8C6C01C9498D8B88}, // 1e339
+ {0xEB8FAD7C7F8680B4, 0xAF87023B9BF0EE6A}, // 1e340
+ {0xA67398DB9F6820E1, 0xDB68C2CA82ED2A05}, // 1e341
+ {0x88083F8943A1148C, 0x892179BE91D43A43}, // 1e342
+ {0x6A0A4F6B948959B0, 0xAB69D82E364948D4}, // 1e343
+ {0x848CE34679ABB01C, 0xD6444E39C3DB9B09}, // 1e344
+ {0xF2D80E0C0C0B4E11, 0x85EAB0E41A6940E5}, // 1e345
+ {0x6F8E118F0F0E2195, 0xA7655D1D2103911F}, // 1e346
+ {0x4B7195F2D2D1A9FB, 0xD13EB46469447567}, // 1e347
+};
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H
diff --git a/lib/libcxx/libc/src/__support/high_precision_decimal.h b/lib/libcxx/libc/src/__support/high_precision_decimal.h
new file mode 100644
index 0000000000..922dce484a
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/high_precision_decimal.h
@@ -0,0 +1,442 @@
+//===-- High Precision Decimal ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See httpss//llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This file is shared with libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
+#define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
+
+#include "src/__support/CPP/limits.h"
+#include "src/__support/ctype_utils.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/str_to_integer.h"
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+struct LShiftTableEntry {
+ uint32_t new_digits;
+ char const *power_of_five;
+};
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+// This is used in both this file and in the main str_to_float.h.
+// TODO: Figure out where to put this.
+enum class RoundDirection { Up, Down, Nearest };
+
+// This is based on the HPD data structure described as part of the Simple
+// Decimal Conversion algorithm by Nigel Tao, described at this link:
+// https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
+class HighPrecisionDecimal {
+
+ // This precomputed table speeds up left shifts by having the number of new
+ // digits that will be added by multiplying 5^i by 2^i. If the number is less
+ // than 5^i then it will add one fewer digit. There are only 60 entries since
+ // that's the max shift amount.
+ // This table was generated by the script at
+ // libc/utils/mathtools/GenerateHPDConstants.py
+ static constexpr LShiftTableEntry LEFT_SHIFT_DIGIT_TABLE[] = {
+ {0, ""},
+ {1, "5"},
+ {1, "25"},
+ {1, "125"},
+ {2, "625"},
+ {2, "3125"},
+ {2, "15625"},
+ {3, "78125"},
+ {3, "390625"},
+ {3, "1953125"},
+ {4, "9765625"},
+ {4, "48828125"},
+ {4, "244140625"},
+ {4, "1220703125"},
+ {5, "6103515625"},
+ {5, "30517578125"},
+ {5, "152587890625"},
+ {6, "762939453125"},
+ {6, "3814697265625"},
+ {6, "19073486328125"},
+ {7, "95367431640625"},
+ {7, "476837158203125"},
+ {7, "2384185791015625"},
+ {7, "11920928955078125"},
+ {8, "59604644775390625"},
+ {8, "298023223876953125"},
+ {8, "1490116119384765625"},
+ {9, "7450580596923828125"},
+ {9, "37252902984619140625"},
+ {9, "186264514923095703125"},
+ {10, "931322574615478515625"},
+ {10, "4656612873077392578125"},
+ {10, "23283064365386962890625"},
+ {10, "116415321826934814453125"},
+ {11, "582076609134674072265625"},
+ {11, "2910383045673370361328125"},
+ {11, "14551915228366851806640625"},
+ {12, "72759576141834259033203125"},
+ {12, "363797880709171295166015625"},
+ {12, "1818989403545856475830078125"},
+ {13, "9094947017729282379150390625"},
+ {13, "45474735088646411895751953125"},
+ {13, "227373675443232059478759765625"},
+ {13, "1136868377216160297393798828125"},
+ {14, "5684341886080801486968994140625"},
+ {14, "28421709430404007434844970703125"},
+ {14, "142108547152020037174224853515625"},
+ {15, "710542735760100185871124267578125"},
+ {15, "3552713678800500929355621337890625"},
+ {15, "17763568394002504646778106689453125"},
+ {16, "88817841970012523233890533447265625"},
+ {16, "444089209850062616169452667236328125"},
+ {16, "2220446049250313080847263336181640625"},
+ {16, "11102230246251565404236316680908203125"},
+ {17, "55511151231257827021181583404541015625"},
+ {17, "277555756156289135105907917022705078125"},
+ {17, "1387778780781445675529539585113525390625"},
+ {18, "6938893903907228377647697925567626953125"},
+ {18, "34694469519536141888238489627838134765625"},
+ {18, "173472347597680709441192448139190673828125"},
+ {19, "867361737988403547205962240695953369140625"},
+ };
+
+ // The maximum amount we can shift is the number of bits used in the
+ // accumulator, minus the number of bits needed to represent the base (in this
+ // case 4).
+ static constexpr uint32_t MAX_SHIFT_AMOUNT = sizeof(uint64_t) - 4;
+
+ // 800 is an arbitrary number of digits, but should be
+ // large enough for any practical number.
+ static constexpr uint32_t MAX_NUM_DIGITS = 800;
+
+ uint32_t num_digits = 0;
+ int32_t decimal_point = 0;
+ bool truncated = false;
+ uint8_t digits[MAX_NUM_DIGITS];
+
+private:
+ LIBC_INLINE bool should_round_up(int32_t round_to_digit,
+ RoundDirection round) {
+ if (round_to_digit < 0 ||
+ static_cast<uint32_t>(round_to_digit) >= this->num_digits) {
+ return false;
+ }
+
+ // The above condition handles all cases where all of the trailing digits
+ // are zero. In that case, if the rounding mode is up, then this number
+ // should be rounded up. Similarly, if the rounding mode is down, then it
+ // should always round down.
+ if (round == RoundDirection::Up) {
+ return true;
+ } else if (round == RoundDirection::Down) {
+ return false;
+ }
+ // Else round to nearest.
+
+ // If we're right in the middle and there are no extra digits
+ if (this->digits[round_to_digit] == 5 &&
+ static_cast<uint32_t>(round_to_digit + 1) == this->num_digits) {
+
+ // Round up if we've truncated (since that means the result is slightly
+ // higher than what's represented.)
+ if (this->truncated) {
+ return true;
+ }
+
+ // If this exactly halfway, round to even.
+ if (round_to_digit == 0)
+ // When the input is ".5".
+ return false;
+ return this->digits[round_to_digit - 1] % 2 != 0;
+ }
+ // If there are digits after round_to_digit, they must be non-zero since we
+ // trim trailing zeroes after all operations that change digits.
+ return this->digits[round_to_digit] >= 5;
+ }
+
+ // Takes an amount to left shift and returns the number of new digits needed
+ // to store the result based on LEFT_SHIFT_DIGIT_TABLE.
+ LIBC_INLINE uint32_t get_num_new_digits(uint32_t lshift_amount) {
+ const char *power_of_five =
+ LEFT_SHIFT_DIGIT_TABLE[lshift_amount].power_of_five;
+ uint32_t new_digits = LEFT_SHIFT_DIGIT_TABLE[lshift_amount].new_digits;
+ uint32_t digit_index = 0;
+ while (power_of_five[digit_index] != 0) {
+ if (digit_index >= this->num_digits) {
+ return new_digits - 1;
+ }
+ if (this->digits[digit_index] !=
+ internal::b36_char_to_int(power_of_five[digit_index])) {
+ return new_digits -
+ ((this->digits[digit_index] <
+ internal::b36_char_to_int(power_of_five[digit_index]))
+ ? 1
+ : 0);
+ }
+ ++digit_index;
+ }
+ return new_digits;
+ }
+
+ // Trim all trailing 0s
+ LIBC_INLINE void trim_trailing_zeroes() {
+ while (this->num_digits > 0 && this->digits[this->num_digits - 1] == 0) {
+ --this->num_digits;
+ }
+ if (this->num_digits == 0) {
+ this->decimal_point = 0;
+ }
+ }
+
+ // Perform a digitwise binary non-rounding right shift on this value by
+ // shift_amount. The shift_amount can't be more than MAX_SHIFT_AMOUNT to
+ // prevent overflow.
+ LIBC_INLINE void right_shift(uint32_t shift_amount) {
+ uint32_t read_index = 0;
+ uint32_t write_index = 0;
+
+ uint64_t accumulator = 0;
+
+ const uint64_t shift_mask = (uint64_t(1) << shift_amount) - 1;
+
+ // Warm Up phase: we don't have enough digits to start writing, so just
+ // read them into the accumulator.
+ while (accumulator >> shift_amount == 0) {
+ uint64_t read_digit = 0;
+ // If there are still digits to read, read the next one, else the digit is
+ // assumed to be 0.
+ if (read_index < this->num_digits) {
+ read_digit = this->digits[read_index];
+ }
+ accumulator = accumulator * 10 + read_digit;
+ ++read_index;
+ }
+
+ // Shift the decimal point by the number of digits it took to fill the
+ // accumulator.
+ this->decimal_point -= read_index - 1;
+
+ // Middle phase: we have enough digits to write, as well as more digits to
+ // read. Keep reading until we run out of digits.
+ while (read_index < this->num_digits) {
+ uint64_t read_digit = this->digits[read_index];
+ uint64_t write_digit = accumulator >> shift_amount;
+ accumulator &= shift_mask;
+ this->digits[write_index] = static_cast<uint8_t>(write_digit);
+ accumulator = accumulator * 10 + read_digit;
+ ++read_index;
+ ++write_index;
+ }
+
+ // Cool Down phase: All of the readable digits have been read, so just write
+ // the remainder, while treating any more digits as 0.
+ while (accumulator > 0) {
+ uint64_t write_digit = accumulator >> shift_amount;
+ accumulator &= shift_mask;
+ if (write_index < MAX_NUM_DIGITS) {
+ this->digits[write_index] = static_cast<uint8_t>(write_digit);
+ ++write_index;
+ } else if (write_digit > 0) {
+ this->truncated = true;
+ }
+ accumulator = accumulator * 10;
+ }
+ this->num_digits = write_index;
+ this->trim_trailing_zeroes();
+ }
+
+ // Perform a digitwise binary non-rounding left shift on this value by
+ // shift_amount. The shift_amount can't be more than MAX_SHIFT_AMOUNT to
+ // prevent overflow.
+ LIBC_INLINE void left_shift(uint32_t shift_amount) {
+ uint32_t new_digits = this->get_num_new_digits(shift_amount);
+
+ int32_t read_index = this->num_digits - 1;
+ uint32_t write_index = this->num_digits + new_digits;
+
+ uint64_t accumulator = 0;
+
+ // No Warm Up phase. Since we're putting digits in at the top and taking
+ // digits from the bottom we don't have to wait for the accumulator to fill.
+
+ // Middle phase: while we have more digits to read, keep reading as well as
+ // writing.
+ while (read_index >= 0) {
+ accumulator += static_cast<uint64_t>(this->digits[read_index])
+ << shift_amount;
+ uint64_t next_accumulator = accumulator / 10;
+ uint64_t write_digit = accumulator - (10 * next_accumulator);
+ --write_index;
+ if (write_index < MAX_NUM_DIGITS) {
+ this->digits[write_index] = static_cast<uint8_t>(write_digit);
+ } else if (write_digit != 0) {
+ this->truncated = true;
+ }
+ accumulator = next_accumulator;
+ --read_index;
+ }
+
+ // Cool Down phase: there are no more digits to read, so just write the
+ // remaining digits in the accumulator.
+ while (accumulator > 0) {
+ uint64_t next_accumulator = accumulator / 10;
+ uint64_t write_digit = accumulator - (10 * next_accumulator);
+ --write_index;
+ if (write_index < MAX_NUM_DIGITS) {
+ this->digits[write_index] = static_cast<uint8_t>(write_digit);
+ } else if (write_digit != 0) {
+ this->truncated = true;
+ }
+ accumulator = next_accumulator;
+ }
+
+ this->num_digits += new_digits;
+ if (this->num_digits > MAX_NUM_DIGITS) {
+ this->num_digits = MAX_NUM_DIGITS;
+ }
+ this->decimal_point += new_digits;
+ this->trim_trailing_zeroes();
+ }
+
+public:
+ // num_string is assumed to be a string of numeric characters. It doesn't
+ // handle leading spaces.
+ LIBC_INLINE
+ HighPrecisionDecimal(
+ const char *__restrict num_string,
+ const size_t num_len = cpp::numeric_limits<size_t>::max()) {
+ bool saw_dot = false;
+ size_t num_cur = 0;
+ // This counts the digits in the number, even if there isn't space to store
+ // them all.
+ uint32_t total_digits = 0;
+ while (num_cur < num_len &&
+ (isdigit(num_string[num_cur]) || num_string[num_cur] == '.')) {
+ if (num_string[num_cur] == '.') {
+ if (saw_dot) {
+ break;
+ }
+ this->decimal_point = total_digits;
+ saw_dot = true;
+ } else {
+ if (num_string[num_cur] == '0' && this->num_digits == 0) {
+ --this->decimal_point;
+ ++num_cur;
+ continue;
+ }
+ ++total_digits;
+ if (this->num_digits < MAX_NUM_DIGITS) {
+ this->digits[this->num_digits] = static_cast<uint8_t>(
+ internal::b36_char_to_int(num_string[num_cur]));
+ ++this->num_digits;
+ } else if (num_string[num_cur] != '0') {
+ this->truncated = true;
+ }
+ }
+ ++num_cur;
+ }
+
+ if (!saw_dot)
+ this->decimal_point = total_digits;
+
+ if (num_cur < num_len &&
+ (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) {
+ ++num_cur;
+ if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' ||
+ num_string[num_cur] == '-') {
+ auto result =
+ strtointeger<int32_t>(num_string + num_cur, 10, num_len - num_cur);
+ if (result.has_error()) {
+ // TODO: handle error
+ }
+ int32_t add_to_exponent = result.value;
+
+ // Here we do this operation as int64 to avoid overflow.
+ int64_t temp_exponent = static_cast<int64_t>(this->decimal_point) +
+ static_cast<int64_t>(add_to_exponent);
+
+ // Theoretically these numbers should be MAX_BIASED_EXPONENT for long
+ // double, but that should be ~16,000 which is much less than 1 << 30.
+ if (temp_exponent > (1 << 30)) {
+ temp_exponent = (1 << 30);
+ } else if (temp_exponent < -(1 << 30)) {
+ temp_exponent = -(1 << 30);
+ }
+ this->decimal_point = static_cast<int32_t>(temp_exponent);
+ }
+ }
+
+ this->trim_trailing_zeroes();
+ }
+
+ // Binary shift left (shift_amount > 0) or right (shift_amount < 0)
+ LIBC_INLINE void shift(int shift_amount) {
+ if (shift_amount == 0) {
+ return;
+ }
+ // Left
+ else if (shift_amount > 0) {
+ while (static_cast<uint32_t>(shift_amount) > MAX_SHIFT_AMOUNT) {
+ this->left_shift(MAX_SHIFT_AMOUNT);
+ shift_amount -= MAX_SHIFT_AMOUNT;
+ }
+ this->left_shift(shift_amount);
+ }
+ // Right
+ else {
+ while (static_cast<uint32_t>(shift_amount) < -MAX_SHIFT_AMOUNT) {
+ this->right_shift(MAX_SHIFT_AMOUNT);
+ shift_amount += MAX_SHIFT_AMOUNT;
+ }
+ this->right_shift(-shift_amount);
+ }
+ }
+
+ // Round the number represented to the closest value of unsigned int type T.
+ // This is done ignoring overflow.
+ template <class T>
+ LIBC_INLINE T
+ round_to_integer_type(RoundDirection round = RoundDirection::Nearest) {
+ T result = 0;
+ uint32_t cur_digit = 0;
+
+ while (static_cast<int32_t>(cur_digit) < this->decimal_point &&
+ cur_digit < this->num_digits) {
+ result = result * 10 + (this->digits[cur_digit]);
+ ++cur_digit;
+ }
+
+ // If there are implicit 0s at the end of the number, include those.
+ while (static_cast<int32_t>(cur_digit) < this->decimal_point) {
+ result *= 10;
+ ++cur_digit;
+ }
+ return result + static_cast<unsigned int>(
+ this->should_round_up(this->decimal_point, round));
+ }
+
+ // Extra functions for testing.
+
+ LIBC_INLINE uint8_t *get_digits() { return this->digits; }
+ LIBC_INLINE uint32_t get_num_digits() { return this->num_digits; }
+ LIBC_INLINE int32_t get_decimal_point() { return this->decimal_point; }
+ LIBC_INLINE void set_truncated(bool trunc) { this->truncated = trunc; }
+};
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
diff --git a/lib/libcxx/libc/src/__support/libc_assert.h b/lib/libcxx/libc/src/__support/libc_assert.h
new file mode 100644
index 0000000000..3db179ff67
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/libc_assert.h
@@ -0,0 +1,88 @@
+//===-- Definition of a libc internal assert macro --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
+#define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
+
+#include "src/__support/macros/config.h"
+#if defined(LIBC_COPT_USE_C_ASSERT) || !defined(LIBC_FULL_BUILD)
+
+// The build is configured to just use the public <assert.h> API
+// for libc's internal assertions.
+
+#include <assert.h>
+
+#define LIBC_ASSERT(COND) assert(COND)
+
+#else // Not LIBC_COPT_USE_C_ASSERT
+
+#include "src/__support/OSUtil/exit.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/__support/integer_to_string.h"
+#include "src/__support/macros/attributes.h" // For LIBC_INLINE
+#include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+// This is intended to be removed in a future patch to use a similar design to
+// below, but it's necessary for the external assert.
+LIBC_INLINE void report_assertion_failure(const char *assertion,
+ const char *filename, unsigned line,
+ const char *funcname) {
+ const IntegerToString<unsigned> line_buffer(line);
+ write_to_stderr(filename);
+ write_to_stderr(":");
+ write_to_stderr(line_buffer.view());
+ write_to_stderr(": Assertion failed: '");
+ write_to_stderr(assertion);
+ write_to_stderr("' in function: '");
+ write_to_stderr(funcname);
+ write_to_stderr("'\n");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_ASSERT
+#error "Unexpected: LIBC_ASSERT macro already defined"
+#endif
+
+// The public "assert" macro calls abort on failure. Should it be same here?
+// The libc internal assert can fire from anywhere inside the libc. So, to
+// avoid potential chicken-and-egg problems, it is simple to do an exit
+// on assertion failure instead of calling abort. We also don't want to use
+// __builtin_trap as it could potentially be implemented using illegal
+// instructions which can be very misleading when debugging.
+#ifdef NDEBUG
+#define LIBC_ASSERT(COND) \
+ do { \
+ } while (false)
+#else
+
+// Convert __LINE__ to a string using macros. The indirection is necessary
+// because otherwise it will turn "__LINE__" into a string, not its value. The
+// value is evaluated in the indirection step.
+#define __LIBC_MACRO_TO_STR(x) #x
+#define __LIBC_MACRO_TO_STR_INDIR(y) __LIBC_MACRO_TO_STR(y)
+#define __LIBC_LINE_STR__ __LIBC_MACRO_TO_STR_INDIR(__LINE__)
+
+#define LIBC_ASSERT(COND) \
+ do { \
+ if (LIBC_UNLIKELY(!(COND))) { \
+ LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \
+ ": Assertion failed: '" #COND \
+ "' in function: '"); \
+ LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \
+ LIBC_NAMESPACE::write_to_stderr("'\n"); \
+ LIBC_NAMESPACE::internal::exit(0xFF); \
+ } \
+ } while (false)
+#endif // NDEBUG
+
+#endif // LIBC_COPT_USE_C_ASSERT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
diff --git a/lib/libcxx/libc/src/__support/macros/attributes.h b/lib/libcxx/libc/src/__support/macros/attributes.h
new file mode 100644
index 0000000000..c6474673de
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/attributes.h
@@ -0,0 +1,51 @@
+//===-- Portable attributes -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This header file defines macros for declaring attributes for functions,
+// types, and variables.
+//
+// These macros are used within llvm-libc and allow the compiler to optimize,
+// where applicable, certain function calls.
+//
+// Most macros here are exposing GCC or Clang features, and are stubbed out for
+// other compilers.
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
+
+#include "properties/architectures.h"
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#define LIBC_INLINE inline
+#define LIBC_INLINE_VAR inline
+#define LIBC_INLINE_ASM __asm__ __volatile__
+#define LIBC_UNUSED __attribute__((unused))
+
+#ifdef LIBC_TARGET_ARCH_IS_GPU
+#define LIBC_THREAD_LOCAL
+#else
+#define LIBC_THREAD_LOCAL thread_local
+#endif
+
+#if __cplusplus >= 202002L
+#define LIBC_CONSTINIT constinit
+#elif __has_attribute(__require_constant_initialization__)
+#define LIBC_CONSTINIT __attribute__((__require_constant_initialization__))
+#else
+#define LIBC_CONSTINIT
+#endif
+
+#if defined(__clang__) && __has_attribute(preferred_type)
+#define LIBC_PREFERED_TYPE(TYPE) [[clang::preferred_type(TYPE)]]
+#else
+#define LIBC_PREFERED_TYPE(TYPE)
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
diff --git a/lib/libcxx/libc/src/__support/macros/config.h b/lib/libcxx/libc/src/__support/macros/config.h
new file mode 100644
index 0000000000..2ab0fba095
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/config.h
@@ -0,0 +1,46 @@
+//===-- Portable attributes -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This header file defines a set of macros for checking the presence of
+// important compiler and platform features. Such macros can be used to
+// produce portable code by parameterizing compilation based on the presence or
+// lack of a given feature.
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
+
+// Workaround for compilers that do not support builtin detection.
+// FIXME: This is only required for the GPU portion which should be moved.
+#ifndef __has_builtin
+#define __has_builtin(b) 0
+#endif
+
+// Compiler feature-detection.
+// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
+#ifdef __has_feature
+#define LIBC_HAS_FEATURE(f) __has_feature(f)
+#else
+#define LIBC_HAS_FEATURE(f) 0
+#endif
+
+#ifdef __clang__
+// Declare a LIBC_NAMESPACE with hidden visibility. `namespace
+// LIBC_NAMESPACE_DECL {` should be used around all declarations and definitions
+// for libc internals as opposed to just `namespace LIBC_NAMESPACE {`. This
+// ensures that all declarations within this namespace have hidden
+// visibility, which optimizes codegen for uses of symbols defined in other
+// translation units in ways that can be necessary for correctness by avoiding
+// dynamic relocations. This does not affect the public C symbols which are
+// controlled independently via `LLVM_LIBC_FUNCTION_ATTR`.
+#define LIBC_NAMESPACE_DECL [[gnu::visibility("hidden")]] LIBC_NAMESPACE
+#else
+// TODO(#98548): GCC emits a warning when using the visibility attribute which
+// needs to be diagnosed and addressed.
+#define LIBC_NAMESPACE_DECL LIBC_NAMESPACE
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
diff --git a/lib/libcxx/libc/src/__support/macros/null_check.h b/lib/libcxx/libc/src/__support/macros/null_check.h
new file mode 100644
index 0000000000..eda19f8892
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/null_check.h
@@ -0,0 +1,28 @@
+//===-- Safe nullptr check --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/sanitizer.h"
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+#define LIBC_CRASH_ON_NULLPTR(ptr) \
+ do { \
+ if (LIBC_UNLIKELY((ptr) == nullptr)) \
+ __builtin_trap(); \
+ } while (0)
+#else
+#define LIBC_CRASH_ON_NULLPTR(ptr) \
+ do { \
+ } while (0)
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H
diff --git a/lib/libcxx/libc/src/__support/macros/optimization.h b/lib/libcxx/libc/src/__support/macros/optimization.h
new file mode 100644
index 0000000000..a2634950d4
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/optimization.h
@@ -0,0 +1,61 @@
+//===-- Portable optimization macros ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This header file defines portable macros for performance optimization.
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG
+
+// We use a template to implement likely/unlikely to make sure that we don't
+// accidentally pass an integer.
+namespace LIBC_NAMESPACE_DECL {
+namespace details {
+template <typename T>
+LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
+ return __builtin_expect(value, expected);
+}
+} // namespace details
+} // namespace LIBC_NAMESPACE_DECL
+#define LIBC_LIKELY(x) LIBC_NAMESPACE::details::expects_bool_condition(x, true)
+#define LIBC_UNLIKELY(x) \
+ LIBC_NAMESPACE::details::expects_bool_condition(x, false)
+
+#if defined(LIBC_COMPILER_IS_CLANG)
+#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
+#elif defined(LIBC_COMPILER_IS_GCC)
+#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
+#else
+#error "Unhandled compiler"
+#endif
+
+// Defining optimization options for math functions.
+// TODO: Exporting this to public generated headers?
+#define LIBC_MATH_SKIP_ACCURATE_PASS 0x01
+#define LIBC_MATH_SMALL_TABLES 0x02
+#define LIBC_MATH_NO_ERRNO 0x04
+#define LIBC_MATH_NO_EXCEPT 0x08
+#define LIBC_MATH_FAST \
+ (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \
+ LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
+
+#ifndef LIBC_MATH
+#define LIBC_MATH 0
+#endif // LIBC_MATH
+
+#if (LIBC_MATH & LIBC_MATH_SKIP_ACCURATE_PASS)
+#define LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#endif
+
+#if (LIBC_MATH & LIBC_MATH_SMALL_TABLES)
+#define LIBC_MATH_HAS_SMALL_TABLES
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/architectures.h b/lib/libcxx/libc/src/__support/macros/properties/architectures.h
new file mode 100644
index 0000000000..c88956ff41
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/architectures.h
@@ -0,0 +1,64 @@
+//===-- Compile time architecture detection ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_ARCHITECTURES_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_ARCHITECTURES_H
+
+#if defined(__AMDGPU__)
+#define LIBC_TARGET_ARCH_IS_AMDGPU
+#endif
+
+#if defined(__NVPTX__)
+#define LIBC_TARGET_ARCH_IS_NVPTX
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_NVPTX) || defined(LIBC_TARGET_ARCH_IS_AMDGPU)
+#define LIBC_TARGET_ARCH_IS_GPU
+#endif
+
+#if defined(__pnacl__) || defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU)
+#define LIBC_TARGET_ARCH_IS_VM
+#endif
+
+#if (defined(_M_IX86) || defined(__i386__)) && !defined(LIBC_TARGET_ARCH_IS_VM)
+#define LIBC_TARGET_ARCH_IS_X86_32
+#endif
+
+#if (defined(_M_X64) || defined(__x86_64__)) && !defined(LIBC_TARGET_ARCH_IS_VM)
+#define LIBC_TARGET_ARCH_IS_X86_64
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_X86_32) || defined(LIBC_TARGET_ARCH_IS_X86_64)
+#define LIBC_TARGET_ARCH_IS_X86
+#endif
+
+#if (defined(__arm__) || defined(_M_ARM))
+#define LIBC_TARGET_ARCH_IS_ARM
+#endif
+
+#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
+#define LIBC_TARGET_ARCH_IS_AARCH64
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || defined(LIBC_TARGET_ARCH_IS_ARM)
+#define LIBC_TARGET_ARCH_IS_ANY_ARM
+#endif
+
+#if defined(__riscv) && (__riscv_xlen == 64)
+#define LIBC_TARGET_ARCH_IS_RISCV64
+#endif
+
+#if defined(__riscv) && (__riscv_xlen == 32)
+#define LIBC_TARGET_ARCH_IS_RISCV32
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_RISCV64) || defined(LIBC_TARGET_ARCH_IS_RISCV32)
+#define LIBC_TARGET_ARCH_IS_ANY_RISCV
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_ARCHITECTURES_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/compiler.h b/lib/libcxx/libc/src/__support/macros/properties/compiler.h
new file mode 100644
index 0000000000..b9ec0dd1de
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/compiler.h
@@ -0,0 +1,43 @@
+//===-- Compile time compiler detection -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
+
+// Example usage of compiler version checks
+// #if defined(LIBC_COMPILER_CLANG_VER)
+// # if LIBC_COMPILER_CLANG_VER < 1500
+// # warning "Libc only supports Clang 15 and later"
+// # endif
+// #elif defined(LIBC_COMPILER_GCC_VER)
+// # if LIBC_COMPILER_GCC_VER < 1500
+// # warning "Libc only supports GCC 15 and later"
+// # endif
+// #elif defined(LIBC_COMPILER_MSC_VER)
+// # if LIBC_COMPILER_MSC_VER < 1930
+// # warning "Libc only supports Visual Studio 2022 RTW (17.0) and later"
+// # endif
+// #endif
+
+#if defined(__clang__)
+#define LIBC_COMPILER_IS_CLANG
+#define LIBC_COMPILER_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+#define LIBC_COMPILER_IS_GCC
+#define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
+#endif
+
+#if defined(_MSC_VER)
+#define LIBC_COMPILER_IS_MSC
+// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+#define LIBC_COMPILER_MSC_VER (_MSC_VER)
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/complex_types.h b/lib/libcxx/libc/src/__support/macros/properties/complex_types.h
new file mode 100644
index 0000000000..ede4d6b7c7
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/complex_types.h
@@ -0,0 +1,30 @@
+//===-- Complex Types support -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Complex Types detection and support.
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
+
+#include "include/llvm-libc-types/cfloat128.h"
+#include "include/llvm-libc-types/cfloat16.h"
+#include "types.h"
+
+// -- cfloat16 support --------------------------------------------------------
+// LIBC_TYPES_HAS_CFLOAT16 and 'cfloat16' type is provided by
+// "include/llvm-libc-types/cfloat16.h"
+
+// -- cfloat128 support -------------------------------------------------------
+// LIBC_TYPES_HAS_CFLOAT128 and 'cfloat128' type are provided by
+// "include/llvm-libc-types/cfloat128.h"
+
+#if defined(LIBC_TYPES_HAS_CFLOAT128) && \
+ !defined(LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE)
+#define LIBC_TYPES_CFLOAT128_IS_NOT_COMPLEX_LONG_DOUBLE
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CTYPES_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/cpu_features.h b/lib/libcxx/libc/src/__support/macros/properties/cpu_features.h
new file mode 100644
index 0000000000..d2cea36751
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/cpu_features.h
@@ -0,0 +1,60 @@
+//===-- Compile time cpu feature detection ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This file lists target cpu features by introspecting compiler enabled
+// preprocessor definitions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CPU_FEATURES_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CPU_FEATURES_H
+
+#include "architectures.h"
+
+#if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC)
+#define LIBC_TARGET_CPU_HAS_FULLFP16
+#endif
+
+#if defined(__SSE2__)
+#define LIBC_TARGET_CPU_HAS_SSE2
+#endif
+
+#if defined(__SSE4_2__)
+#define LIBC_TARGET_CPU_HAS_SSE4_2
+#endif
+
+#if defined(__AVX__)
+#define LIBC_TARGET_CPU_HAS_AVX
+#endif
+
+#if defined(__AVX2__)
+#define LIBC_TARGET_CPU_HAS_AVX2
+#endif
+
+#if defined(__AVX512F__)
+#define LIBC_TARGET_CPU_HAS_AVX512F
+#endif
+
+#if defined(__AVX512BW__)
+#define LIBC_TARGET_CPU_HAS_AVX512BW
+#endif
+
+#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
+ defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA)
+#define LIBC_TARGET_CPU_HAS_FMA
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || \
+ (defined(LIBC_TARGET_ARCH_IS_X86_64) && \
+ defined(LIBC_TARGET_CPU_HAS_SSE4_2))
+#define LIBC_TARGET_CPU_HAS_NEAREST_INT
+#endif
+
+#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || defined(LIBC_TARGET_ARCH_IS_GPU)
+#define LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_CPU_FEATURES_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/os.h b/lib/libcxx/libc/src/__support/macros/properties/os.h
new file mode 100644
index 0000000000..807ce18127
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/os.h
@@ -0,0 +1,32 @@
+//===-- Target OS detection -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_OS_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_OS_H
+
+#if (defined(__freebsd__) || defined(__FreeBSD__))
+#define LIBC_TARGET_OS_IS_FREEBSD
+#endif
+
+#if defined(__ANDROID__)
+#define LIBC_TARGET_OS_IS_ANDROID
+#endif
+
+#if defined(__linux__) && !defined(LIBC_TARGET_OS_IS_FREEBSD) && \
+ !defined(LIBC_TARGET_OS_IS_ANDROID)
+#define LIBC_TARGET_OS_IS_LINUX
+#endif
+
+#if (defined(_WIN64) || defined(_WIN32))
+#define LIBC_TARGET_OS_IS_WINDOWS
+#endif
+
+#if defined(__Fuchsia__)
+#define LIBC_TARGET_OS_IS_FUCHSIA
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_OS_H
diff --git a/lib/libcxx/libc/src/__support/macros/properties/types.h b/lib/libcxx/libc/src/__support/macros/properties/types.h
new file mode 100644
index 0000000000..6293b9d4d2
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/properties/types.h
@@ -0,0 +1,61 @@
+//===-- Types support -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Types detection and support.
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
+
+#include "hdr/float_macros.h" // LDBL_MANT_DIG
+#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
+#include "include/llvm-libc-types/float128.h" // float128
+#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/macros/properties/os.h"
+
+#include <stdint.h> // UINT64_MAX, __SIZEOF_INT128__
+
+// 'long double' properties.
+#if (LDBL_MANT_DIG == 53)
+#define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
+#elif (LDBL_MANT_DIG == 64)
+#define LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
+#elif (LDBL_MANT_DIG == 113)
+#define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128
+#elif (LDBL_MANT_DIG == 106)
+#define LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
+#endif
+
+#if defined(LIBC_TYPES_HAS_FLOAT128) && \
+ !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
+#define LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
+#endif
+
+// int64 / uint64 support
+#if defined(UINT64_MAX)
+#define LIBC_TYPES_HAS_INT64
+#endif // UINT64_MAX
+
+// int128 / uint128 support
+#if defined(__SIZEOF_INT128__) && !defined(LIBC_TARGET_OS_IS_WINDOWS)
+#define LIBC_TYPES_HAS_INT128
+#endif // defined(__SIZEOF_INT128__)
+
+// -- float16 support ---------------------------------------------------------
+// LIBC_TYPES_HAS_FLOAT16 is provided by
+// "include/llvm-libc-macros/float16-macros.h"
+#ifdef LIBC_TYPES_HAS_FLOAT16
+// Type alias for internal use.
+using float16 = _Float16;
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+// -- float128 support --------------------------------------------------------
+// LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by
+// "include/llvm-libc-types/float128.h"
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
diff --git a/lib/libcxx/libc/src/__support/macros/sanitizer.h b/lib/libcxx/libc/src/__support/macros/sanitizer.h
new file mode 100644
index 0000000000..c20412e0f8
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/macros/sanitizer.h
@@ -0,0 +1,59 @@
+//===-- Convenient sanitizer macros -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H
+#define LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H
+
+#include "src/__support/macros/config.h" //LIBC_HAS_FEATURE
+
+//-----------------------------------------------------------------------------
+// Functions to unpoison memory
+//-----------------------------------------------------------------------------
+
+#if LIBC_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#define LIBC_HAS_ADDRESS_SANITIZER
+#endif
+
+#if LIBC_HAS_FEATURE(memory_sanitizer)
+#define LIBC_HAS_MEMORY_SANITIZER
+#endif
+
+#if LIBC_HAS_FEATURE(undefined_behavior_sanitizer)
+#define LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER
+#endif
+
+#if defined(LIBC_HAS_ADDRESS_SANITIZER) || \
+ defined(LIBC_HAS_MEMORY_SANITIZER) || \
+ defined(LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER)
+#define LIBC_HAS_SANITIZER
+#endif
+
+#ifdef LIBC_HAS_MEMORY_SANITIZER
+// Only perform MSAN unpoison in non-constexpr context.
+#include <sanitizer/msan_interface.h>
+#define MSAN_UNPOISON(addr, size) \
+ do { \
+ if (!__builtin_is_constant_evaluated()) \
+ __msan_unpoison(addr, size); \
+ } while (0)
+#else
+#define MSAN_UNPOISON(ptr, size)
+#endif
+
+#ifdef LIBC_HAS_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#define ASAN_POISON_MEMORY_REGION(addr, size) \
+ __asan_poison_memory_region((addr), (size))
+#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
+ __asan_unpoison_memory_region((addr), (size))
+#else
+#define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
+#define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
+#endif
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H
diff --git a/lib/libcxx/libc/src/__support/math_extras.h b/lib/libcxx/libc/src/__support/math_extras.h
new file mode 100644
index 0000000000..6f4a006aad
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/math_extras.h
@@ -0,0 +1,161 @@
+//===-- Mimics llvm/Support/MathExtras.h ------------------------*- C++ -*-===//
+// Provides useful math functions.
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
+
+#include "src/__support/CPP/bit.h" // countl_one, countr_zero
+#include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits
+#include "src/__support/CPP/type_traits.h" // is_unsigned_v, is_constant_evaluated
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Create a bitmask with the count right-most bits set to 1, and all other bits
+// set to 0. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+mask_trailing_ones() {
+ constexpr unsigned T_BITS = CHAR_BIT * sizeof(T);
+ static_assert(count <= T_BITS && "Invalid bit index");
+ return count == 0 ? 0 : (T(-1) >> (T_BITS - count));
+}
+
+// Create a bitmask with the count left-most bits set to 1, and all other bits
+// set to 0. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+mask_leading_ones() {
+ return T(~mask_trailing_ones<T, CHAR_BIT * sizeof(T) - count>());
+}
+
+// Create a bitmask with the count right-most bits set to 0, and all other bits
+// set to 1. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+mask_trailing_zeros() {
+ return mask_leading_ones<T, CHAR_BIT * sizeof(T) - count>();
+}
+
+// Create a bitmask with the count left-most bits set to 0, and all other bits
+// set to 1. Only unsigned types are allowed.
+template <typename T, size_t count>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+mask_leading_zeros() {
+ return mask_trailing_ones<T, CHAR_BIT * sizeof(T) - count>();
+}
+
+// Returns whether 'a + b' overflows, the result is stored in 'res'.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) {
+ return __builtin_add_overflow(a, b, &res);
+}
+
+// Returns whether 'a - b' overflows, the result is stored in 'res'.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) {
+ return __builtin_sub_overflow(a, b, &res);
+}
+
+#define RETURN_IF(TYPE, BUILTIN) \
+ if constexpr (cpp::is_same_v<T, TYPE>) \
+ return BUILTIN(a, b, carry_in, carry_out);
+
+// Returns the result of 'a + b' taking into account 'carry_in'.
+// The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise.
+// We keep the pass by pointer interface for consistency with the intrinsic.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+add_with_carry(T a, T b, T carry_in, T &carry_out) {
+ if constexpr (!cpp::is_constant_evaluated()) {
+#if __has_builtin(__builtin_addcb)
+ RETURN_IF(unsigned char, __builtin_addcb)
+#elif __has_builtin(__builtin_addcs)
+ RETURN_IF(unsigned short, __builtin_addcs)
+#elif __has_builtin(__builtin_addc)
+ RETURN_IF(unsigned int, __builtin_addc)
+#elif __has_builtin(__builtin_addcl)
+ RETURN_IF(unsigned long, __builtin_addcl)
+#elif __has_builtin(__builtin_addcll)
+ RETURN_IF(unsigned long long, __builtin_addcll)
+#endif
+ }
+ T sum = {};
+ T carry1 = add_overflow(a, b, sum);
+ T carry2 = add_overflow(sum, carry_in, sum);
+ carry_out = carry1 | carry2;
+ return sum;
+}
+
+// Returns the result of 'a - b' taking into account 'carry_in'.
+// The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise.
+// We keep the pass by pointer interface for consistency with the intrinsic.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
+sub_with_borrow(T a, T b, T carry_in, T &carry_out) {
+ if constexpr (!cpp::is_constant_evaluated()) {
+#if __has_builtin(__builtin_subcb)
+ RETURN_IF(unsigned char, __builtin_subcb)
+#elif __has_builtin(__builtin_subcs)
+ RETURN_IF(unsigned short, __builtin_subcs)
+#elif __has_builtin(__builtin_subc)
+ RETURN_IF(unsigned int, __builtin_subc)
+#elif __has_builtin(__builtin_subcl)
+ RETURN_IF(unsigned long, __builtin_subcl)
+#elif __has_builtin(__builtin_subcll)
+ RETURN_IF(unsigned long long, __builtin_subcll)
+#endif
+ }
+ T sub = {};
+ T carry1 = sub_overflow(a, b, sub);
+ T carry2 = sub_overflow(sub, carry_in, sub);
+ carry_out = carry1 | carry2;
+ return sub;
+}
+
+#undef RETURN_IF
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_leading_zero(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countl_one(value) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_leading_one(T value) {
+ return first_leading_zero(static_cast<T>(~value));
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_trailing_zero(T value) {
+ return value == cpp::numeric_limits<T>::max()
+ ? 0
+ : cpp::countr_zero(static_cast<T>(~value)) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+first_trailing_one(T value) {
+ return value == cpp::numeric_limits<T>::max() ? 0
+ : cpp::countr_zero(value) + 1;
+}
+
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
+count_zeros(T value) {
+ return cpp::popcount<T>(static_cast<T>(~value));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
diff --git a/lib/libcxx/libc/src/__support/number_pair.h b/lib/libcxx/libc/src/__support/number_pair.h
new file mode 100644
index 0000000000..f5e877406d
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/number_pair.h
@@ -0,0 +1,26 @@
+//===-- Utilities for pairs of numbers. -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_NUMBER_PAIR_H
+#define LLVM_LIBC_SRC___SUPPORT_NUMBER_PAIR_H
+
+#include "CPP/type_traits.h"
+#include "src/__support/macros/config.h"
+
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+template <typename T> struct NumberPair {
+ T lo = T(0);
+ T hi = T(0);
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_NUMBER_PAIR_H
diff --git a/lib/libcxx/libc/src/__support/sign.h b/lib/libcxx/libc/src/__support/sign.h
new file mode 100644
index 0000000000..4a629e4488
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/sign.h
@@ -0,0 +1,43 @@
+//===-- A simple sign type --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_SIGN_H
+#define LLVM_LIBC_SRC___SUPPORT_SIGN_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+
+namespace LIBC_NAMESPACE_DECL {
+
+// A type to interact with signed arithmetic types.
+struct Sign {
+ LIBC_INLINE constexpr bool is_pos() const { return !is_negative; }
+ LIBC_INLINE constexpr bool is_neg() const { return is_negative; }
+
+ LIBC_INLINE friend constexpr bool operator==(Sign a, Sign b) {
+ return a.is_negative == b.is_negative;
+ }
+
+ LIBC_INLINE friend constexpr bool operator!=(Sign a, Sign b) {
+ return !(a == b);
+ }
+
+ static const Sign POS;
+ static const Sign NEG;
+
+private:
+ LIBC_INLINE constexpr explicit Sign(bool is_negative)
+ : is_negative(is_negative) {}
+
+ bool is_negative;
+};
+
+LIBC_INLINE_VAR constexpr Sign Sign::NEG = Sign(true);
+LIBC_INLINE_VAR constexpr Sign Sign::POS = Sign(false);
+
+} // namespace LIBC_NAMESPACE_DECL
+#endif // LLVM_LIBC_SRC___SUPPORT_SIGN_H
diff --git a/lib/libcxx/libc/src/__support/str_to_float.h b/lib/libcxx/libc/src/__support/str_to_float.h
new file mode 100644
index 0000000000..b4d5646822
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/str_to_float.h
@@ -0,0 +1,1275 @@
+//===-- String to float conversion utils ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This file is shared with libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
+#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
+
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/ctype_utils.h"
+#include "src/__support/detailed_powers_of_ten.h"
+#include "src/__support/high_precision_decimal.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/str_to_integer.h"
+#include "src/__support/str_to_num_result.h"
+#include "src/__support/uint128.h"
+#include "src/errno/libc_errno.h" // For ERANGE
+
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+template <class T> struct ExpandedFloat {
+ typename fputil::FPBits<T>::StorageType mantissa;
+ int32_t exponent;
+};
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+template <class T> struct FloatConvertReturn {
+ ExpandedFloat<T> num = {0, 0};
+ int error = 0;
+};
+
+LIBC_INLINE uint64_t low64(const UInt128 &num) {
+ return static_cast<uint64_t>(num & 0xffffffffffffffff);
+}
+
+LIBC_INLINE uint64_t high64(const UInt128 &num) {
+ return static_cast<uint64_t>(num >> 64);
+}
+
+template <class T> LIBC_INLINE void set_implicit_bit(fputil::FPBits<T> &) {
+ return;
+}
+
+#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
+template <>
+LIBC_INLINE void
+set_implicit_bit<long double>(fputil::FPBits<long double> &result) {
+ result.set_implicit_bit(result.get_biased_exponent() != 0);
+}
+#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
+
+// This Eisel-Lemire implementation is based on the algorithm described in the
+// paper Number Parsing at a Gigabyte per Second, Software: Practice and
+// Experience 51 (8), 2021 (https://arxiv.org/abs/2101.11408), as well as the
+// description by Nigel Tao
+// (https://nigeltao.github.io/blog/2020/eisel-lemire.html) and the golang
+// implementation, also by Nigel Tao
+// (https://github.com/golang/go/blob/release-branch.go1.16/src/strconv/eisel_lemire.go#L25)
+// for some optimizations as well as handling 32 bit floats.
+template <class T>
+LIBC_INLINE cpp::optional<ExpandedFloat<T>>
+eisel_lemire(ExpandedFloat<T> init_num,
+ RoundDirection round = RoundDirection::Nearest) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType mantissa = init_num.mantissa;
+ int32_t exp10 = init_num.exponent;
+
+ if (sizeof(T) > 8) { // This algorithm cannot handle anything longer than a
+ // double, so we skip straight to the fallback.
+ return cpp::nullopt;
+ }
+
+ // Exp10 Range
+ if (exp10 < DETAILED_POWERS_OF_TEN_MIN_EXP_10 ||
+ exp10 > DETAILED_POWERS_OF_TEN_MAX_EXP_10) {
+ return cpp::nullopt;
+ }
+
+ // Normalization
+ uint32_t clz = cpp::countl_zero<StorageType>(mantissa);
+ mantissa <<= clz;
+
+ int32_t exp2 =
+ exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS - clz;
+
+ // Multiplication
+ const uint64_t *power_of_ten =
+ DETAILED_POWERS_OF_TEN[exp10 - DETAILED_POWERS_OF_TEN_MIN_EXP_10];
+
+ UInt128 first_approx =
+ static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[1]);
+
+ // Wider Approximation
+ UInt128 final_approx;
+ // The halfway constant is used to check if the bits that will be shifted away
+ // intially are all 1. For doubles this is 64 (bitstype size) - 52 (final
+ // mantissa size) - 3 (we shift away the last two bits separately for
+ // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly,
+ // it's 6 bits for floats in this case.
+ const uint64_t halfway_constant =
+ (uint64_t(1) << (FPBits::STORAGE_LEN - (FPBits::FRACTION_LEN + 3))) - 1;
+ if ((high64(first_approx) & halfway_constant) == halfway_constant &&
+ low64(first_approx) + mantissa < mantissa) {
+ UInt128 low_bits =
+ static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[0]);
+ UInt128 second_approx =
+ first_approx + static_cast<UInt128>(high64(low_bits));
+
+ if ((high64(second_approx) & halfway_constant) == halfway_constant &&
+ low64(second_approx) + 1 == 0 &&
+ low64(low_bits) + mantissa < mantissa) {
+ return cpp::nullopt;
+ }
+ final_approx = second_approx;
+ } else {
+ final_approx = first_approx;
+ }
+
+ // Shifting to 54 bits for doubles and 25 bits for floats
+ StorageType msb = static_cast<StorageType>(high64(final_approx) >>
+ (FPBits::STORAGE_LEN - 1));
+ StorageType final_mantissa = static_cast<StorageType>(
+ high64(final_approx) >>
+ (msb + FPBits::STORAGE_LEN - (FPBits::FRACTION_LEN + 3)));
+ exp2 -= static_cast<uint32_t>(1 ^ msb); // same as !msb
+
+ if (round == RoundDirection::Nearest) {
+ // Half-way ambiguity
+ if (low64(final_approx) == 0 &&
+ (high64(final_approx) & halfway_constant) == 0 &&
+ (final_mantissa & 3) == 1) {
+ return cpp::nullopt;
+ }
+
+ // Round to even.
+ final_mantissa += final_mantissa & 1;
+
+ } else if (round == RoundDirection::Up) {
+ // If any of the bits being rounded away are non-zero, then round up.
+ if (low64(final_approx) > 0 ||
+ (high64(final_approx) & halfway_constant) > 0) {
+ // Add two since the last current lowest bit is about to be shifted away.
+ final_mantissa += 2;
+ }
+ }
+ // else round down, which has no effect.
+
+ // From 54 to 53 bits for doubles and 25 to 24 bits for floats
+ final_mantissa >>= 1;
+ if ((final_mantissa >> (FPBits::FRACTION_LEN + 1)) > 0) {
+ final_mantissa >>= 1;
+ ++exp2;
+ }
+
+ // The if block is equivalent to (but has fewer branches than):
+ // if exp2 <= 0 || exp2 >= 0x7FF { etc }
+ if (static_cast<uint32_t>(exp2) - 1 >= (1 << FPBits::EXP_LEN) - 2) {
+ return cpp::nullopt;
+ }
+
+ ExpandedFloat<T> output;
+ output.mantissa = final_mantissa;
+ output.exponent = exp2;
+ return output;
+}
+
+// TODO: Re-enable eisel-lemire for long double is double double once it's
+// properly supported.
+#if !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) && \
+ !defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE)
+template <>
+LIBC_INLINE cpp::optional<ExpandedFloat<long double>>
+eisel_lemire<long double>(ExpandedFloat<long double> init_num,
+ RoundDirection round) {
+ using FPBits = typename fputil::FPBits<long double>;
+ using StorageType = typename FPBits::StorageType;
+
+ UInt128 mantissa = init_num.mantissa;
+ int32_t exp10 = init_num.exponent;
+
+ // Exp10 Range
+ // This doesn't reach very far into the range for long doubles, since it's
+ // sized for doubles and their 11 exponent bits, and not for long doubles and
+ // their 15 exponent bits (max exponent of ~300 for double vs ~5000 for long
+ // double). This is a known tradeoff, and was made because a proper long
+ // double table would be approximately 16 times larger. This would have
+ // significant memory and storage costs all the time to speed up a relatively
+ // uncommon path. In addition the exp10_to_exp2 function only approximates
+ // multiplying by log(10)/log(2), and that approximation may not be accurate
+ // out to the full long double range.
+ if (exp10 < DETAILED_POWERS_OF_TEN_MIN_EXP_10 ||
+ exp10 > DETAILED_POWERS_OF_TEN_MAX_EXP_10) {
+ return cpp::nullopt;
+ }
+
+ // Normalization
+ uint32_t clz = cpp::countl_zero(mantissa) -
+ ((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT);
+ mantissa <<= clz;
+
+ int32_t exp2 =
+ exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS - clz;
+
+ // Multiplication
+ const uint64_t *power_of_ten =
+ DETAILED_POWERS_OF_TEN[exp10 - DETAILED_POWERS_OF_TEN_MIN_EXP_10];
+
+ // Since the input mantissa is more than 64 bits, we have to multiply with the
+ // full 128 bits of the power of ten to get an approximation with the same
+ // number of significant bits. This means that we only get the one
+ // approximation, and that approximation is 256 bits long.
+ UInt128 approx_upper = static_cast<UInt128>(high64(mantissa)) *
+ static_cast<UInt128>(power_of_ten[1]);
+
+ UInt128 approx_middle_a = static_cast<UInt128>(high64(mantissa)) *
+ static_cast<UInt128>(power_of_ten[0]);
+ UInt128 approx_middle_b = static_cast<UInt128>(low64(mantissa)) *
+ static_cast<UInt128>(power_of_ten[1]);
+
+ UInt128 approx_middle = approx_middle_a + approx_middle_b;
+
+ // Handle overflow in the middle
+ approx_upper += (approx_middle < approx_middle_a) ? UInt128(1) << 64 : 0;
+
+ UInt128 approx_lower = static_cast<UInt128>(low64(mantissa)) *
+ static_cast<UInt128>(power_of_ten[0]);
+
+ UInt128 final_approx_lower =
+ approx_lower + (static_cast<UInt128>(low64(approx_middle)) << 64);
+ UInt128 final_approx_upper = approx_upper + high64(approx_middle) +
+ (final_approx_lower < approx_lower ? 1 : 0);
+
+ // The halfway constant is used to check if the bits that will be shifted away
+ // intially are all 1. For 80 bit floats this is 128 (bitstype size) - 64
+ // (final mantissa size) - 3 (we shift away the last two bits separately for
+ // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly,
+ // it's 12 bits for 128 bit floats in this case.
+ constexpr UInt128 HALFWAY_CONSTANT =
+ (UInt128(1) << (FPBits::STORAGE_LEN - (FPBits::FRACTION_LEN + 3))) - 1;
+
+ if ((final_approx_upper & HALFWAY_CONSTANT) == HALFWAY_CONSTANT &&
+ final_approx_lower + mantissa < mantissa) {
+ return cpp::nullopt;
+ }
+
+ // Shifting to 65 bits for 80 bit floats and 113 bits for 128 bit floats
+ uint32_t msb =
+ static_cast<uint32_t>(final_approx_upper >> (FPBits::STORAGE_LEN - 1));
+ UInt128 final_mantissa = final_approx_upper >> (msb + FPBits::STORAGE_LEN -
+ (FPBits::FRACTION_LEN + 3));
+ exp2 -= static_cast<uint32_t>(1 ^ msb); // same as !msb
+
+ if (round == RoundDirection::Nearest) {
+ // Half-way ambiguity
+ if (final_approx_lower == 0 &&
+ (final_approx_upper & HALFWAY_CONSTANT) == 0 &&
+ (final_mantissa & 3) == 1) {
+ return cpp::nullopt;
+ }
+ // Round to even.
+ final_mantissa += final_mantissa & 1;
+
+ } else if (round == RoundDirection::Up) {
+ // If any of the bits being rounded away are non-zero, then round up.
+ if (final_approx_lower > 0 || (final_approx_upper & HALFWAY_CONSTANT) > 0) {
+ // Add two since the last current lowest bit is about to be shifted away.
+ final_mantissa += 2;
+ }
+ }
+ // else round down, which has no effect.
+
+ // From 65 to 64 bits for 80 bit floats and 113 to 112 bits for 128 bit
+ // floats
+ final_mantissa >>= 1;
+ if ((final_mantissa >> (FPBits::FRACTION_LEN + 1)) > 0) {
+ final_mantissa >>= 1;
+ ++exp2;
+ }
+
+ // The if block is equivalent to (but has fewer branches than):
+ // if exp2 <= 0 || exp2 >= MANTISSA_MAX { etc }
+ if (exp2 - 1 >= (1 << FPBits::EXP_LEN) - 2) {
+ return cpp::nullopt;
+ }
+
+ ExpandedFloat<long double> output;
+ output.mantissa = static_cast<StorageType>(final_mantissa);
+ output.exponent = exp2;
+ return output;
+}
+#endif // !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) &&
+ // !defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE)
+
+// The nth item in POWERS_OF_TWO represents the greatest power of two less than
+// 10^n. This tells us how much we can safely shift without overshooting.
+constexpr uint8_t POWERS_OF_TWO[19] = {
+ 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59,
+};
+constexpr int32_t NUM_POWERS_OF_TWO =
+ sizeof(POWERS_OF_TWO) / sizeof(POWERS_OF_TWO[0]);
+
+// Takes a mantissa and base 10 exponent and converts it into its closest
+// floating point type T equivalent. This is the fallback algorithm used when
+// the Eisel-Lemire algorithm fails, it's slower but more accurate. It's based
+// on the Simple Decimal Conversion algorithm by Nigel Tao, described at this
+// link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
+template <class T>
+LIBC_INLINE FloatConvertReturn<T> simple_decimal_conversion(
+ const char *__restrict numStart,
+ const size_t num_len = cpp::numeric_limits<size_t>::max(),
+ RoundDirection round = RoundDirection::Nearest) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ int32_t exp2 = 0;
+ HighPrecisionDecimal hpd = HighPrecisionDecimal(numStart, num_len);
+
+ FloatConvertReturn<T> output;
+
+ if (hpd.get_num_digits() == 0) {
+ output.num = {0, 0};
+ return output;
+ }
+
+ // If the exponent is too large and can't be represented in this size of
+ // float, return inf.
+ if (hpd.get_decimal_point() > 0 &&
+ exp10_to_exp2(hpd.get_decimal_point() - 1) > FPBits::EXP_BIAS) {
+ output.num = {0, fputil::FPBits<T>::MAX_BIASED_EXPONENT};
+ output.error = ERANGE;
+ return output;
+ }
+ // If the exponent is too small even for a subnormal, return 0.
+ if (hpd.get_decimal_point() < 0 &&
+ exp10_to_exp2(-hpd.get_decimal_point()) >
+ (FPBits::EXP_BIAS + static_cast<int32_t>(FPBits::FRACTION_LEN))) {
+ output.num = {0, 0};
+ output.error = ERANGE;
+ return output;
+ }
+
+ // Right shift until the number is smaller than 1.
+ while (hpd.get_decimal_point() > 0) {
+ int32_t shift_amount = 0;
+ if (hpd.get_decimal_point() >= NUM_POWERS_OF_TWO) {
+ shift_amount = 60;
+ } else {
+ shift_amount = POWERS_OF_TWO[hpd.get_decimal_point()];
+ }
+ exp2 += shift_amount;
+ hpd.shift(-shift_amount);
+ }
+
+ // Left shift until the number is between 1/2 and 1
+ while (hpd.get_decimal_point() < 0 ||
+ (hpd.get_decimal_point() == 0 && hpd.get_digits()[0] < 5)) {
+ int32_t shift_amount = 0;
+
+ if (-hpd.get_decimal_point() >= NUM_POWERS_OF_TWO) {
+ shift_amount = 60;
+ } else if (hpd.get_decimal_point() != 0) {
+ shift_amount = POWERS_OF_TWO[-hpd.get_decimal_point()];
+ } else { // This handles the case of the number being between .1 and .5
+ shift_amount = 1;
+ }
+ exp2 -= shift_amount;
+ hpd.shift(shift_amount);
+ }
+
+ // Left shift once so that the number is between 1 and 2
+ --exp2;
+ hpd.shift(1);
+
+ // Get the biased exponent
+ exp2 += FPBits::EXP_BIAS;
+
+ // Handle the exponent being too large (and return inf).
+ if (exp2 >= FPBits::MAX_BIASED_EXPONENT) {
+ output.num = {0, FPBits::MAX_BIASED_EXPONENT};
+ output.error = ERANGE;
+ return output;
+ }
+
+ // Shift left to fill the mantissa
+ hpd.shift(FPBits::FRACTION_LEN);
+ StorageType final_mantissa = hpd.round_to_integer_type<StorageType>();
+
+ // Handle subnormals
+ if (exp2 <= 0) {
+ // Shift right until there is a valid exponent
+ while (exp2 < 0) {
+ hpd.shift(-1);
+ ++exp2;
+ }
+ // Shift right one more time to compensate for the left shift to get it
+ // between 1 and 2.
+ hpd.shift(-1);
+ final_mantissa = hpd.round_to_integer_type<StorageType>(round);
+
+ // Check if by shifting right we've caused this to round to a normal number.
+ if ((final_mantissa >> FPBits::FRACTION_LEN) != 0) {
+ ++exp2;
+ }
+ }
+
+ // Check if rounding added a bit, and shift down if that's the case.
+ if (final_mantissa == StorageType(2) << FPBits::FRACTION_LEN) {
+ final_mantissa >>= 1;
+ ++exp2;
+
+ // Check if this rounding causes exp2 to go out of range and make the result
+ // INF. If this is the case, then finalMantissa and exp2 are already the
+ // correct values for an INF result.
+ if (exp2 >= FPBits::MAX_BIASED_EXPONENT) {
+ output.error = ERANGE;
+ }
+ }
+
+ if (exp2 == 0) {
+ output.error = ERANGE;
+ }
+
+ output.num = {final_mantissa, exp2};
+ return output;
+}
+
+// This class is used for templating the constants for Clinger's Fast Path,
+// described as a method of approximation in
+// Clinger WD. How to Read Floating Point Numbers Accurately. SIGPLAN Not 1990
+// Jun;25(6):92–101. https://doi.org/10.1145/93548.93557.
+// As well as the additions by Gay that extend the useful range by the number of
+// exact digits stored by the float type, described in
+// Gay DM, Correctly rounded binary-decimal and decimal-binary conversions;
+// 1990. AT&T Bell Laboratories Numerical Analysis Manuscript 90-10.
+template <class T> class ClingerConsts;
+
+template <> class ClingerConsts<float> {
+public:
+ static constexpr float POWERS_OF_TEN_ARRAY[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5,
+ 1e6, 1e7, 1e8, 1e9, 1e10};
+ static constexpr int32_t EXACT_POWERS_OF_TEN = 10;
+ static constexpr int32_t DIGITS_IN_MANTISSA = 7;
+ static constexpr float MAX_EXACT_INT = 16777215.0;
+};
+
+template <> class ClingerConsts<double> {
+public:
+ static constexpr double POWERS_OF_TEN_ARRAY[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+ static constexpr int32_t EXACT_POWERS_OF_TEN = 22;
+ static constexpr int32_t DIGITS_IN_MANTISSA = 15;
+ static constexpr double MAX_EXACT_INT = 9007199254740991.0;
+};
+
+#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
+template <> class ClingerConsts<long double> {
+public:
+ static constexpr long double POWERS_OF_TEN_ARRAY[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+ static constexpr int32_t EXACT_POWERS_OF_TEN =
+ ClingerConsts<double>::EXACT_POWERS_OF_TEN;
+ static constexpr int32_t DIGITS_IN_MANTISSA =
+ ClingerConsts<double>::DIGITS_IN_MANTISSA;
+ static constexpr long double MAX_EXACT_INT =
+ ClingerConsts<double>::MAX_EXACT_INT;
+};
+#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
+template <> class ClingerConsts<long double> {
+public:
+ static constexpr long double POWERS_OF_TEN_ARRAY[] = {
+ 1e0L, 1e1L, 1e2L, 1e3L, 1e4L, 1e5L, 1e6L, 1e7L, 1e8L, 1e9L,
+ 1e10L, 1e11L, 1e12L, 1e13L, 1e14L, 1e15L, 1e16L, 1e17L, 1e18L, 1e19L,
+ 1e20L, 1e21L, 1e22L, 1e23L, 1e24L, 1e25L, 1e26L, 1e27L};
+ static constexpr int32_t EXACT_POWERS_OF_TEN = 27;
+ static constexpr int32_t DIGITS_IN_MANTISSA = 21;
+ static constexpr long double MAX_EXACT_INT = 18446744073709551615.0L;
+};
+#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
+template <> class ClingerConsts<long double> {
+public:
+ static constexpr long double POWERS_OF_TEN_ARRAY[] = {
+ 1e0L, 1e1L, 1e2L, 1e3L, 1e4L, 1e5L, 1e6L, 1e7L, 1e8L, 1e9L,
+ 1e10L, 1e11L, 1e12L, 1e13L, 1e14L, 1e15L, 1e16L, 1e17L, 1e18L, 1e19L,
+ 1e20L, 1e21L, 1e22L, 1e23L, 1e24L, 1e25L, 1e26L, 1e27L, 1e28L, 1e29L,
+ 1e30L, 1e31L, 1e32L, 1e33L, 1e34L, 1e35L, 1e36L, 1e37L, 1e38L, 1e39L,
+ 1e40L, 1e41L, 1e42L, 1e43L, 1e44L, 1e45L, 1e46L, 1e47L, 1e48L};
+ static constexpr int32_t EXACT_POWERS_OF_TEN = 48;
+ static constexpr int32_t DIGITS_IN_MANTISSA = 33;
+ static constexpr long double MAX_EXACT_INT =
+ 10384593717069655257060992658440191.0L;
+};
+#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE)
+// TODO: Add proper double double type support here, currently using constants
+// for double since it should be safe.
+template <> class ClingerConsts<long double> {
+public:
+ static constexpr double POWERS_OF_TEN_ARRAY[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
+ 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
+ static constexpr int32_t EXACT_POWERS_OF_TEN = 22;
+ static constexpr int32_t DIGITS_IN_MANTISSA = 15;
+ static constexpr double MAX_EXACT_INT = 9007199254740991.0;
+};
+#else
+#error "Unknown long double type"
+#endif
+
+// Take an exact mantissa and exponent and attempt to convert it using only
+// exact floating point arithmetic. This only handles numbers with low
+// exponents, but handles them quickly. This is an implementation of Clinger's
+// Fast Path, as described above.
+template <class T>
+LIBC_INLINE cpp::optional<ExpandedFloat<T>>
+clinger_fast_path(ExpandedFloat<T> init_num,
+ RoundDirection round = RoundDirection::Nearest) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType mantissa = init_num.mantissa;
+ int32_t exp10 = init_num.exponent;
+
+ if ((mantissa >> FPBits::FRACTION_LEN) > 0) {
+ return cpp::nullopt;
+ }
+
+ FPBits result;
+ T float_mantissa;
+ if constexpr (is_big_int_v<StorageType> || sizeof(T) > sizeof(uint64_t)) {
+ float_mantissa =
+ (static_cast<T>(uint64_t(mantissa >> 64)) * static_cast<T>(0x1.0p64)) +
+ static_cast<T>(uint64_t(mantissa));
+ } else {
+ float_mantissa = static_cast<T>(mantissa);
+ }
+
+ if (exp10 == 0) {
+ result = FPBits(float_mantissa);
+ }
+ if (exp10 > 0) {
+ if (exp10 > ClingerConsts<T>::EXACT_POWERS_OF_TEN +
+ ClingerConsts<T>::DIGITS_IN_MANTISSA) {
+ return cpp::nullopt;
+ }
+ if (exp10 > ClingerConsts<T>::EXACT_POWERS_OF_TEN) {
+ float_mantissa = float_mantissa *
+ ClingerConsts<T>::POWERS_OF_TEN_ARRAY
+ [exp10 - ClingerConsts<T>::EXACT_POWERS_OF_TEN];
+ exp10 = ClingerConsts<T>::EXACT_POWERS_OF_TEN;
+ }
+ if (float_mantissa > ClingerConsts<T>::MAX_EXACT_INT) {
+ return cpp::nullopt;
+ }
+ result =
+ FPBits(float_mantissa * ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
+ } else if (exp10 < 0) {
+ if (-exp10 > ClingerConsts<T>::EXACT_POWERS_OF_TEN) {
+ return cpp::nullopt;
+ }
+ result =
+ FPBits(float_mantissa / ClingerConsts<T>::POWERS_OF_TEN_ARRAY[-exp10]);
+ }
+
+ // If the rounding mode is not nearest, then the sign of the number may affect
+ // the result. To make sure the rounding mode is respected properly, the
+ // calculation is redone with a negative result, and the rounding mode is used
+ // to select the correct result.
+ if (round != RoundDirection::Nearest) {
+ FPBits negative_result;
+ // I'm 99% sure this will break under fast math optimizations.
+ negative_result = FPBits((-float_mantissa) *
+ ClingerConsts<T>::POWERS_OF_TEN_ARRAY[exp10]);
+
+ // If the results are equal, then we don't need to use the rounding mode.
+ if (result.get_val() != -negative_result.get_val()) {
+ FPBits lower_result;
+ FPBits higher_result;
+
+ if (result.get_val() < -negative_result.get_val()) {
+ lower_result = result;
+ higher_result = negative_result;
+ } else {
+ lower_result = negative_result;
+ higher_result = result;
+ }
+
+ if (round == RoundDirection::Up) {
+ result = higher_result;
+ } else {
+ result = lower_result;
+ }
+ }
+ }
+
+ ExpandedFloat<T> output;
+ output.mantissa = result.get_explicit_mantissa();
+ output.exponent = result.get_biased_exponent();
+ return output;
+}
+
+// The upper bound is the highest base-10 exponent that could possibly give a
+// non-inf result for this size of float. The value is
+// log10(2^(exponent bias)).
+// The generic approximation uses the fact that log10(2^x) ~= x/3
+template <typename T> LIBC_INLINE constexpr int32_t get_upper_bound() {
+ return fputil::FPBits<T>::EXP_BIAS / 3;
+}
+
+template <> LIBC_INLINE constexpr int32_t get_upper_bound<float>() {
+ return 39;
+}
+
+template <> LIBC_INLINE constexpr int32_t get_upper_bound<double>() {
+ return 309;
+}
+
+// The lower bound is the largest negative base-10 exponent that could possibly
+// give a non-zero result for this size of float. The value is
+// log10(2^(exponent bias + final mantissa width + intermediate mantissa width))
+// The intermediate mantissa is the integer that's been parsed from the string,
+// and the final mantissa is the fractional part of the output number. A very
+// low base 10 exponent with a very high intermediate mantissa can cancel each
+// other out, and subnormal numbers allow for the result to be at the very low
+// end of the final mantissa.
+template <typename T> LIBC_INLINE constexpr int32_t get_lower_bound() {
+ using FPBits = typename fputil::FPBits<T>;
+ return -((FPBits::EXP_BIAS +
+ static_cast<int32_t>(FPBits::FRACTION_LEN + FPBits::STORAGE_LEN)) /
+ 3);
+}
+
+template <> LIBC_INLINE constexpr int32_t get_lower_bound<float>() {
+ return -(39 + 6 + 10);
+}
+
+template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() {
+ return -(309 + 15 + 20);
+}
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+// Takes a mantissa and base 10 exponent and converts it into its closest
+// floating point type T equivalient. First we try the Eisel-Lemire algorithm,
+// then if that fails then we fall back to a more accurate algorithm for
+// accuracy. The resulting mantissa and exponent are placed in outputMantissa
+// and outputExp2.
+template <class T>
+LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float(
+ ExpandedFloat<T> init_num, bool truncated, RoundDirection round,
+ const char *__restrict numStart,
+ const size_t num_len = cpp::numeric_limits<size_t>::max()) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType mantissa = init_num.mantissa;
+ int32_t exp10 = init_num.exponent;
+
+ FloatConvertReturn<T> output;
+ cpp::optional<ExpandedFloat<T>> opt_output;
+
+ // If the exponent is too large and can't be represented in this size of
+ // float, return inf. These bounds are relatively loose, but are mostly
+ // serving as a first pass. Some close numbers getting through is okay.
+ if (exp10 > get_upper_bound<T>()) {
+ output.num = {0, FPBits::MAX_BIASED_EXPONENT};
+ output.error = ERANGE;
+ return output;
+ }
+ // If the exponent is too small even for a subnormal, return 0.
+ if (exp10 < get_lower_bound<T>()) {
+ output.num = {0, 0};
+ output.error = ERANGE;
+ return output;
+ }
+
+ // Clinger's Fast Path and Eisel-Lemire can't set errno, but they can fail.
+ // For this reason the "error" field in their return values is used to
+ // represent whether they've failed as opposed to the errno value. Any
+ // non-zero value represents a failure.
+
+#ifndef LIBC_COPT_STRTOFLOAT_DISABLE_CLINGER_FAST_PATH
+ if (!truncated) {
+ opt_output = clinger_fast_path<T>(init_num, round);
+ // If the algorithm succeeded the error will be 0, else it will be a
+ // non-zero number.
+ if (opt_output.has_value()) {
+ return {opt_output.value(), 0};
+ }
+ }
+#endif // LIBC_COPT_STRTOFLOAT_DISABLE_CLINGER_FAST_PATH
+
+#ifndef LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE
+ // Try Eisel-Lemire
+ opt_output = eisel_lemire<T>(init_num, round);
+ if (opt_output.has_value()) {
+ if (!truncated) {
+ return {opt_output.value(), 0};
+ }
+ // If the mantissa is truncated, then the result may be off by the LSB, so
+ // check if rounding the mantissa up changes the result. If not, then it's
+ // safe, else use the fallback.
+ auto second_output = eisel_lemire<T>({mantissa + 1, exp10}, round);
+ if (second_output.has_value()) {
+ if (opt_output->mantissa == second_output->mantissa &&
+ opt_output->exponent == second_output->exponent) {
+ return {opt_output.value(), 0};
+ }
+ }
+ }
+#endif // LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE
+
+#ifndef LIBC_COPT_STRTOFLOAT_DISABLE_SIMPLE_DECIMAL_CONVERSION
+ output = simple_decimal_conversion<T>(numStart, num_len, round);
+#else
+#warning "Simple decimal conversion is disabled, result may not be correct."
+#endif // LIBC_COPT_STRTOFLOAT_DISABLE_SIMPLE_DECIMAL_CONVERSION
+
+ return output;
+}
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+// Takes a mantissa and base 2 exponent and converts it into its closest
+// floating point type T equivalient. Since the exponent is already in the right
+// form, this is mostly just shifting and rounding. This is used for hexadecimal
+// numbers since a base 16 exponent multiplied by 4 is the base 2 exponent.
+template <class T>
+LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
+ bool truncated,
+ RoundDirection round) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType mantissa = init_num.mantissa;
+ int32_t exp2 = init_num.exponent;
+
+ FloatConvertReturn<T> output;
+
+ // This is the number of leading zeroes a properly normalized float of type T
+ // should have.
+ constexpr int32_t INF_EXP = (1 << FPBits::EXP_LEN) - 1;
+
+ // Normalization step 1: Bring the leading bit to the highest bit of
+ // StorageType.
+ uint32_t amount_to_shift_left = cpp::countl_zero<StorageType>(mantissa);
+ mantissa <<= amount_to_shift_left;
+
+ // Keep exp2 representing the exponent of the lowest bit of StorageType.
+ exp2 -= amount_to_shift_left;
+
+ // biased_exponent represents the biased exponent of the most significant bit.
+ int32_t biased_exponent = exp2 + FPBits::STORAGE_LEN + FPBits::EXP_BIAS - 1;
+
+ // Handle numbers that're too large and get squashed to inf
+ if (biased_exponent >= INF_EXP) {
+ // This indicates an overflow, so we make the result INF and set errno.
+ output.num = {0, (1 << FPBits::EXP_LEN) - 1};
+ output.error = ERANGE;
+ return output;
+ }
+
+ uint32_t amount_to_shift_right =
+ FPBits::STORAGE_LEN - FPBits::FRACTION_LEN - 1;
+
+ // Handle subnormals.
+ if (biased_exponent <= 0) {
+ amount_to_shift_right += 1 - biased_exponent;
+ biased_exponent = 0;
+
+ if (amount_to_shift_right > FPBits::STORAGE_LEN) {
+ // Return 0 if the exponent is too small.
+ output.num = {0, 0};
+ output.error = ERANGE;
+ return output;
+ }
+ }
+
+ StorageType round_bit_mask = StorageType(1) << (amount_to_shift_right - 1);
+ StorageType sticky_mask = round_bit_mask - 1;
+ bool round_bit = static_cast<bool>(mantissa & round_bit_mask);
+ bool sticky_bit = static_cast<bool>(mantissa & sticky_mask) || truncated;
+
+ if (amount_to_shift_right < FPBits::STORAGE_LEN) {
+ // Shift the mantissa and clear the implicit bit.
+ mantissa >>= amount_to_shift_right;
+ mantissa &= FPBits::FRACTION_MASK;
+ } else {
+ mantissa = 0;
+ }
+ bool least_significant_bit = static_cast<bool>(mantissa & StorageType(1));
+
+ // TODO: check that this rounding behavior is correct.
+
+ if (round == RoundDirection::Nearest) {
+ // Perform rounding-to-nearest, tie-to-even.
+ if (round_bit && (least_significant_bit || sticky_bit)) {
+ ++mantissa;
+ }
+ } else if (round == RoundDirection::Up) {
+ if (round_bit || sticky_bit) {
+ ++mantissa;
+ }
+ } else /* (round == RoundDirection::Down)*/ {
+ if (round_bit && sticky_bit) {
+ ++mantissa;
+ }
+ }
+
+ if (mantissa > FPBits::FRACTION_MASK) {
+ // Rounding causes the exponent to increase.
+ ++biased_exponent;
+
+ if (biased_exponent == INF_EXP) {
+ output.error = ERANGE;
+ }
+ }
+
+ if (biased_exponent == 0) {
+ output.error = ERANGE;
+ }
+
+ output.num = {mantissa & FPBits::FRACTION_MASK, biased_exponent};
+ return output;
+}
+
+// checks if the next 4 characters of the string pointer are the start of a
+// hexadecimal floating point number. Does not advance the string pointer.
+LIBC_INLINE bool is_float_hex_start(const char *__restrict src,
+ const char decimalPoint) {
+ if (!(src[0] == '0' && tolower(src[1]) == 'x')) {
+ return false;
+ }
+ size_t first_digit = 2;
+ if (src[2] == decimalPoint) {
+ ++first_digit;
+ }
+ return isalnum(src[first_digit]) && b36_char_to_int(src[first_digit]) < 16;
+}
+
+// Takes the start of a string representing a decimal float, as well as the
+// local decimalPoint. It returns if it suceeded in parsing any digits, and if
+// the return value is true then the outputs are pointer to the end of the
+// number, and the mantissa and exponent for the closest float T representation.
+// If the return value is false, then it is assumed that there is no number
+// here.
+template <class T>
+LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
+decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
+ RoundDirection round) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ constexpr uint32_t BASE = 10;
+ constexpr char EXPONENT_MARKER = 'e';
+
+ bool truncated = false;
+ bool seen_digit = false;
+ bool after_decimal = false;
+ StorageType mantissa = 0;
+ int32_t exponent = 0;
+
+ size_t index = 0;
+
+ StrToNumResult<ExpandedFloat<T>> output({0, 0});
+
+ // The goal for the first step of parsing is to convert the number in src to
+ // the format mantissa * (base ^ exponent)
+
+ // The loop fills the mantissa with as many digits as it can hold
+ const StorageType bitstype_max_div_by_base =
+ cpp::numeric_limits<StorageType>::max() / BASE;
+ while (true) {
+ if (isdigit(src[index])) {
+ uint32_t digit = b36_char_to_int(src[index]);
+ seen_digit = true;
+
+ if (mantissa < bitstype_max_div_by_base) {
+ mantissa = (mantissa * BASE) + digit;
+ if (after_decimal) {
+ --exponent;
+ }
+ } else {
+ if (digit > 0)
+ truncated = true;
+ if (!after_decimal)
+ ++exponent;
+ }
+
+ ++index;
+ continue;
+ }
+ if (src[index] == DECIMAL_POINT) {
+ if (after_decimal) {
+ break; // this means that src[index] points to a second decimal point,
+ // ending the number.
+ }
+ after_decimal = true;
+ ++index;
+ continue;
+ }
+ // The character is neither a digit nor a decimal point.
+ break;
+ }
+
+ if (!seen_digit)
+ return output;
+
+ // TODO: When adding max length argument, handle the case of a trailing
+ // EXPONENT MARKER, see scanf for more details.
+ if (tolower(src[index]) == EXPONENT_MARKER) {
+ bool has_sign = false;
+ if (src[index + 1] == '+' || src[index + 1] == '-') {
+ has_sign = true;
+ }
+ if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) {
+ ++index;
+ auto result = strtointeger<int32_t>(src + index, 10);
+ if (result.has_error())
+ output.error = result.error;
+ int32_t add_to_exponent = result.value;
+ index += result.parsed_len;
+
+ // Here we do this operation as int64 to avoid overflow.
+ int64_t temp_exponent = static_cast<int64_t>(exponent) +
+ static_cast<int64_t>(add_to_exponent);
+
+ // If the result is in the valid range, then we use it. The valid range is
+ // also within the int32 range, so this prevents overflow issues.
+ if (temp_exponent > FPBits::MAX_BIASED_EXPONENT) {
+ exponent = FPBits::MAX_BIASED_EXPONENT;
+ } else if (temp_exponent < -FPBits::MAX_BIASED_EXPONENT) {
+ exponent = -FPBits::MAX_BIASED_EXPONENT;
+ } else {
+ exponent = static_cast<int32_t>(temp_exponent);
+ }
+ }
+ }
+
+ output.parsed_len = index;
+ if (mantissa == 0) { // if we have a 0, then also 0 the exponent.
+ output.value = {0, 0};
+ } else {
+ auto temp =
+ decimal_exp_to_float<T>({mantissa, exponent}, truncated, round, src);
+ output.value = temp.num;
+ output.error = temp.error;
+ }
+ return output;
+}
+
+// Takes the start of a string representing a hexadecimal float, as well as the
+// local decimal point. It returns if it suceeded in parsing any digits, and if
+// the return value is true then the outputs are pointer to the end of the
+// number, and the mantissa and exponent for the closest float T representation.
+// If the return value is false, then it is assumed that there is no number
+// here.
+template <class T>
+LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
+hexadecimal_string_to_float(const char *__restrict src,
+ const char DECIMAL_POINT, RoundDirection round) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ constexpr uint32_t BASE = 16;
+ constexpr char EXPONENT_MARKER = 'p';
+
+ bool truncated = false;
+ bool seen_digit = false;
+ bool after_decimal = false;
+ StorageType mantissa = 0;
+ int32_t exponent = 0;
+
+ size_t index = 0;
+
+ StrToNumResult<ExpandedFloat<T>> output({0, 0});
+
+ // The goal for the first step of parsing is to convert the number in src to
+ // the format mantissa * (base ^ exponent)
+
+ // The loop fills the mantissa with as many digits as it can hold
+ const StorageType bitstype_max_div_by_base =
+ cpp::numeric_limits<StorageType>::max() / BASE;
+ while (true) {
+ if (isalnum(src[index])) {
+ uint32_t digit = b36_char_to_int(src[index]);
+ if (digit < BASE)
+ seen_digit = true;
+ else
+ break;
+
+ if (mantissa < bitstype_max_div_by_base) {
+ mantissa = (mantissa * BASE) + digit;
+ if (after_decimal)
+ --exponent;
+ } else {
+ if (digit > 0)
+ truncated = true;
+ if (!after_decimal)
+ ++exponent;
+ }
+ ++index;
+ continue;
+ }
+ if (src[index] == DECIMAL_POINT) {
+ if (after_decimal) {
+ break; // this means that src[index] points to a second decimal point,
+ // ending the number.
+ }
+ after_decimal = true;
+ ++index;
+ continue;
+ }
+ // The character is neither a hexadecimal digit nor a decimal point.
+ break;
+ }
+
+ if (!seen_digit)
+ return output;
+
+ // Convert the exponent from having a base of 16 to having a base of 2.
+ exponent *= 4;
+
+ if (tolower(src[index]) == EXPONENT_MARKER) {
+ bool has_sign = false;
+ if (src[index + 1] == '+' || src[index + 1] == '-') {
+ has_sign = true;
+ }
+ if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) {
+ ++index;
+ auto result = strtointeger<int32_t>(src + index, 10);
+ if (result.has_error())
+ output.error = result.error;
+
+ int32_t add_to_exponent = result.value;
+ index += result.parsed_len;
+
+ // Here we do this operation as int64 to avoid overflow.
+ int64_t temp_exponent = static_cast<int64_t>(exponent) +
+ static_cast<int64_t>(add_to_exponent);
+
+ // If the result is in the valid range, then we use it. The valid range is
+ // also within the int32 range, so this prevents overflow issues.
+ if (temp_exponent > FPBits::MAX_BIASED_EXPONENT) {
+ exponent = FPBits::MAX_BIASED_EXPONENT;
+ } else if (temp_exponent < -FPBits::MAX_BIASED_EXPONENT) {
+ exponent = -FPBits::MAX_BIASED_EXPONENT;
+ } else {
+ exponent = static_cast<int32_t>(temp_exponent);
+ }
+ }
+ }
+ output.parsed_len = index;
+ if (mantissa == 0) { // if we have a 0, then also 0 the exponent.
+ output.value.exponent = 0;
+ output.value.mantissa = 0;
+ } else {
+ auto temp = binary_exp_to_float<T>({mantissa, exponent}, truncated, round);
+ output.error = temp.error;
+ output.value = temp.num;
+ }
+ return output;
+}
+
+template <class T>
+LIBC_INLINE typename fputil::FPBits<T>::StorageType
+nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType nan_mantissa = 0;
+
+ if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) {
+ StrToNumResult<StorageType> strtoint_result =
+ strtointeger<StorageType>(ncharseq.data(), 0);
+ if (!strtoint_result.has_error())
+ nan_mantissa = strtoint_result.value;
+
+ if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size()))
+ nan_mantissa = 0;
+ }
+
+ return nan_mantissa;
+}
+
+// Takes a pointer to a string and a pointer to a string pointer. This function
+// is used as the backend for all of the string to float functions.
+// TODO: Add src_len member to match strtointeger.
+// TODO: Next, move from char* and length to string_view
+template <class T>
+LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ FPBits result = FPBits();
+ bool seen_digit = false;
+ char sign = '+';
+
+ int error = 0;
+
+ ptrdiff_t index = first_non_whitespace(src) - src;
+
+ if (src[index] == '+' || src[index] == '-') {
+ sign = src[index];
+ ++index;
+ }
+
+ if (sign == '-') {
+ result.set_sign(Sign::NEG);
+ }
+
+ static constexpr char DECIMAL_POINT = '.';
+ static const char *inf_string = "infinity";
+ static const char *nan_string = "nan";
+
+ if (isdigit(src[index]) || src[index] == DECIMAL_POINT) { // regular number
+ int base = 10;
+ if (is_float_hex_start(src + index, DECIMAL_POINT)) {
+ base = 16;
+ index += 2;
+ seen_digit = true;
+ }
+
+ RoundDirection round_direction = RoundDirection::Nearest;
+
+ switch (fputil::quick_get_round()) {
+ case FE_TONEAREST:
+ round_direction = RoundDirection::Nearest;
+ break;
+ case FE_UPWARD:
+ if (sign == '+') {
+ round_direction = RoundDirection::Up;
+ } else {
+ round_direction = RoundDirection::Down;
+ }
+ break;
+ case FE_DOWNWARD:
+ if (sign == '+') {
+ round_direction = RoundDirection::Down;
+ } else {
+ round_direction = RoundDirection::Up;
+ }
+ break;
+ case FE_TOWARDZERO:
+ round_direction = RoundDirection::Down;
+ break;
+ }
+
+ StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
+ if (base == 16) {
+ parse_result = hexadecimal_string_to_float<T>(src + index, DECIMAL_POINT,
+ round_direction);
+ } else { // base is 10
+ parse_result = decimal_string_to_float<T>(src + index, DECIMAL_POINT,
+ round_direction);
+ }
+ seen_digit = parse_result.parsed_len != 0;
+ result.set_mantissa(parse_result.value.mantissa);
+ result.set_biased_exponent(parse_result.value.exponent);
+ index += parse_result.parsed_len;
+ error = parse_result.error;
+ } else if (tolower(src[index]) == 'n') { // NaN
+ if (tolower(src[index + 1]) == nan_string[1] &&
+ tolower(src[index + 2]) == nan_string[2]) {
+ seen_digit = true;
+ index += 3;
+ StorageType nan_mantissa = 0;
+ // this handles the case of `NaN(n-character-sequence)`, where the
+ // n-character-sequence is made of 0 or more letters, numbers, or
+ // underscore characters in any order.
+ if (src[index] == '(') {
+ size_t left_paren = index;
+ ++index;
+ while (isalnum(src[index]) || src[index] == '_')
+ ++index;
+ if (src[index] == ')') {
+ ++index;
+ nan_mantissa = nan_mantissa_from_ncharseq<T>(
+ cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
+ } else {
+ index = left_paren;
+ }
+ }
+ result = FPBits(result.quiet_nan(result.sign(), nan_mantissa));
+ }
+ } else if (tolower(src[index]) == 'i') { // INF
+ if (tolower(src[index + 1]) == inf_string[1] &&
+ tolower(src[index + 2]) == inf_string[2]) {
+ seen_digit = true;
+ result = FPBits(result.inf(result.sign()));
+ if (tolower(src[index + 3]) == inf_string[3] &&
+ tolower(src[index + 4]) == inf_string[4] &&
+ tolower(src[index + 5]) == inf_string[5] &&
+ tolower(src[index + 6]) == inf_string[6] &&
+ tolower(src[index + 7]) == inf_string[7]) {
+ // if the string is "INFINITY" then consume 8 characters.
+ index += 8;
+ } else {
+ index += 3;
+ }
+ }
+ }
+ if (!seen_digit) { // If there is nothing to actually parse, then return 0.
+ return {T(0), 0, error};
+ }
+
+ // This function only does something if T is long double and the platform uses
+ // special 80 bit long doubles. Otherwise it should be inlined out.
+ set_implicit_bit<T>(result);
+
+ return {result.get_val(), index, error};
+}
+
+template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ LIBC_CRASH_ON_NULLPTR(arg);
+
+ FPBits result;
+ int error = 0;
+ StorageType nan_mantissa = 0;
+
+ ptrdiff_t index = 0;
+ while (isalnum(arg[index]) || arg[index] == '_')
+ ++index;
+
+ if (arg[index] == '\0')
+ nan_mantissa = nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index));
+
+ result = FPBits::quiet_nan(Sign::POS, nan_mantissa);
+ return {result.get_val(), 0, error};
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
diff --git a/lib/libcxx/libc/src/__support/str_to_integer.h b/lib/libcxx/libc/src/__support/str_to_integer.h
new file mode 100644
index 0000000000..8e569e8a7f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/str_to_integer.h
@@ -0,0 +1,169 @@
+//===-- String to integer conversion utils ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This file is shared with libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
+#define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
+
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/CPP/type_traits/make_unsigned.h"
+#include "src/__support/big_int.h"
+#include "src/__support/common.h"
+#include "src/__support/ctype_utils.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/str_to_num_result.h"
+#include "src/__support/uint128.h"
+#include "src/errno/libc_errno.h" // For ERANGE
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+// Returns a pointer to the first character in src that is not a whitespace
+// character (as determined by isspace())
+// TODO: Change from returning a pointer to returning a length.
+LIBC_INLINE const char *
+first_non_whitespace(const char *__restrict src,
+ size_t src_len = cpp::numeric_limits<size_t>::max()) {
+ size_t src_cur = 0;
+ while (src_cur < src_len && internal::isspace(src[src_cur])) {
+ ++src_cur;
+ }
+ return src + src_cur;
+}
+
+// checks if the next 3 characters of the string pointer are the start of a
+// hexadecimal number. Does not advance the string pointer.
+LIBC_INLINE bool
+is_hex_start(const char *__restrict src,
+ size_t src_len = cpp::numeric_limits<size_t>::max()) {
+ if (src_len < 3)
+ return false;
+ return *src == '0' && tolower(*(src + 1)) == 'x' && isalnum(*(src + 2)) &&
+ b36_char_to_int(*(src + 2)) < 16;
+}
+
+// Takes the address of the string pointer and parses the base from the start of
+// it.
+LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) {
+ // A hexadecimal number is defined as "the prefix 0x or 0X followed by a
+ // sequence of the decimal digits and the letters a (or A) through f (or F)
+ // with values 10 through 15 respectively." (C standard 6.4.4.1)
+ if (is_hex_start(src, src_len))
+ return 16;
+ // An octal number is defined as "the prefix 0 optionally followed by a
+ // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any
+ // number that starts with 0, including just 0, is an octal number.
+ if (src_len > 0 && src[0] == '0')
+ return 8;
+ // A decimal number is defined as beginning "with a nonzero digit and
+ // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1)
+ return 10;
+}
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+// Takes a pointer to a string and the base to convert to. This function is used
+// as the backend for all of the string to int functions.
+template <class T>
+LIBC_INLINE StrToNumResult<T>
+strtointeger(const char *__restrict src, int base,
+ const size_t src_len = cpp::numeric_limits<size_t>::max()) {
+ using ResultType = make_integral_or_big_int_unsigned_t<T>;
+
+ ResultType result = 0;
+
+ bool is_number = false;
+ size_t src_cur = 0;
+ int error_val = 0;
+
+ if (src_len == 0)
+ return {0, 0, 0};
+
+ if (base < 0 || base == 1 || base > 36)
+ return {0, 0, EINVAL};
+
+ src_cur = first_non_whitespace(src, src_len) - src;
+
+ char result_sign = '+';
+ if (src[src_cur] == '+' || src[src_cur] == '-') {
+ result_sign = src[src_cur];
+ ++src_cur;
+ }
+
+ if (base == 0)
+ base = infer_base(src + src_cur, src_len - src_cur);
+
+ if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur))
+ src_cur = src_cur + 2;
+
+ constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>;
+ const bool is_positive = (result_sign == '+');
+
+ ResultType constexpr NEGATIVE_MAX =
+ !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1
+ : cpp::numeric_limits<T>::max();
+ ResultType const abs_max =
+ (is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);
+ ResultType const abs_max_div_by_base =
+ static_cast<ResultType>(abs_max / base);
+
+ while (src_cur < src_len && isalnum(src[src_cur])) {
+ int cur_digit = b36_char_to_int(src[src_cur]);
+ if (cur_digit >= base)
+ break;
+
+ is_number = true;
+ ++src_cur;
+
+ // If the number has already hit the maximum value for the current type then
+ // the result cannot change, but we still need to advance src to the end of
+ // the number.
+ if (result == abs_max) {
+ error_val = ERANGE;
+ continue;
+ }
+
+ if (result > abs_max_div_by_base) {
+ result = abs_max;
+ error_val = ERANGE;
+ } else {
+ result = static_cast<ResultType>(result * base);
+ }
+ if (result > abs_max - cur_digit) {
+ result = abs_max;
+ error_val = ERANGE;
+ } else {
+ result = static_cast<ResultType>(result + cur_digit);
+ }
+ }
+
+ ptrdiff_t str_len = is_number ? (src_cur) : 0;
+
+ if (error_val == ERANGE) {
+ if (is_positive || IS_UNSIGNED)
+ return {cpp::numeric_limits<T>::max(), str_len, error_val};
+ else // T is signed and there is a negative overflow
+ return {cpp::numeric_limits<T>::min(), str_len, error_val};
+ }
+
+ return {static_cast<T>(is_positive ? result : -result), str_len, error_val};
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
diff --git a/lib/libcxx/libc/src/__support/str_to_num_result.h b/lib/libcxx/libc/src/__support/str_to_num_result.h
new file mode 100644
index 0000000000..48c363c88f
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/str_to_num_result.h
@@ -0,0 +1,48 @@
+//===-- A data structure for str_to_number to return ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This file is shared with libc++. You should also be careful when adding
+// dependencies to this file, since it needs to build for all libc++ targets.
+// -----------------------------------------------------------------------------
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H
+#define LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/config.h"
+
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// -----------------------------------------------------------------------------
+// **** WARNING ****
+// This interface is shared with libc++, if you change this interface you need
+// to update it in both libc and libc++.
+// -----------------------------------------------------------------------------
+template <typename T> struct StrToNumResult {
+ T value;
+ int error;
+ ptrdiff_t parsed_len;
+
+ LIBC_INLINE constexpr StrToNumResult(T value)
+ : value(value), error(0), parsed_len(0) {}
+ LIBC_INLINE constexpr StrToNumResult(T value, ptrdiff_t parsed_len)
+ : value(value), error(0), parsed_len(parsed_len) {}
+ LIBC_INLINE constexpr StrToNumResult(T value, ptrdiff_t parsed_len, int error)
+ : value(value), error(error), parsed_len(parsed_len) {}
+
+ LIBC_INLINE constexpr bool has_error() { return error != 0; }
+
+ LIBC_INLINE constexpr operator T() { return value; }
+};
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H
diff --git a/lib/libcxx/libc/src/__support/uint128.h b/lib/libcxx/libc/src/__support/uint128.h
new file mode 100644
index 0000000000..722e79d080
--- /dev/null
+++ b/lib/libcxx/libc/src/__support/uint128.h
@@ -0,0 +1,23 @@
+//===-- 128-bit signed and unsigned int types -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_UINT128_H
+#define LLVM_LIBC_SRC___SUPPORT_UINT128_H
+
+#include "big_int.h"
+#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
+
+#ifdef LIBC_TYPES_HAS_INT128
+using UInt128 = __uint128_t;
+using Int128 = __int128_t;
+#else
+using UInt128 = LIBC_NAMESPACE::UInt<128>;
+using Int128 = LIBC_NAMESPACE::Int<128>;
+#endif // LIBC_TYPES_HAS_INT128
+
+#endif // LLVM_LIBC_SRC___SUPPORT_UINT128_H
diff --git a/lib/libcxx/libc/src/errno/libc_errno.h b/lib/libcxx/libc/src/errno/libc_errno.h
new file mode 100644
index 0000000000..44ee271484
--- /dev/null
+++ b/lib/libcxx/libc/src/errno/libc_errno.h
@@ -0,0 +1,47 @@
+//===-- Implementation header for libc_errno --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
+#define LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
+
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#include "hdr/errno_macros.h"
+
+// This header is to be consumed by internal implementations, in which all of
+// them should refer to `libc_errno` instead of using `errno` directly from
+// <errno.h> header.
+
+// Unit and hermetic tests should:
+// - #include "src/errno/libc_errno.h"
+// - NOT #include <errno.h>
+// - Only use `libc_errno` in the code
+// - Depend on libc.src.errno.errno
+
+// Integration tests should:
+// - NOT #include "src/errno/libc_errno.h"
+// - #include <errno.h>
+// - Use regular `errno` in the code
+// - Still depend on libc.src.errno.errno
+
+namespace LIBC_NAMESPACE_DECL {
+
+extern "C" int *__llvm_libc_errno() noexcept;
+
+struct Errno {
+ void operator=(int);
+ operator int();
+};
+
+extern Errno libc_errno;
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H