aboutsummaryrefslogtreecommitdiff
path: root/libc/src
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2026-01-29 14:39:34 -0800
committerPeter Collingbourne <peter@pcc.me.uk>2026-01-29 14:39:34 -0800
commit7b3f189a1369f9348c007730ddea953b1e68acb1 (patch)
tree7db8969ee8a34a10b6c8ae033c939c9d653376f6 /libc/src
parentf3d6dae13ae710323a2ddbaf87af71b1abcbfada (diff)
parent0893b70ecfc4f4aca0a20a078476d191edc1e623 (diff)
downloadllvm-users/pcc/spr/codegen-introduce-machinefunctiongetpreferredalignment.zip
llvm-users/pcc/spr/codegen-introduce-machinefunctiongetpreferredalignment.tar.gz
llvm-users/pcc/spr/codegen-introduce-machinefunctiongetpreferredalignment.tar.bz2
Created using spr 1.3.6-beta.1
Diffstat (limited to 'libc/src')
-rw-r--r--libc/src/__support/CMakeLists.txt15
-rw-r--r--libc/src/__support/CPP/limits.h88
-rw-r--r--libc/src/__support/CPP/type_traits/is_integral.h15
-rw-r--r--libc/src/__support/CPP/type_traits/is_unsigned.h6
-rw-r--r--libc/src/__support/GPU/allocator.cpp17
-rw-r--r--libc/src/__support/math/CMakeLists.txt411
-rw-r--r--libc/src/__support/math/asin.h2
-rw-r--r--libc/src/__support/math/atan2f_float.h6
-rw-r--r--libc/src/__support/math/atanf_float.h6
-rw-r--r--libc/src/__support/math/cbrt.h6
-rw-r--r--libc/src/__support/math/cbrtf.h6
-rw-r--r--libc/src/__support/math/cos.h6
-rw-r--r--libc/src/__support/math/cosf.h6
-rw-r--r--libc/src/__support/math/dfmaf128.h31
-rw-r--r--libc/src/__support/math/dfmal.h26
-rw-r--r--libc/src/__support/math/f16fma.h33
-rw-r--r--libc/src/__support/math/f16fmal.h34
-rw-r--r--libc/src/__support/math/f16sqrtl.h33
-rw-r--r--libc/src/__support/math/fsqrt.h26
-rw-r--r--libc/src/__support/math/fsqrtf128.h33
-rw-r--r--libc/src/__support/math/fsqrtl.h26
-rw-r--r--libc/src/__support/math/hypotf.h107
-rw-r--r--libc/src/__support/math/ilogb.h27
-rw-r--r--libc/src/__support/math/ilogbf.h26
-rw-r--r--libc/src/__support/math/ilogbf128.h34
-rw-r--r--libc/src/__support/math/ilogbl.h28
-rw-r--r--libc/src/__support/math/llogb.h27
-rw-r--r--libc/src/__support/math/llogbf.h28
-rw-r--r--libc/src/__support/math/llogbf128.h34
-rw-r--r--libc/src/__support/math/llogbf16.h34
-rw-r--r--libc/src/__support/math/log10.h919
-rw-r--r--libc/src/__support/math/log1p.h1070
-rw-r--r--libc/src/__support/math/log2.h978
-rw-r--r--libc/src/__support/math/logbf.h26
-rw-r--r--libc/src/__support/math/logbf128.h34
-rw-r--r--libc/src/__support/math/logbf16.h34
-rw-r--r--libc/src/__support/math/logf.h192
-rw-r--r--libc/src/__support/math/logf16.h180
-rw-r--r--libc/src/__support/math/range_reduction.h6
-rw-r--r--libc/src/__support/math/range_reduction_fma.h6
-rw-r--r--libc/src/__support/math/sin.h6
-rw-r--r--libc/src/__support/math/sincosf_utils.h6
-rw-r--r--libc/src/__support/math/sinf.h194
-rw-r--r--libc/src/__support/math/sinf16.h136
-rw-r--r--libc/src/__support/math/sinhf.h88
-rw-r--r--libc/src/__support/math/sinhf16.h168
-rw-r--r--libc/src/__support/math/sinpif.h123
-rw-r--r--libc/src/__support/math/sqrt.h24
-rw-r--r--libc/src/__support/math/sqrtf16.h31
-rw-r--r--libc/src/__support/math/tan.h305
-rw-r--r--libc/src/__support/math/tanf.h164
-rw-r--r--libc/src/__support/threads/fork_callbacks.cpp1
-rw-r--r--libc/src/__support/wchar/CMakeLists.txt9
-rw-r--r--libc/src/__support/wchar/character_converter.cpp176
-rw-r--r--libc/src/__support/wchar/character_converter.h166
-rw-r--r--libc/src/__support/wchar/wcrtomb.cpp50
-rw-r--r--libc/src/__support/wchar/wcrtomb.h39
-rw-r--r--libc/src/__support/weak_avl.h595
-rw-r--r--libc/src/math/generic/CMakeLists.txt185
-rw-r--r--libc/src/math/generic/asin.cpp262
-rw-r--r--libc/src/math/generic/dfmaf128.cpp11
-rw-r--r--libc/src/math/generic/dfmal.cpp6
-rw-r--r--libc/src/math/generic/f16fma.cpp6
-rw-r--r--libc/src/math/generic/f16fmal.cpp6
-rw-r--r--libc/src/math/generic/f16sqrtl.cpp6
-rw-r--r--libc/src/math/generic/fsqrt.cpp6
-rw-r--r--libc/src/math/generic/fsqrtf128.cpp7
-rw-r--r--libc/src/math/generic/fsqrtl.cpp8
-rw-r--r--libc/src/math/generic/hypotf.cpp85
-rw-r--r--libc/src/math/generic/ilogb.cpp6
-rw-r--r--libc/src/math/generic/ilogbf.cpp6
-rw-r--r--libc/src/math/generic/ilogbf128.cpp8
-rw-r--r--libc/src/math/generic/ilogbl.cpp8
-rw-r--r--libc/src/math/generic/llogb.cpp6
-rw-r--r--libc/src/math/generic/llogbf.cpp6
-rw-r--r--libc/src/math/generic/llogbf128.cpp8
-rw-r--r--libc/src/math/generic/llogbf16.cpp8
-rw-r--r--libc/src/math/generic/log10.cpp901
-rw-r--r--libc/src/math/generic/log1p.cpp1052
-rw-r--r--libc/src/math/generic/log2.cpp962
-rw-r--r--libc/src/math/generic/logbf.cpp6
-rw-r--r--libc/src/math/generic/logbf128.cpp8
-rw-r--r--libc/src/math/generic/logbf16.cpp6
-rw-r--r--libc/src/math/generic/logf.cpp140
-rw-r--r--libc/src/math/generic/logf16.cpp150
-rw-r--r--libc/src/math/generic/sinf.cpp170
-rw-r--r--libc/src/math/generic/sinf16.cpp104
-rw-r--r--libc/src/math/generic/sinhf.cpp68
-rw-r--r--libc/src/math/generic/sinhf16.cpp141
-rw-r--r--libc/src/math/generic/sinpif.cpp106
-rw-r--r--libc/src/math/generic/sqrt.cpp6
-rw-r--r--libc/src/math/generic/sqrtf16.cpp9
-rw-r--r--libc/src/math/generic/tan.cpp284
-rw-r--r--libc/src/math/generic/tanf.cpp140
-rw-r--r--libc/src/pthread/pthread_getattr_np.h21
-rw-r--r--libc/src/spawn/linux/posix_spawn.cpp2
-rw-r--r--libc/src/stdio/printf_core/CMakeLists.txt19
-rw-r--r--libc/src/stdio/printf_core/char_converter.h50
-rw-r--r--libc/src/stdio/printf_core/core_structs.h2
-rw-r--r--libc/src/stdio/printf_core/linux/error_mapper.h3
-rw-r--r--libc/src/stdio/printf_core/parser.h32
-rw-r--r--libc/src/string/memory_utils/inline_memcpy.h2
-rw-r--r--libc/src/string/memory_utils/inline_memmove.h2
-rw-r--r--libc/src/string/memory_utils/inline_memset.h2
104 files changed, 6785 insertions, 5150 deletions
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index df524c2..64cf3687 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -391,6 +391,21 @@ add_header_library(
libc.src.__support.macros.attributes
)
+add_header_library(
+ weak_avl
+ HDRS
+ weak_avl.h
+ DEPENDS
+ libc.hdr.stdint_proxy
+ libc.src.__support.CPP.bit
+ libc.src.__support.CPP.new
+ libc.src.__support.CPP.utility
+ libc.src.__support.CPP.optional
+ libc.src.__support.libc_assert
+ libc.src.__support.macros.attributes
+ libc.src.__support.macros.config
+)
+
add_subdirectory(FPUtil)
add_subdirectory(OSUtil)
add_subdirectory(StringUtil)
diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h
index cf4beb9..76158b2 100644
--- a/libc/src/__support/CPP/limits.h
+++ b/libc/src/__support/CPP/limits.h
@@ -1,4 +1,4 @@
-//===-- A self contained equivalent of std::limits --------------*- C++ -*-===//
+//===-- A self contained equivalent of <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.
@@ -13,78 +13,42 @@
#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; }
+template <typename T, bool is_integral> struct numeric_limits_impl {};
+
+template <typename T> struct numeric_limits_impl<T, true> {
+ LIBC_INLINE_VAR static constexpr bool is_signed = T(-1) < T(0);
+
LIBC_INLINE_VAR static constexpr int digits =
- CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>;
+ (CHAR_BIT * sizeof(T)) - is_signed;
+
+ LIBC_INLINE static constexpr T min() {
+ if constexpr (is_signed) {
+ return T(T(1) << digits);
+ } else {
+ return 0;
+ }
+ }
+
+ LIBC_INLINE static constexpr T max() {
+ if constexpr (is_signed) {
+ return T(T(~0) ^ min());
+ } else {
+ return T(~0);
+ }
+ }
};
} // 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
+template <typename T>
+struct numeric_limits
+ : public internal::numeric_limits_impl<T, is_integral_v<T>> {};
} // namespace cpp
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/CPP/type_traits/is_integral.h b/libc/src/__support/CPP/type_traits/is_integral.h
index 96ba09a..09047cb 100644
--- a/libc/src/__support/CPP/type_traits/is_integral.h
+++ b/libc/src/__support/CPP/type_traits/is_integral.h
@@ -26,13 +26,18 @@ private:
}
public:
- LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of<
- T,
+ LIBC_INLINE_VAR static constexpr bool value =
+ __is_unqualified_any_of<T,
#ifdef LIBC_TYPES_HAS_INT128
- __int128_t, __uint128_t,
+ __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>();
+#ifdef __cpp_char8_t
+ char8_t,
+#endif
+ char16_t, char32_t, 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;
diff --git a/libc/src/__support/CPP/type_traits/is_unsigned.h b/libc/src/__support/CPP/type_traits/is_unsigned.h
index b4267ee..87c352b 100644
--- a/libc/src/__support/CPP/type_traits/is_unsigned.h
+++ b/libc/src/__support/CPP/type_traits/is_unsigned.h
@@ -10,7 +10,7 @@
#include "include/llvm-libc-macros/stdfix-macros.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_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"
@@ -23,7 +23,7 @@ namespace cpp {
#ifndef LIBC_COMPILER_HAS_FIXED_POINT
template <typename T>
-struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
+struct is_unsigned : bool_constant<(is_integral_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; }
};
@@ -37,7 +37,7 @@ private:
public:
LIBC_INLINE_VAR static constexpr bool value =
- (is_arithmetic_v<T> && (T(-1) > T(0))) ||
+ (is_integral_v<T> && (T(-1) > T(0))) ||
__is_unqualified_any_of<T, unsigned short fract, unsigned fract,
unsigned long fract, unsigned short accum,
unsigned accum, unsigned long accum,
diff --git a/libc/src/__support/GPU/allocator.cpp b/libc/src/__support/GPU/allocator.cpp
index 7182180..f8a3b46 100644
--- a/libc/src/__support/GPU/allocator.cpp
+++ b/libc/src/__support/GPU/allocator.cpp
@@ -498,20 +498,21 @@ public:
result = gpu::shuffle(lane_mask, cpp::countr_zero(uniform), result);
count = gpu::shuffle(lane_mask, cpp::countr_zero(uniform), count);
+ if (!result)
+ return nullptr;
+
// We defer storing the newly allocated slab until now so that we can use
// multiple lanes to initialize it and release it for use.
- uint64_t slab_mask =
- gpu::ballot(lane_mask, result && impl::is_sentinel(count));
- if (slab_mask & impl::id_in_mask()) {
- result->initialize(slab_mask, uniform);
+ if (impl::is_sentinel(count)) {
+ uint64_t count_mask = gpu::get_lane_mask();
+ result->initialize(count_mask, uniform);
if (gpu::get_lane_id() == uint32_t(cpp::countr_zero(uniform)))
finalize(result, cpp::popcount(uniform), count);
- count = gpu::shuffle(slab_mask, cpp::countr_zero(uniform), count);
+ count = gpu::shuffle(count_mask, cpp::countr_zero(uniform), count);
}
- if (result)
- count = count - cpp::popcount(uniform) +
- impl::lane_count(uniform, gpu::get_lane_id());
+ count = count - cpp::popcount(uniform) +
+ impl::lane_count(uniform, gpu::get_lane_id());
return result;
}
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 4139a1b..aad2270 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -390,7 +390,6 @@ add_header_library(
cosf.h
DEPENDS
.sincosf_utils
- libc.src.errno.errno
libc.src.__support.FPUtil.basic_operations
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
@@ -595,6 +594,15 @@ add_header_library(
)
add_header_library(
+ f16sqrtl
+ HDRS
+ f16sqrtl.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.sqrt
+ libc.src.__support.macros.properties.types
+)
+
+add_header_library(
frexpf128
HDRS
frexpf128.h
@@ -604,6 +612,22 @@ add_header_library(
)
add_header_library(
+ fsqrt
+ HDRS
+ fsqrt.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.sqrt
+)
+
+add_header_library(
+ fsqrtl
+ HDRS
+ fsqrtl.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.sqrt
+)
+
+add_header_library(
inv_trigf_utils
HDRS
inv_trigf_utils.h
@@ -632,6 +656,36 @@ add_header_library(
)
add_header_library(
+ f16fma
+ HDRS
+ f16fma.h
+ DEPENDS
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.macros.config
+ libc.include.llvm-libc-macros.float16_macros
+)
+
+add_header_library(
+ f16fmal
+ HDRS
+ f16fmal.h
+ DEPENDS
+ libc.src.__support.macros.config
+ libc.src.__support.FPUtil.fma
+ libc.include.llvm-libc-macros.float16_macros
+)
+
+add_header_library(
+ ilogb
+ HDRS
+ ilogb.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.FPUtil.manipulation_functions
+)
+
+add_header_library(
ilogbf16
HDRS
ilogbf16.h
@@ -643,6 +697,36 @@ add_header_library(
)
add_header_library(
+ ilogbf128
+ HDRS
+ ilogbf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.include.llvm-libc-types.float128
+)
+
+add_header_library(
+ llogbf16
+ HDRS
+ llogbf16.h
+ DEPENDS
+ libc.src.__support.macros.config
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.include.llvm-libc-macros.float16_macros
+)
+
+add_header_library(
+ ilogbf
+ HDRS
+ ilogbf.h
+ DEPENDS
+ libc.src.__support.macros.config
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.manipulation_functions
+)
+
+add_header_library(
ldexpf128
HDRS
ldexpf128.h
@@ -653,6 +737,16 @@ add_header_library(
)
add_header_library(
+ llogbf128
+ HDRS
+ llogbf128.h
+ DEPENDS
+ libc.src.__support.macros.config
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.include.llvm-libc-types.float128
+)
+
+add_header_library(
ldexpf16
HDRS
ldexpf16.h
@@ -671,6 +765,37 @@ add_header_library(
)
add_header_library(
+ llogbf
+ HDRS
+ llogbf.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.common
+ libc.src.__support.macros.config
+)
+
+add_header_library(
+ logf16
+ HDRS
+ logf16.h
+ DEPENDS
+ .expxf16_utils
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.common
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.cpu_features
+ libc.include.llvm-libc-macros.float16_macros
+)
+
+add_header_library(
exp_constants
HDRS
exp_constants.h
@@ -936,6 +1061,38 @@ add_header_library(
)
add_header_library(
+ fsqrtf128
+ HDRS
+ fsqrtf128.h
+ DEPENDS
+ libc.src.__support.FPUtil.generic.sqrt
+ libc.src.__support.macros.properties.types
+)
+
+add_header_library(
+ hypotf
+ HDRS
+ hypotf.h
+ DEPENDS
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ ilogbl
+ HDRS
+ ilogbl.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.common
+ libc.src.__support.macros.config
+)
+
+add_header_library(
range_reduction_double
HDRS
range_reduction_double_common.h
@@ -994,6 +1151,15 @@ add_header_library(
)
add_header_library(
+ sqrtf16
+ HDRS
+ sqrtf16.h
+ DEPENDS
+ libc.src.__support.FPUtil.sqrt
+ libc.include.llvm-libc-macros.float16_macros
+)
+
+add_header_library(
sincos_eval
HDRS
sincos_eval.h
@@ -1037,6 +1203,31 @@ add_header_library(
)
add_header_library(
+ sinpif
+ HDRS
+ sinpif.h
+ DEPENDS
+ .sincosf_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ llogb
+ HDRS
+ llogb.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.common
+ libc.src.__support.macros.config
+)
+
+add_header_library(
log
HDRS
log.h
@@ -1054,6 +1245,99 @@ add_header_library(
)
add_header_library(
+ log10
+ HDRS
+ log10.h
+ DEPENDS
+ .common_constants
+ .log_range_reduction
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.integer_literals
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ log1p
+ HDRS
+ log1p.h
+ DEPENDS
+ .common_constants
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.integer_literals
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ log2
+ HDRS
+ log2.h
+ DEPENDS
+ .common_constants
+ .log_range_reduction
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.integer_literals
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ logbf128
+ HDRS
+ logbf128.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.macros.properties.types
+)
+
+add_header_library(
+ logbf16
+ HDRS
+ logbf16.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.macros.properties.types
+)
+
+add_header_library(
+ logbf
+ HDRS
+ logbf.h
+ DEPENDS
+ libc.src.__support.FPUtil.manipulation_functions
+)
+
+add_header_library(
+ logf
+ HDRS
+ logf.h
+ DEPENDS
+ .common_constants
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.cpu_features
+)
+
+add_header_library(
log_range_reduction
HDRS
log_range_reduction.h
@@ -1078,3 +1362,128 @@ add_header_library(
libc.src.__support.math.sincos_eval
libc.src.__support.macros.optimization
)
+
+add_header_library(
+ sinf
+ HDRS
+ sinf.h
+ DEPENDS
+ .range_reduction
+ .sincosf_utils
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ sinf16
+ HDRS
+ sinf16.h
+ DEPENDS
+ .sincosf16_utils
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.include.llvm-libc-macros.float16_macros
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.types
+)
+
+add_header_library(
+ sinhf
+ HDRS
+ sinhf.h
+ DEPENDS
+ .sinhfcoshf_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ sinhf16
+ HDRS
+ sinhf16.h
+ DEPENDS
+ .expxf16_utils
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ sqrt
+ HDRS
+ sqrt.h
+ DEPENDS
+ libc.src.__support.FPUtil.sqrt
+)
+
+add_header_library(
+ dfmal
+ HDRS
+ dfmal.h
+ DEPENDS
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.common
+ libc.src.__support.macros.config
+)
+
+add_header_library(
+ dfmaf128
+ HDRS
+ dfmaf128.h
+ DEPENDS
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.include.llvm-libc-types.float128
+)
+
+add_header_library(
+ tan
+ HDRS
+ tan.h
+ DEPENDS
+ .range_reduction_double
+ libc.hdr.errno_macros
+ libc.src.__support.FPUtil.double_double
+ libc.src.__support.FPUtil.dyadic_float
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.macros.optimization
+)
+
+add_header_library(
+ tanf
+ HDRS
+ tanf.h
+ DEPENDS
+ .range_reduction
+ .sincosf_utils
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fma
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.macros.optimization
+)
diff --git a/libc/src/__support/math/asin.h b/libc/src/__support/math/asin.h
index 5e06d04..396a535 100644
--- a/libc/src/__support/math/asin.h
+++ b/libc/src/__support/math/asin.h
@@ -25,7 +25,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE static constexpr double asin(double x) {
+LIBC_INLINE static double asin(double x) {
using namespace asin_internal;
using FPBits = fputil::FPBits<double>;
diff --git a/libc/src/__support/math/atan2f_float.h b/libc/src/__support/math/atan2f_float.h
index 8bd7095..cc5ea77 100644
--- a/libc/src/__support/math/atan2f_float.h
+++ b/libc/src/__support/math/atan2f_float.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
-#define LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/double_double.h"
@@ -242,4 +242,4 @@ LIBC_INLINE static constexpr float atan2f(float y, float x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F_FLOAT_H
diff --git a/libc/src/__support/math/atanf_float.h b/libc/src/__support/math/atanf_float.h
index 3e5adf3..8794cec 100644
--- a/libc/src/__support/math/atanf_float.h
+++ b/libc/src/__support/math/atanf_float.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
-#define LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -165,4 +165,4 @@ LIBC_INLINE static float atanf(float x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATANF_FLOAT_H
diff --git a/libc/src/__support/math/cbrt.h b/libc/src/__support/math/cbrt.h
index fe6bc19..38df9fb 100644
--- a/libc/src/__support/math/cbrt.h
+++ b/libc/src/__support/math/cbrt.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_CBRT_H
-#define LIBC_SRC___SUPPORT_MATH_CBRT_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_CBRT_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_CBRT_H
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -347,4 +347,4 @@ LIBC_INLINE static constexpr double cbrt(double x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_CBRT_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_CBRT_H
diff --git a/libc/src/__support/math/cbrtf.h b/libc/src/__support/math/cbrtf.h
index f82892b..d7ff1cd 100644
--- a/libc/src/__support/math/cbrtf.h
+++ b/libc/src/__support/math/cbrtf.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_CBRTF_H
-#define LIBC_SRC___SUPPORT_MATH_CBRTF_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_CBRTF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_CBRTF_H
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -158,4 +158,4 @@ LIBC_INLINE static constexpr float cbrtf(float x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_CBRTF_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_CBRTF_H
diff --git a/libc/src/__support/math/cos.h b/libc/src/__support/math/cos.h
index 0802f9e..cd4abc2 100644
--- a/libc/src/__support/math/cos.h
+++ b/libc/src/__support/math/cos.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_COS_H
-#define LIBC_SRC___SUPPORT_MATH_COS_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_COS_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_COS_H
#include "range_reduction_double_common.h"
#include "sincos_eval.h"
@@ -170,4 +170,4 @@ LIBC_INLINE static constexpr double cos(double x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_COS_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COS_H
diff --git a/libc/src/__support/math/cosf.h b/libc/src/__support/math/cosf.h
index 48ba71a..e635d30 100644
--- a/libc/src/__support/math/cosf.h
+++ b/libc/src/__support/math/cosf.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_COSF_H
-#define LIBC_SRC___SUPPORT_MATH_COSF_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_COSF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_COSF_H
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -169,6 +169,6 @@ LIBC_INLINE static constexpr float cosf(float x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_COSF_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSF_H
#endif // LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
diff --git a/libc/src/__support/math/dfmaf128.h b/libc/src/__support/math/dfmaf128.h
new file mode 100644
index 0000000..0a266d4
--- /dev/null
+++ b/libc/src/__support/math/dfmaf128.h
@@ -0,0 +1,31 @@
+//===-- Implementation header for dfmaf128 --------------------------------===//
+//
+// 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_DFMAF128_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_DFMAF128_H
+
+#include "include/llvm-libc-types/float128.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+#include "src/__support/FPUtil/FMA.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static double dfmaf128(float128 x, float128 y, float128 z) {
+ return fputil::fma<double>(x, y, z);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_DFMAF128_H
diff --git a/libc/src/__support/math/dfmal.h b/libc/src/__support/math/dfmal.h
new file mode 100644
index 0000000..ffe94bc
--- /dev/null
+++ b/libc/src/__support/math/dfmal.h
@@ -0,0 +1,26 @@
+//===-- Implementation header for dfmal -----------------------------------===//
+//
+// 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_DFMAL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_DFMAL_H
+
+#include "src/__support/FPUtil/FMA.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static double dfmal(long double x, long double y, long double z) {
+ return fputil::fma<double>(x, y, z);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_DFMAL_H
diff --git a/libc/src/__support/math/f16fma.h b/libc/src/__support/math/f16fma.h
new file mode 100644
index 0000000..f7bb2fe
--- /dev/null
+++ b/libc/src/__support/math/f16fma.h
@@ -0,0 +1,33 @@
+//===-- Implementation header for f16fma ------------------------*- 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_MATH_F16FMA_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_F16FMA_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/FMA.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float16 f16fma(double x, double y, double z) {
+ return fputil::fma<float16>(x, y, z);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_F16FMA_H
diff --git a/libc/src/__support/math/f16fmal.h b/libc/src/__support/math/f16fmal.h
new file mode 100644
index 0000000..6e9c4b9
--- /dev/null
+++ b/libc/src/__support/math/f16fmal.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for f16fmal -----------------------*- 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_MATH_F16FMAL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_F16FMAL_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/FMA.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float16 f16fmal(long double x, long double y,
+ long double z) {
+ return fputil::fma<float16>(x, y, z);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_F16FMAL_H
diff --git a/libc/src/__support/math/f16sqrtl.h b/libc/src/__support/math/f16sqrtl.h
new file mode 100644
index 0000000..86f0e59
--- /dev/null
+++ b/libc/src/__support/math/f16sqrtl.h
@@ -0,0 +1,33 @@
+//===-- Implementation header of f16sqrt function -------------------------===//
+//
+// 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_F16SQRTL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_F16SQRTL_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 f16sqrtl(long double x) {
+ return fputil::sqrt<float16>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_F16SQRTL_H
diff --git a/libc/src/__support/math/fsqrt.h b/libc/src/__support/math/fsqrt.h
new file mode 100644
index 0000000..8dd6afc
--- /dev/null
+++ b/libc/src/__support/math/fsqrt.h
@@ -0,0 +1,26 @@
+//===-- Implementation header for fsqrt ------------------------*- 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_MATH_FSQRT_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_FSQRT_H
+
+#include "src/__support/FPUtil/generic/sqrt.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float fsqrt(double x) {
+ return fputil::sqrt<float>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_FSQRT_H
diff --git a/libc/src/__support/math/fsqrtf128.h b/libc/src/__support/math/fsqrtf128.h
new file mode 100644
index 0000000..8ca274ef
--- /dev/null
+++ b/libc/src/__support/math/fsqrtf128.h
@@ -0,0 +1,33 @@
+//===-- Implementation header for fsqrtf128 ---------------------*- 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_MATH_FSQRTF128_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_FSQRTF128_H
+
+#include "include/llvm-libc-types/float128.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+#include "src/__support/FPUtil/generic/sqrt.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float fsqrtf128(float128 x) {
+ return fputil::sqrt<float>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_FSQRTF128_H
diff --git a/libc/src/__support/math/fsqrtl.h b/libc/src/__support/math/fsqrtl.h
new file mode 100644
index 0000000..3033f0a5
--- /dev/null
+++ b/libc/src/__support/math/fsqrtl.h
@@ -0,0 +1,26 @@
+//===-- Implementation header for fsqrtl ------------------------*- 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_MATH_FSQRTL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_FSQRTL_H
+
+#include "src/__support/FPUtil/generic/sqrt.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float fsqrtl(long double x) {
+ return fputil::sqrt<float>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_FSQRTL_H
diff --git a/libc/src/__support/math/hypotf.h b/libc/src/__support/math/hypotf.h
new file mode 100644
index 0000000..e712a07
--- /dev/null
+++ b/libc/src/__support/math/hypotf.h
@@ -0,0 +1,107 @@
+//===-- Implementation header for hypotf ------------------------*- 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_MATH_HYPOTF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_HYPOTF_H
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float hypotf(float x, float y) {
+ using DoubleBits = fputil::FPBits<double>;
+ using FPBits = fputil::FPBits<float>;
+
+ FPBits x_abs = FPBits(x).abs();
+ FPBits y_abs = FPBits(y).abs();
+
+ bool x_abs_larger = x_abs.uintval() >= y_abs.uintval();
+
+ FPBits a_bits = x_abs_larger ? x_abs : y_abs;
+ FPBits b_bits = x_abs_larger ? y_abs : x_abs;
+
+ uint32_t a_u = a_bits.uintval();
+ uint32_t b_u = b_bits.uintval();
+
+ // Note: replacing `a_u >= FPBits::EXP_MASK` with `a_bits.is_inf_or_nan()`
+ // generates extra exponent bit masking instructions on x86-64.
+ if (LIBC_UNLIKELY(a_u >= FPBits::EXP_MASK)) {
+ // x or y is inf or nan
+ if (a_bits.is_signaling_nan() || b_bits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ if (a_bits.is_inf() || b_bits.is_inf())
+ return FPBits::inf().get_val();
+ return a_bits.get_val();
+ }
+
+ if (LIBC_UNLIKELY(a_u - b_u >=
+ static_cast<uint32_t>((FPBits::FRACTION_LEN + 2)
+ << FPBits::FRACTION_LEN)))
+ return x_abs.get_val() + y_abs.get_val();
+
+ double ad = static_cast<double>(a_bits.get_val());
+ double bd = static_cast<double>(b_bits.get_val());
+
+ // These squares are exact.
+ double a_sq = ad * ad;
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ double sum_sq = fputil::multiply_add(bd, bd, a_sq);
+#else
+ double b_sq = bd * bd;
+ double sum_sq = a_sq + b_sq;
+#endif
+
+ // Take sqrt in double precision.
+ DoubleBits result(fputil::sqrt<double>(sum_sq));
+ uint64_t r_u = result.uintval();
+
+ // If any of the sticky bits of the result are non-zero, except the LSB, then
+ // the rounded result is correct.
+ if (LIBC_UNLIKELY(((r_u + 1) & 0x0000'0000'0FFF'FFFE) == 0)) {
+ double r_d = result.get_val();
+
+ // Perform rounding correction.
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ double sum_sq_lo = fputil::multiply_add(bd, bd, a_sq - sum_sq);
+ double err = sum_sq_lo - fputil::multiply_add(r_d, r_d, -sum_sq);
+#else
+ fputil::DoubleDouble r_sq = fputil::exact_mult(r_d, r_d);
+ double sum_sq_lo = b_sq - (sum_sq - a_sq);
+ double err = (sum_sq - r_sq.hi) + (sum_sq_lo - r_sq.lo);
+#endif
+
+ if (err > 0) {
+ r_u |= 1;
+ } else if ((err < 0) && (r_u & 1) == 0) {
+ r_u -= 1;
+ } else if ((r_u & 0x0000'0000'1FFF'FFFF) == 0) {
+ // The rounded result is exact.
+ fputil::clear_except_if_required(FE_INEXACT);
+ }
+ return static_cast<float>(DoubleBits(r_u).get_val());
+ }
+
+ return static_cast<float>(result.get_val());
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_HYPOTF_H
diff --git a/libc/src/__support/math/ilogb.h b/libc/src/__support/math/ilogb.h
new file mode 100644
index 0000000..0215314
--- /dev/null
+++ b/libc/src/__support/math/ilogb.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for ilogb -------------------------*- 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_MATH_ILOGB_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ILOGB_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr int ilogb(double x) {
+ return fputil::intlogb<int>(x);
+}
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ILOGB_H
diff --git a/libc/src/__support/math/ilogbf.h b/libc/src/__support/math/ilogbf.h
new file mode 100644
index 0000000..dfc8f62
--- /dev/null
+++ b/libc/src/__support/math/ilogbf.h
@@ -0,0 +1,26 @@
+//===-- Implementation header for ilogbf ----------------------*- 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_MATH_ILOGBF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBF_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE constexpr int ilogbf(float x) { return fputil::intlogb<int>(x); }
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBF_H
diff --git a/libc/src/__support/math/ilogbf128.h b/libc/src/__support/math/ilogbf128.h
new file mode 100644
index 0000000..47c3643
--- /dev/null
+++ b/libc/src/__support/math/ilogbf128.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for ilogbf128 --------------------*- 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_MATH_ILOGBF128_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBF128_H
+
+#include "include/llvm-libc-types/float128.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr int ilogbf128(float128 x) {
+ return fputil::intlogb<int>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBF128_H
diff --git a/libc/src/__support/math/ilogbl.h b/libc/src/__support/math/ilogbl.h
new file mode 100644
index 0000000..1d6a8b5
--- /dev/null
+++ b/libc/src/__support/math/ilogbl.h
@@ -0,0 +1,28 @@
+//===-- Implementation header for ilogbl ------------------------*- 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_MATH_ILOGBL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBL_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr int ilogbl(long double x) {
+ return fputil::intlogb<int>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ILOGBL_H
diff --git a/libc/src/__support/math/llogb.h b/libc/src/__support/math/llogb.h
new file mode 100644
index 0000000..0c6acf0
--- /dev/null
+++ b/libc/src/__support/math/llogb.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for llogb -------------------------*- 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_MATH_LLOGB_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LLOGB_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static constexpr long llogb(double x) {
+ return fputil::intlogb<long>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LLOGB_H
diff --git a/libc/src/__support/math/llogbf.h b/libc/src/__support/math/llogbf.h
new file mode 100644
index 0000000..1dcdcd0
--- /dev/null
+++ b/libc/src/__support/math/llogbf.h
@@ -0,0 +1,28 @@
+//===-- Implementation header for llogbf ------------------------*- 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_MATH_LLOGBF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr long llogbf(float x) {
+ return fputil::intlogb<long>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF_H
diff --git a/libc/src/__support/math/llogbf128.h b/libc/src/__support/math/llogbf128.h
new file mode 100644
index 0000000..5168647
--- /dev/null
+++ b/libc/src/__support/math/llogbf128.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for llogbf128 ---------------------*- 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_MATH_LLOGBF128_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF128_H
+
+#include "include/llvm-libc-types/float128.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr long llogbf128(float128 x) {
+ return fputil::intlogb<long>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF128_H
diff --git a/libc/src/__support/math/llogbf16.h b/libc/src/__support/math/llogbf16.h
new file mode 100644
index 0000000..55ddd3b9
--- /dev/null
+++ b/libc/src/__support/math/llogbf16.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for llogbf16 ----------------------*- 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_MATH_LLOGBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr long llogbf16(float16 x) {
+ return fputil::intlogb<long>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LLOGBF16_H
diff --git a/libc/src/__support/math/log10.h b/libc/src/__support/math/log10.h
new file mode 100644
index 0000000..8861c89
--- /dev/null
+++ b/libc/src/__support/math/log10.h
@@ -0,0 +1,919 @@
+//===-- Double-precision log10(x) function --------------------------------===//
+//
+// 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_LOG10_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG10_H
+
+#include "common_constants.h"
+#include "log_range_reduction.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/integer_literals.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+namespace log10_internal {
+// 128-bit precision dyadic floating point numbers.
+using Float128 = typename fputil::DyadicFloat<128>;
+
+using LIBC_NAMESPACE::operator""_u128;
+
+using namespace common_constants_internal;
+using namespace math::log_range_reduction_internal;
+
+LIBC_INLINE_VAR constexpr fputil::DoubleDouble LOG10_E = {0x1.95355baaafad3p-57,
+ 0x1.bcb7b1526e50ep-2};
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+// A simple upper bound for the error of e_x * log(2) - log(r).
+LIBC_INLINE_VAR constexpr double HI_ERR = 0x1.0p-85;
+
+// Extra errors from P is from using x^2 to reduce evaluation latency.
+LIBC_INLINE_VAR constexpr double P_ERR = 0x1.0p-51;
+
+// log10(2) with 128-bit precision generated by SageMath with:
+// def format_hex(value):
+// l = hex(value)[2:]
+// n = 8
+// x = [l[i:i + n] for i in range(0, len(l), n)]
+// return "0x" + "'".join(x) + "_u128"
+// (s, m, e) = RealField(128)(2).log10().sign_exponent_mantissa();
+// print(format_hex(m));
+LIBC_INLINE_VAR constexpr Float128
+ LOG10_2(Sign::POS,
+ /*exponent=*/-129, /*mantissa=*/
+ 0x9a209a84'fbcff798'8f8959ac'0b7c9178_u128);
+
+alignas(16) LIBC_INLINE_VAR constexpr LogRR LOG10_TABLE = {
+ // -log10(r) with 128-bit precision generated by SageMath with:
+ //
+ // for i in range(128):
+ // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) );
+ // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
+ // print("{Sign::POS,", e, ", format_hex(m), "},");
+ /* .step_1 = */ {
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -136, 0xdf3b5ebb'da7e186b'65af394f'e05eafd3_u128},
+ {Sign::POS, -135, 0xe01d4057'2f029c16'a8fb8d87'b30163b5_u128},
+ {Sign::POS, -134, 0xa8c1263a'c3f57eb3'6bb0170e'5bb5d630_u128},
+ {Sign::POS, -134, 0xe1e841bb'c26204e5'fc2ea6eb'0ea1370e_u128},
+ {Sign::POS, -133, 0x8dc2eb02'274d6ff4'dc8a199a'4bb63382_u128},
+ {Sign::POS, -133, 0xaacde920'361dd054'86b57ea6'10c7db33_u128},
+ {Sign::POS, -133, 0xc81618eb'15421bab'5f034a40'e6a2f09d_u128},
+ {Sign::POS, -133, 0xe59c7e66'c5fedb4b'594a31b2'c5cc891c_u128},
+ {Sign::POS, -133, 0xf477584f'97b654de'221efda5'8221904b_u128},
+ {Sign::POS, -132, 0x892e8219'75106e09'68a0dc47'567691c9_u128},
+ {Sign::POS, -132, 0x9841c66e'17dfe7da'10bc94f4'4d216b49_u128},
+ {Sign::POS, -132, 0x9fd7be33'18306cc5'e303ea7e'23c9d6fb_u128},
+ {Sign::POS, -132, 0xaf1cb35b'f494a8dd'ce697dba'a00d4c7d_u128},
+ {Sign::POS, -132, 0xbe8380a2'fa7eba5a'9c216079'dcf0ea96_u128},
+ {Sign::POS, -132, 0xc643c775'8283a271'75278940'eecfc3a9_u128},
+ {Sign::POS, -132, 0xd5de75ec'27e4fe68'2d3467d2'53e2d1fc_u128},
+ {Sign::POS, -132, 0xddb904e8'f1272a95'ead4055d'cdec7b22_u128},
+ {Sign::POS, -132, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
+ {Sign::POS, -132, 0xf57e8281'ade9d92d'38dc40c4'fe11e608_u128},
+ {Sign::POS, -131, 0x82c2941b'b20bbe1f'3bcdcfe7'b23976cd_u128},
+ {Sign::POS, -131, 0x86cb3663'2807cdcd'456350b0'bda452a6_u128},
+ {Sign::POS, -131, 0x8eeaa306'458b760a'78185dcc'37fda01a_u128},
+ {Sign::POS, -131, 0x93018395'12fc1168'307643ad'bbbde1b3_u128},
+ {Sign::POS, -131, 0x9b3dd1d5'50c41443'6c449d40'9f883fe3_u128},
+ {Sign::POS, -131, 0x9f6356aa'03c34389'8ea7b30c'8b4ad886_u128},
+ {Sign::POS, -131, 0xa7bd56cd'de5d76a2'961c6e69'0d8879b4_u128},
+ {Sign::POS, -131, 0xabf1ea3e'1d7bd7cf'042643ce'd81ec14a_u128},
+ {Sign::POS, -131, 0xb02b9af7'4c2f879e'4742fb3d'0b5cdd19_u128},
+ {Sign::POS, -131, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
+ {Sign::POS, -131, 0xbcf7dabd'87c01afc'8d3fc634'85e7ff13_u128},
+ {Sign::POS, -131, 0xc1467f69'4d10a581'f3edc493'75fbc5a5_u128},
+ {Sign::POS, -131, 0xc9f3ef07'e1f3fc5e'5fcd7d0c'e937375f_u128},
+ {Sign::POS, -131, 0xce52d50b'94fa253a'58252dad'a9f06111_u128},
+ {Sign::POS, -131, 0xd2b74192'fae43777'62f01e5f'f43708ab_u128},
+ {Sign::POS, -131, 0xd72142a8'4ca85abd'481d9b31'31f52639_u128},
+ {Sign::POS, -131, 0xdb90e68b'8abf14af'b305ced1'419fe924_u128},
+ {Sign::POS, -131, 0xe48150cf'32888b9c'849266a8'5513dc6d_u128},
+ {Sign::POS, -131, 0xe90234c6'5a15e533'080ecf32'66b4dcf4_u128},
+ {Sign::POS, -131, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
+ {Sign::POS, -131, 0xf215a60b'6557943f'ce3537a3'a211b25b_u128},
+ {Sign::POS, -131, 0xf6a85251'3757dfbd'5dab6830'7fedefcd_u128},
+ {Sign::POS, -131, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
+ {Sign::POS, -130, 0x8242724a'155219f3'18aa3021'71017dcb_u128},
+ {Sign::POS, -130, 0x849812d0'ccbb5cbd'abc7e698'502d43c0_u128},
+ {Sign::POS, -130, 0x86f0dab1'ab5822b6'c339089a'51663370_u128},
+ {Sign::POS, -130, 0x894cd27d'9f182c63'26f70b34'ce5cf201_u128},
+ {Sign::POS, -130, 0x8bac02e8'ac3e09ac'676f20a8'7ab433df_u128},
+ {Sign::POS, -130, 0x8e0e74ca'ae062e24'6db4169c'c4b83bc3_u128},
+ {Sign::POS, -130, 0x90743120'1c7f651a'cd3fdb2f'ad0d1fd6_u128},
+ {Sign::POS, -130, 0x92dd410a'd7bfe103'49d03e16'3250d1d4_u128},
+ {Sign::POS, -130, 0x9549add2'f8a3c7e0'9ec7dc02'd5e723b9_u128},
+ {Sign::POS, -130, 0x97b980e7'a743d71c'34698d03'a5442573_u128},
+ {Sign::POS, -130, 0x9a2cc3df'f7548556'0522904d'1e47f3de_u128},
+ {Sign::POS, -130, 0x9ca3807b'ca9fe93f'791a7264'6c87b976_u128},
+ {Sign::POS, -130, 0x9f1dc0a4'b9cea286'3826f190'd655d736_u128},
+ {Sign::POS, -130, 0xa19b8e6f'03b60e45'544ab3e4'8199b299_u128},
+ {Sign::POS, -130, 0xa41cf41a'83643487'be775fa8'2961114e_u128},
+ {Sign::POS, -130, 0xa6a1fc13'ad241953'45798e50'19e6c082_u128},
+ {Sign::POS, -130, 0xa92ab0f4'92b772bd'91fb1ed0'cdc4d1fb_u128},
+ {Sign::POS, -130, 0xabb71d85'ef05380d'818b8b9c'bbd17b72_u128},
+ {Sign::POS, -130, 0xae474cc0'397f0d4f'a50c2fea'60c5b3b2_u128},
+ {Sign::POS, -130, 0xb0db49cc'c1823c8e'58ea3498'0ad8b720_u128},
+ {Sign::POS, -130, 0xb3732006'd1fbbba5'4b5f7194'1be508a4_u128},
+ {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
+ {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
+ {Sign::POS, -130, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
+ {Sign::POS, -130, 0xbb522e5d'bf37f63b'c6696396'40c305bb_u128},
+ {Sign::POS, -130, 0xbdf9def0'4cf980ff'a3dc9e46'4e98764b_u128},
+ {Sign::POS, -130, 0xc0a5a490'dea95b5e'ffd3256b'59fa9c59_u128},
+ {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
+ {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
+ {Sign::POS, -130, 0xc609a1bb'4aa98f59'acb2ca5d'4ca1c10e_u128},
+ {Sign::POS, -130, 0xc8c1f339'9ca7d33b'43690b9e'3cde0d02_u128},
+ {Sign::POS, -130, 0xcb7e8db1'cfe04827'18b1fd60'383f7e5a_u128},
+ {Sign::POS, -130, 0xce3f7eb9'a517c969'0248757e'5f45af3d_u128},
+ {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
+ {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
+ {Sign::POS, -130, 0xd3ce9c15'e10ec927'58ff6362'9a92652d_u128},
+ {Sign::POS, -130, 0xd69ce4e1'6303fcdd'6b49be3b'd8c89f10_u128},
+ {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
+ {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
+ {Sign::POS, -130, 0xdc4733e7'cbcbfc8c'89e281c9'8c1d705c_u128},
+ {Sign::POS, -130, 0xdf235843'9aa5dd12'dc0db7cf'0cce9f32_u128},
+ {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
+ {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
+ {Sign::POS, -130, 0xe4e9e832'e2da0c05'3dd7eab4'8869c402_u128},
+ {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
+ {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
+ {Sign::POS, -130, 0xeac3ecb2'4a3ac7b4'7593e1a9'e917359a_u128},
+ {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
+ {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
+ {Sign::POS, -130, 0xf0b1ea93'f34675a7'c8ba4f8f'47b85a5c_u128},
+ {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
+ {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
+ {Sign::POS, -130, 0xf6b46c0c'8c8fdea1'7ee19afe'6db7e324_u128},
+ {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
+ {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
+ {Sign::POS, -130, 0xfccc00fe'dba4e6fb'efe52ccf'03e7dee1_u128},
+ {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
+ {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
+ {Sign::POS, -129, 0x817c9fa6'43880404'e0b571f5'c91b0446_u128},
+ {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
+ {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
+ {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
+ {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
+ {Sign::POS, -129, 0x863388eb'55ebd295'1a618264'446cb495_u128},
+ {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
+ {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
+ {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
+ {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
+ {Sign::POS, -129, 0x8b04972e'9d4d3011'd28e8ada'fea703b4_u128},
+ {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
+ {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
+ {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
+ {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
+ {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
+ {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
+ {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
+ {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
+ {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
+ {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
+ {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
+ {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
+ {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
+ {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
+ {Sign::POS, -129, 0x98659d3d'd9b12532'336db063'0f536fb9_u128},
+ {Sign::POS, 0, 0_u128},
+ },
+ // -log10(r) for the second step, generated by SageMath with:
+ //
+ // for i in range(-2^6, 2^7 + 1):
+ // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) );
+ // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
+ // print("{Sign::POS," if s == -1 else "{Sign::NEG,", e, ",
+ // format_hex(m), "},");
+ /* .step_2 = */
+ {
+ {Sign::NEG, -137, 0xdeca7290'13cd7c31'7f1ce002'fa34131b_u128},
+ {Sign::NEG, -137, 0xdb5475b4'4946d986'639afa08'5dd8b4c7_u128},
+ {Sign::NEG, -137, 0xd7de6b0e'10cab7d2'05512632'fe9a58cb_u128},
+ {Sign::NEG, -137, 0xd468529c'fc6fb395'b5380a99'53117d07_u128},
+ {Sign::NEG, -137, 0xd0f22c60'9e474741'70af2d7d'53be1f31_u128},
+ {Sign::NEG, -137, 0xcd7bf858'885dcae2'0ccd499c'49b74cc2_u128},
+ {Sign::NEG, -137, 0xca05b684'4cba73cf'5b51ddc3'987ebfb8_u128},
+ {Sign::NEG, -137, 0xc68f66e3'7d5f545a'49375f51'89b3782b_u128},
+ {Sign::NEG, -137, 0xc3190975'ac495b7a'f6e57738'865c712f_u128},
+ {Sign::NEG, -137, 0xbfa29e3a'6b70547e'ca02b10a'8c712acd_u128},
+ {Sign::NEG, -137, 0xbc2c2531'4cc6e6b6'78e50382'10208151_u128},
+ {Sign::NEG, -137, 0xb8b59e59'e23a9524'0fa099ec'd71ee0ea_u128},
+ {Sign::NEG, -137, 0xb53f09b3'bdb3be28'eeb445cc'b8fb09ed_u128},
+ {Sign::NEG, -137, 0xb1c8673e'71159b33'c352fff1'8a1c02fb_u128},
+ {Sign::NEG, -137, 0xae51b6f9'8e3e406e'7949e03e'cf9b390b_u128},
+ {Sign::NEG, -137, 0xaadaf8e4'a7069c6c'2681f33f'30aadedc_u128},
+ {Sign::NEG, -137, 0xa7642cff'4d4277d6'f01d5496'eea213b3_u128},
+ {Sign::NEG, -137, 0xa3ed5349'12c0751d'e92ef555'ff1de975_u128},
+ {Sign::NEG, -137, 0xa0766bc1'894a1022'eb0c7519'b3e7c1e0_u128},
+ {Sign::NEG, -137, 0x9c21b6e9'1e7f03a3'f60d204f'f0fe5296_u128},
+ {Sign::NEG, -137, 0x98aab049'1050bea8'125c19a4'f057c18b_u128},
+ {Sign::NEG, -137, 0x95339bd6'4cd953e7'7e9383ce'1bdf9575_u128},
+ {Sign::NEG, -137, 0x91bc7990'65cc57d6'bf274f4d'8f770253_u128},
+ {Sign::NEG, -137, 0x8e454976'ecd836ad'656bd9b7'58fe44ba_u128},
+ {Sign::NEG, -137, 0x8ace0b89'73a63413'bfdd2c7f'388fc014_u128},
+ {Sign::NEG, -137, 0x8756bfc7'8bda6ad0'83fbf6ed'936c493a_u128},
+ {Sign::NEG, -137, 0x83df6630'c713cc76'71bfa9a1'8bec01cc_u128},
+ {Sign::NEG, -137, 0x8067fec4'b6ec2111'f09d19f5'6dbfef72_u128},
+ {Sign::NEG, -138, 0xf9e11305'd9f00dad'4c422713'b1642228_u128},
+ {Sign::NEG, -138, 0xf2f20cd5'f58de39a'0c3c7c56'99b7a0a4_u128},
+ {Sign::NEG, -138, 0xec02eaf8'e3c656ff'b8db7c69'e3fa0797_u128},
+ {Sign::NEG, -138, 0xe513ad6d'c7a3a553'a083eb05'506ff7ed_u128},
+ {Sign::NEG, -138, 0xde245433'c425b5c5'c21595e7'45f1fa15_u128},
+ {Sign::NEG, -138, 0xd734df49'fc42189b'b9d5bcdb'fe719389_u128},
+ {Sign::NEG, -138, 0xd0454eaf'92e4068b'a17a1e85'e93461f4_u128},
+ {Sign::NEG, -138, 0xc955a263'aaec6016'e3537584'da333fda_u128},
+ {Sign::NEG, -138, 0xc265da65'6731ace5'00963177'f24682c2_u128},
+ {Sign::NEG, -138, 0xbb75f6b3'ea801b1e'4ac03734'7bcfc50e_u128},
+ {Sign::NEG, -138, 0xb485f74e'57997ec6'901a736a'4364cdfd_u128},
+ {Sign::NEG, -138, 0xad95dc33'd1355117'bb550acc'3b9d7247_u128},
+ {Sign::NEG, -138, 0xa6a5a563'7a00afdc'663cf2b2'7e8f1ffb_u128},
+ {Sign::NEG, -138, 0x9fb552dc'749e5cca'5f89bd08'feb39952_u128},
+ {Sign::NEG, -138, 0x98c4e49d'e3a6bcdd'23c2623c'73f494db_u128},
+ {Sign::NEG, -138, 0x91d45aa6'e9a7d7b0'4937d3b5'485af61e_u128},
+ {Sign::NEG, -138, 0x8ae3b4f6'a92556d9'df14214e'7a6d8111_u128},
+ {Sign::NEG, -138, 0x83f2f38c'44988544'bf7cfc14'999fb4bc_u128},
+ {Sign::NEG, -139, 0xfa042ccd'bce09d15'a990c0ee'569a8d51_u128},
+ {Sign::NEG, -139, 0xec223b0b'32227c9e'a38463e9'd941e1c2_u128},
+ {Sign::NEG, -139, 0xde4011cf'2daaff31'ba032453'0edaa03f_u128},
+ {Sign::NEG, -139, 0xd05db117'f419b857'5e997a02'dad7ace7_u128},
+ {Sign::NEG, -139, 0xc27b18e3'c9f977c7'4a14676d'4d0f817e_u128},
+ {Sign::NEG, -139, 0xb4984930'f3c0481c'857c002e'e7a1e473_u128},
+ {Sign::NEG, -139, 0xa6b541fd'b5cf6d89'5923b2eb'72d8012a_u128},
+ {Sign::NEG, -139, 0x98d20348'5473648b'21cde8f8'5ca1f9fd_u128},
+ {Sign::NEG, -139, 0x8aee8d0f'13e3e09e'0be08e08'b1d212d4_u128},
+ {Sign::NEG, -140, 0xfa15bea0'708795e1'69502399'8e6bd7b0_u128},
+ {Sign::NEG, -140, 0xde4df414'0b42822f'634cea67'50617a92_u128},
+ {Sign::NEG, -140, 0xc285ba75'7feb2781'fbd7e970'aef9dbb8_u128},
+ {Sign::NEG, -140, 0xa6bd11c1'564a8ace'9aedc1c1'ba7d0695_u128},
+ {Sign::NEG, -140, 0x8af3f9f4'1600120a'8d306ba2'07233c44_u128},
+ {Sign::NEG, -141, 0xde54e614'8d030322'856a0a3a'00fcf3c1_u128},
+ {Sign::NEG, -141, 0xa6c0fa00'de35f314'b3a2c140'7cf6d38d_u128},
+ {Sign::NEG, -142, 0xde585f4c'5bbbcd3d'd791cf6a'70c3a504_u128},
+ {Sign::NEG, -143, 0xde5a1bf6'27b1f68f'10a633f2'c4a8ea22_u128},
+ {Sign::NEG, 0, 0_u128},
+ {Sign::POS, -143, 0xde5d9565'8a729eab'ed4a68e5'e6e83ddf_u128},
+ {Sign::POS, -142, 0xde5f522b'21e3e25a'3281f187'2cdbee94_u128},
+ {Sign::POS, -141, 0xa6c8cb3b'7e5bbbfd'f1466eda'a96e356e_u128},
+ {Sign::POS, -141, 0xde62cbd2'1e895473'8a607fd6'95dfc3d9_u128},
+ {Sign::POS, -140, 0x8afed570'32bebc7c'c36b8713'ceefe2de_u128},
+ {Sign::POS, -140, 0xa6ccb436'a3c72fa4'5c2e76c9'53e3e3e6_u128},
+ {Sign::POS, -140, 0xc29b023f'dcb2dccf'8e4950fa'5c943bbf_u128},
+ {Sign::POS, -140, 0xde69bf8f'58005dfc'20fa8a73'c585f634_u128},
+ {Sign::POS, -140, 0xfa38ec28'905810a3'0aa106d9'b0a9717a_u128},
+ {Sign::POS, -139, 0x8b044407'80460c2a'85d70e03'2de41aec_u128},
+ {Sign::POS, -139, 0x98ec49a3'11cc30ab'beee21cb'b82a9a78_u128},
+ {Sign::POS, -139, 0xa6d486e8'ba5151a0'abd7b0fd'd8efe6f6_u128},
+ {Sign::POS, -139, 0xb4bcfbda'377d31cc'3221c56e'2c1aa912_u128},
+ {Sign::POS, -139, 0xc2a5a879'470c7c37'57b795a3'6d9c5f19_u128},
+ {Sign::POS, -139, 0xd08e8cc7'a6d0c580'131ec142'c053ac3b_u128},
+ {Sign::POS, -139, 0xde77a8c7'14b08d28'35e3298f'4bb2aa0a_u128},
+ {Sign::POS, -139, 0xec60fc79'4ea73ee4'7133dafd'fc44f160_u128},
+ {Sign::POS, -139, 0xfa4a87e0'12c533eb'74b37d23'121c59d5_u128},
+ {Sign::POS, -138, 0x841a257e'8f97da22'93bf5f42'07da8a4c_u128},
+ {Sign::POS, -138, 0x8b0f22e9'19107c0c'fdb5990e'c6057f4e_u128},
+ {Sign::POS, -138, 0x92043c30'84f41481'2d408a58'b1b202fe_u128},
+ {Sign::POS, -138, 0x98f97155'b274b1ab'1759381b'61dfbf01_u128},
+ {Sign::POS, -138, 0x9feec259'80cedbbe'41e90a05'4df4b9f1_u128},
+ {Sign::POS, -138, 0xa6e42f3c'cf49959d'a1e66c62'03725d50_u128},
+ {Sign::POS, -138, 0xadd9b800'7d365d83'8693d36a'b45bd7ce_u128},
+ {Sign::POS, -138, 0xb4cf5ca5'69f12da9'91e25bb4'0ad3f098_u128},
+ {Sign::POS, -138, 0xbbc51d2c'74e07cf0'bdf94392'c4cc7f6c_u128},
+ {Sign::POS, -138, 0xc2baf996'7d753f89'6fe37973'354a82f9_u128},
+ {Sign::POS, -138, 0xc9b0f1e4'632ae79b'97647b42'67bfd801_u128},
+ {Sign::POS, -138, 0xd0a70617'058765ee'dbf5c32a'454f7bdf_u128},
+ {Sign::POS, -138, 0xd79d362f'441b2a92'd6edfe04'c37ba916_u128},
+ {Sign::POS, -138, 0xde93822d'fe812587'5ad3480c'cfbe9890_u128},
+ {Sign::POS, -138, 0xe589ea14'145ec764'c7d9ac76'5be7e325_u128},
+ {Sign::POS, -138, 0xec806de2'65640204'6d8f24b9'a3ca011b_u128},
+ {Sign::POS, -138, 0xf3770d99'd14b4928'f9b65480'7dcdd5b2_u128},
+ {Sign::POS, -138, 0xfa6dc93b'37d99326'f4513f47'45663028_u128},
+ {Sign::POS, -137, 0x80b25063'bc6f2cc6'a46e9a72'd80da75f_u128},
+ {Sign::POS, -137, 0x842dca1f'ba19cce6'ee60992b'51ffac4b_u128},
+ {Sign::POS, -137, 0x87a951d2'04deeaf3'1977fa1c'786886b3_u128},
+ {Sign::POS, -137, 0x8b24e77b'0cb60a84'0e5f7c52'cdf119d5_u128},
+ {Sign::POS, -137, 0x8ea08b1b'419bf221'3bf9d70d'a1021a10_u128},
+ {Sign::POS, -137, 0x921c3cb3'1392ab94'fd0406b0'7523b8e6_u128},
+ {Sign::POS, -137, 0x9597fc42'f2a18441'0453ee32'c020f2a8_u128},
+ {Sign::POS, -137, 0x9913c9cb'4ed50d72'cfb3ec22'066bf7f6_u128},
+ {Sign::POS, -137, 0x9c8fa54c'983f1cb8'215c025b'd493ecf9_u128},
+ {Sign::POS, -137, 0x9f2c9319'2e68232b'39c116b7'ee3a83ec_u128},
+ {Sign::POS, -137, 0xa2a8870f'24ac5f66'f41f4b3e'de2782f0_u128},
+ {Sign::POS, -137, 0xa62488ff'3c735799'61196927'723eb75c_u128},
+ {Sign::POS, -137, 0xa9a098e9'e5e2a432'0e615e83'6cb1edab_u128},
+ {Sign::POS, -137, 0xad1cb6cf'91252372'6981331c'5fc71cfc_u128},
+ {Sign::POS, -137, 0xb098e2b0'ae6af9c2'5f6a4faa'054f11fa_u128},
+ {Sign::POS, -137, 0xb4151c8d'ade99205'02a68bc6'81a74c28_u128},
+ {Sign::POS, -137, 0xb7916466'ffdb9ded'382ba24d'90566403_u128},
+ {Sign::POS, -137, 0xbb0dba3d'14811652'6ad1abe5'1dd22e00_u128},
+ {Sign::POS, -137, 0xbe8a1e10'5c1f3b85'456d3f7f'59b13960_u128},
+ {Sign::POS, -137, 0xc2068fe1'470095a4'738dd8b7'd66e9058_u128},
+ {Sign::POS, -137, 0xc5830fb0'4574f4f1'68e123fe'd7ff11c6_u128},
+ {Sign::POS, -137, 0xc8ff9d7d'c7d17225'2f3bd097'80c3aa11_u128},
+ {Sign::POS, -137, 0xcc7c394a'3e706ec5'3b48887f'1ce36935_u128},
+ {Sign::POS, -137, 0xcff8e316'19b19578'47ddae65'5ecc4633_u128},
+ {Sign::POS, -137, 0xd3759ae1'c9f9da5b'37fa81ee'f4819c88_u128},
+ {Sign::POS, -137, 0xd6f260ad'bfb37b55'ff6c4a8d'747c65ed_u128},
+ {Sign::POS, -137, 0xda6f347a'6b4e0070'921c2949'3a33318c_u128},
+ {Sign::POS, -137, 0xddec1648'3d3e3c27'da0631eb'65e731d8_u128},
+ {Sign::POS, -137, 0xe1690617'a5fe4bc2'b3da6c07'd110babc_u128},
+ {Sign::POS, -137, 0xe4e603e9'160d97a6'f2485c78'68b8835a_u128},
+ {Sign::POS, -137, 0xe8630fbc'fdf0d3ae'67f5b7ed'01344055_u128},
+ {Sign::POS, -137, 0xebe02993'ce31ff7b'f820df44'5b1d0622_u128},
+ {Sign::POS, -137, 0xef5d516d'f76066d0'adefc674'b7eca5cd_u128},
+ {Sign::POS, -137, 0xf2da874b'ea10a1e0'da6be6dc'057d3235_u128},
+ {Sign::POS, -137, 0xf657cb2e'16dc95a9'392bdde1'52ab5ff5_u128},
+ {Sign::POS, -137, 0xf9d51d14'ee637444'1bab58e2'ec99cf73_u128},
+ {Sign::POS, -137, 0xfd527d00'e149bd3e'9b51ef7e'3388d692_u128},
+ {Sign::POS, -136, 0x8067f579'301c9ef6'e914c6a7'f3f22fa2_u128},
+ {Sign::POS, -136, 0x8226b374'edf088e2'0d22862e'b2081c94_u128},
+ {Sign::POS, -136, 0x83e57873'e27ad153'29ebd0b4'76cd8fd8_u128},
+ {Sign::POS, -136, 0x85a44476'461854a0'98feddc2'806d01ed_u128},
+ {Sign::POS, -136, 0x8763177c'512896af'471bfc26'1a401854_u128},
+ {Sign::POS, -136, 0x88b23a5b'61430a16'b6f89c19'b4cd1acd_u128},
+ {Sign::POS, -136, 0x8a7119a8'5909ebe9'b39aaf34'163fb099_u128},
+ {Sign::POS, -136, 0x8c2ffff9'9357e887'1665f0f8'21541c36_u128},
+ {Sign::POS, -136, 0x8deeed4f'489679a6'a5051754'e049c1cb_u128},
+ {Sign::POS, -136, 0x8fade1a9'b131c159'8c5a9a1c'57b2e986_u128},
+ {Sign::POS, -136, 0x916cdd09'05988a35'1d844843'8a26a9ae_u128},
+ {Sign::POS, -136, 0x932bdf6d'7e3c477d'8e3a0913'ecd2fd02_u128},
+ {Sign::POS, -136, 0x94eae8d7'53911550'bc881a45'f47f1d36_u128},
+ {Sign::POS, -136, 0x96a9f946'be0db8d0'f5e51c05'499b06d0_u128},
+ {Sign::POS, -136, 0x986910bb'f62ba04f'c1a43be8'1a243fde_u128},
+ {Sign::POS, -136, 0x9a282f37'3466e378'aec3cfeb'e971beb7_u128},
+ {Sign::POS, -136, 0x9be754b8'b13e437c'2518b293'28614989_u128},
+ {Sign::POS, -136, 0x9da68140'a5332b3a'39d6b147'cbe803a4_u128},
+ {Sign::POS, -136, 0x9f65b4cf'48c9af6d'87765e30'04ae428d_u128},
+ {Sign::POS, -136, 0xa124ef64'd4888ed6'08f896ab'28245bac_u128},
+ {Sign::POS, -136, 0xa2e43101'80f93263'f8880fb5'ca630c87_u128},
+ {Sign::POS, -136, 0xa4a379a5'86a7ad62'b179397c'f82e935c_u128},
+ {Sign::POS, -136, 0xa662c951'1e22bda3'95a8cb71'7197ad81_u128},
+ {Sign::POS, -136, 0xa8222004'7ffbcba8'f6394a34'b7f9a4a4_u128},
+ {Sign::POS, -136, 0xa9e17dbf'e4c6ead0'ffafd8c2'b57884e8_u128},
+ {Sign::POS, -136, 0xaba0e283'851ad980'a970a643'b8a6ac2b_u128},
+ {Sign::POS, -136, 0xad604e4f'9991014e'a89b49fb'749d47e0_u128},
+ {Sign::POS, -136, 0xaf1fc124'5ac5772e'66475ed2'ac983305_u128},
+ {Sign::POS, -136, 0xb06f5be1'bf1918e7'b4fd6209'364bb36f_u128},
+ {Sign::POS, -136, 0xb22edb06'36da31d6'8b5ce79b'0965962a_u128},
+ {Sign::POS, -136, 0xb3ee6133'f7149769'6724232b'07396427_u128},
+ {Sign::POS, -136, 0xb5adee6b'386e62ae'2f02b14d'cad8a49c_u128},
+ {Sign::POS, -136, 0xb76d82ac'339058db'bd6443a8'1f792e07_u128},
+ {Sign::POS, -136, 0xb92d1df7'2125eb7c'ea1cd962'5749939a_u128},
+ {Sign::POS, -136, 0xbaecc04c'39dd389b'97775e31'42198913_u128},
+ {Sign::POS, -136, 0xbcac69ab'b6670aeb'c2a701b8'09a2bc39_u128},
+ {Sign::POS, -136, 0xbe6c1a15'cf76d9f6'979b990f'39e662e3_u128},
+ {Sign::POS, -136, 0xc02bd18a'bdc2ca45'88395c46'3ddd82b2_u128},
+ {Sign::POS, -136, 0xc1eb900a'ba03ad8d'66f451bd'9ba5ed05_u128},
+ {Sign::POS, -136, 0xc3ab5595'fcf502d9'84cfb941'3f6437a6_u128},
+ {Sign::POS, -136, 0xc56b222c'bf54f6b6'd2c1c8d3'2943ca42_u128},
+ {Sign::POS, -136, 0xc72af5cf'39e4635f'067c0d1f'd95192e6_u128},
+ {Sign::POS, -136, 0xc8ead07d'a566d0e3'c298bf9e'db6441f2_u128},
+ {Sign::POS, -136, 0xcaaab238'3aa27559'c22d646a'ddde3910_u128},
+ {Sign::POS, -136, 0xcc6a9aff'32603504'07c301e5'c7d1ca40_u128},
+ {Sign::POS, -136, 0xce2a8ad2'c56ba27f'0fb44446'4df02505_u128},
+ {Sign::POS, -136, 0xcfea81b3'2c92feec'05f1df35'91ae898f_u128},
+ {Sign::POS, -136, 0xd13a7f7c'07506f7d'b43caf8e'7b891066_u128},
+ {Sign::POS, -136, 0xd2fa82b3'6a610c4f'597fb13f'0d0fdf19_u128},
+ {Sign::POS, -136, 0xd4ba8cf8'3dd2a06b'3c21f1c6'0a60b0d6_u128},
+ {Sign::POS, -136, 0xd67a9e4a'ba7d7ce5'2b745590'9a0428a4_u128},
+ {Sign::POS, -136, 0xd83ab6ab'193ca223'1438b605'73d2da10_u128},
+ {Sign::POS, -136, 0xd9fad619'92edc008'49f86400'c5ab2b11_u128},
+ {Sign::POS, -136, 0xdbbafc96'60713620'd3c313d1'48a23c35_u128},
+ {Sign::POS, -136, 0xdd7b2a21'baaa13cc'bc568523'55e0f0d5_u128},
+ },
+ // -log10(r) for the third step, generated by SageMath with:
+ //
+ // for i in range(-80, 81):
+ // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
+ // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
+ // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, "," ,
+ // format_hex(m), "},");
+ /* .step_3 = */
+ {
+ {Sign::NEG, -143, 0x8af8b9b3'22ba8c7d'54d7e498'98ca0093_u128},
+ {Sign::NEG, -143, 0x893c0652'9deffc3d'c321bbf1'6665f29c_u128},
+ {Sign::NEG, -143, 0x877f52e4'33ac7ec4'8246df71'40c3e4ae_u128},
+ {Sign::NEG, -143, 0x85c29f67'e3ef35bc'1deaa9e8'5780e4c1_u128},
+ {Sign::NEG, -143, 0x8405ebdd'aeb742cf'0cd8a512'1a9162d0_u128},
+ {Sign::NEG, -143, 0x82493845'9403c7a7'b10486fa'4644308d_u128},
+ {Sign::NEG, -143, 0x808c849f'93d3e5f0'578a2f61'eedd4be8_u128},
+ {Sign::NEG, -144, 0xfd9fa1d7'5c4d7ea6'715b4a49'1790e8a7_u128},
+ {Sign::NEG, -144, 0xfa263a53'c5f6eaf4'efb6273a'04c71573_u128},
+ {Sign::NEG, -144, 0xf6acd2b4'64a25420'474d9015'60c17807_u128},
+ {Sign::NEG, -144, 0xf3336af9'384dfd7c'6b9a5dec'eb80ec57_u128},
+ {Sign::NEG, -144, 0xefba0322'40f82a5d'2665a32f'7cc64f79_u128},
+ {Sign::NEG, -144, 0xec409b2f'7e9f1e16'17c8a673'16659363_u128},
+ {Sign::NEG, -144, 0xe8c73320'f1411bfa'b62cdd3e'f5c8673d_u128},
+ {Sign::NEG, -144, 0xe54dcaf6'98dc675e'4e4be6d5'a4a07422_u128},
+ {Sign::NEG, -144, 0xe1d462b0'756f4394'032f86ff'08c92e22_u128},
+ {Sign::NEG, -144, 0xde5afa4e'86f7f3ee'ce31a0d2'7359396f_u128},
+ {Sign::NEG, -144, 0xdae191d0'cd74bbc1'7efc3180'aee36373_u128},
+ {Sign::NEG, -144, 0xd7682937'48e3de5e'bb894b1e'0ce72fc4_u128},
+ {Sign::NEG, -144, 0xd3eec081'f9439f19'00230f6c'7270f8be_u128},
+ {Sign::NEG, -144, 0xd07557b0'de924142'9f63aaa5'63e9a399_u128},
+ {Sign::NEG, -144, 0xccfbeec3'f8ce082d'c2354e44'1015e7eb_u128},
+ {Sign::NEG, -144, 0xc98285bb'47f5372c'67d22bcf'5a452a4c_u128},
+ {Sign::NEG, -144, 0xc6091c96'cc061190'65c46fa3'e3afea18_u128},
+ {Sign::NEG, -144, 0xc28fb356'84fedaab'67e63bbe'1405c20d_u128},
+ {Sign::NEG, -144, 0xbf1649fa'72ddd5ce'f061a284'212afbad_u128},
+ {Sign::NEG, -144, 0xbb9ce082'95a1464c'57b0a190'1625b539_u128},
+ {Sign::NEG, -144, 0xb82376ee'ed476f74'cc9d1c79'd93a9a1e_u128},
+ {Sign::NEG, -144, 0xb4aa0d3f'79ce9499'5440d7a1'31392da8_u128},
+ {Sign::NEG, -144, 0xb130a374'3b34f90a'ca0572f7'c9f7a7de_u128},
+ {Sign::NEG, -144, 0xadb7398d'3178e019'dfa464cb'37fe6455_u128},
+ {Sign::NEG, -144, 0xaa3dcf8a'5c988d17'1d26f48e'fb62e2e0_u128},
+ {Sign::NEG, -144, 0xa6c4656b'bc924352'e0e635a6'81d259e2_u128},
+ {Sign::NEG, -144, 0xa34afb31'5164461d'5f8b022f'27cbda35_u128},
+ {Sign::NEG, -144, 0x9fd190db'1b0cd8c6'a40df5ca'390a0465_u128},
+ {Sign::NEG, -144, 0x9c582669'198a3e9e'8fb76866'f01c4f2d_u128},
+ {Sign::NEG, -144, 0x98debbdb'4cdabaf4'da1f690c'752fdeff_u128},
+ {Sign::NEG, -144, 0x95655131'b4fc9119'112db8a3'dc07ee78_u128},
+ {Sign::NEG, -144, 0x91ebe66c'51ee045a'9919c4c2'2125c79e_u128},
+ {Sign::NEG, -144, 0x8e727b8b'23ad5808'ac6aa272'26204db3_u128},
+ {Sign::NEG, -144, 0x8af9108e'2a38cf72'5bf708fe'ad2b1780_u128},
+ {Sign::NEG, -144, 0x877fa575'658eade6'8ee54cbc'53cd19ed_u128},
+ {Sign::NEG, -144, 0x84063a40'd5ad36b4'02ab59d3'8cc6e2c5_u128},
+ {Sign::NEG, -144, 0x808ccef0'7a92ad29'4b0eaf0a'99286378_u128},
+ {Sign::NEG, -145, 0xfa26c708'a87aa929'a448b11f'012c975c_u128},
+ {Sign::NEG, -145, 0xf333eff8'c556e089'b0a1d584'117de73b_u128},
+ {Sign::NEG, -145, 0xec4118b1'4bb6870e'e890f9fb'57fdabb6_u128},
+ {Sign::NEG, -145, 0xe54e4132'3b962355'261d48c7'1e693130_u128},
+ {Sign::NEG, -145, 0xde5b697b'94f23bf7'efecdd48'ed894c32_u128},
+ {Sign::NEG, -145, 0xd768918d'57c75792'7944b995'7598a88a_u128},
+ {Sign::NEG, -145, 0xd075b967'8411fcbf'a208bc08'75093645_u128},
+ {Sign::NEG, -145, 0xc982e10a'19ceb219'f6bb94d8'9da8b432_u128},
+ {Sign::NEG, -145, 0xc2900875'18f9fe3b'b07ebbab'782457b0_u128},
+ {Sign::NEG, -145, 0xbb9d2fa8'819067be'b5126529'45eb9165_u128},
+ {Sign::NEG, -145, 0xb4aa56a4'538e753c'96d57890'e171eea5_u128},
+ {Sign::NEG, -145, 0xadb77d68'8ef0ad4e'94c5854b'9cd01726_u128},
+ {Sign::NEG, -145, 0xa6c4a3f5'33b3968d'9a7eb881'1ec3e6bb_u128},
+ {Sign::NEG, -145, 0x9fd1ca4a'41d3b792'403bd2ab'3e0fa2d7_u128},
+ {Sign::NEG, -145, 0x98def067'b94d96f4'cad61d29'db384b6b_u128},
+ {Sign::NEG, -145, 0x91ec164d'9a1dbb4d'2bc55fd6'b8a306ec_u128},
+ {Sign::NEG, -145, 0x8af93bfb'e440ab33'011fd699'5111a927_u128},
+ {Sign::NEG, -145, 0x84066172'97b2ed3d'959a26fa'ac7e5494_u128},
+ {Sign::NEG, -146, 0xfa270d63'68e21007'c10eab72'66ac6bc0_u128},
+ {Sign::NEG, -146, 0xec415772'74ef0439'0bb178b9'0026b2b2_u128},
+ {Sign::NEG, -146, 0xde5ba112'5385c43b'ac3bfd92'5e6b33e1_u128},
+ {Sign::NEG, -146, 0xd075ea43'049f5d3b'9d0a01a9'5b355319_u128},
+ {Sign::NEG, -146, 0xc2903304'8834dc64'31b3b7b2'0a6a6496_u128},
+ {Sign::NEG, -146, 0xb4aa7b56'de3f4ee0'170da891'504620f4_u128},
+ {Sign::NEG, -146, 0xa6c4c33a'06b7c1d9'53289e84'744549cb_u128},
+ {Sign::NEG, -146, 0x98df0aae'01974279'45519048'b0ce7e7f_u128},
+ {Sign::NEG, -146, 0x8af951b2'ced6dde8'a6118c42'bf99407e_u128},
+ {Sign::NEG, -147, 0xfa273090'dcdf429f'0e5b474c'c5a64cf6_u128},
+ {Sign::NEG, -147, 0xde5bbcdd'c0b533aa'a74dab3b'd6067bc7_u128},
+ {Sign::NEG, -147, 0xc290484c'4921a941'9f73f4e3'7357341b_u128},
+ {Sign::NEG, -147, 0xa6c4d2dc'7616bdb0'31bf5d5f'815220e7_u128},
+ {Sign::NEG, -147, 0x8af95c8e'47868b41'4b987ca5'fca242d7_u128},
+ {Sign::NEG, -148, 0xde5bcac3'7ac6587d'19be3fab'd93832c5_u128},
+ {Sign::NEG, -148, 0xa6c4daad'af3d75e0'8fd43f0c'9ce444d3_u128},
+ {Sign::NEG, -149, 0xde5bd1b6'58ad4676'061cd853'e796bc2c_u128},
+ {Sign::NEG, -150, 0xde5bd52f'c7d8545f'87d6afab'fba0644f_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -150, 0xde5bdc22'a69d9e19'a9bf3200'1043629d_u128},
+ {Sign::POS, -149, 0xde5bdf9c'1637d9ef'8014f0f3'60272d82_u128},
+ {Sign::POS, -148, 0xa6c4ea50'24795bd2'fe94a02f'c639c0e3_u128},
+ {Sign::POS, -148, 0xde5be68e'f5db7f99'bee710a5'ace7c8d4_u128},
+ {Sign::POS, -147, 0x8af97245'3faf11e8'1a778d81'00437e4f_u128},
+ {Sign::POS, -147, 0xa6c4f221'608e89fe'97d773f8'992f7051_u128},
+ {Sign::POS, -147, 0xc29072db'dd9a0dd5'0c9ee584'1a3afa95_u128},
+ {Sign::POS, -147, 0xde5bf474'b6df8331'7b644b13'993cf4ef_u128},
+ {Sign::POS, -147, 0xfa2776eb'ec6ccfdb'3448f66e'2bd7a0ca_u128},
+ {Sign::POS, -146, 0x8af97d20'bf27eccd'6a7ca5f1'a87a1a3c_u128},
+ {Sign::POS, -146, 0x98df3f3a'b64b431d'245675fe'3061108f_u128},
+ {Sign::POS, -146, 0xa6c501c3'dba75dc2'64136e97'019d0a3b_u128},
+ {Sign::POS, -146, 0xb4aac4bc'2f432fa3'6cdadac4'd6925bd4_u128},
+ {Sign::POS, -146, 0xc2908823'b125aba7'2899e237'91d29632_u128},
+ {Sign::POS, -146, 0xd0764bfa'6155c4b5'28039e1f'0323a4c1_u128},
+ {Sign::POS, -146, 0xde5c1040'3fda6db5'a2912e03'afc8cc28_u128},
+ {Sign::POS, -146, 0xec41d4f5'4cba9991'7681cc9f'9e0d89f9_u128},
+ {Sign::POS, -146, 0xfa279a19'87fd3b32'28dae4b7'241255e1_u128},
+ {Sign::POS, -145, 0x8406afd6'78d4a2c0'f2b412f8'dceda28e_u128},
+ {Sign::POS, -145, 0x8af992d7'c4e2d5b5'bf5dccd9'67504857_u128},
+ {Sign::POS, -145, 0x91ec7610'a82cafed'3716dbf9'50b07f85_u128},
+ {Sign::POS, -145, 0x98df5981'22b5aadd'69eebe0b'8e5b18e1_u128},
+ {Sign::POS, -145, 0x9fd23d29'34813ffc'bb583ce6'5af56beb_u128},
+ {Sign::POS, -145, 0xa6c52108'dd92e8c1'e22978ef'a7a962a0_u128},
+ {Sign::POS, -145, 0xadb80520'1dee1ea3'e89bf389'8ef27836_u128},
+ {Sign::POS, -145, 0xb4aae96e'f5965b1a'2c4c997e'c90bab0b_u128},
+ {Sign::POS, -145, 0xbb9dcdf5'648f179c'5e3bcd6f'21fe6224_u128},
+ {Sign::POS, -145, 0xc290b2b3'6adbcda2'82cd723b'f1524680_u128},
+ {Sign::POS, -145, 0xc98397a9'087ff6a4'f1c8f574'935e109b_u128},
+ {Sign::POS, -145, 0xd0767cd6'3d7f0c1c'565959c2'e4394a59_u128},
+ {Sign::POS, -145, 0xd769623b'09dc8781'af0d4157'bc4f05be_u128},
+ {Sign::POS, -145, 0xde5c47d7'6d9be24e'4dd6f857'6e9188b8_u128},
+ {Sign::POS, -145, 0xe54f2dab'68c095fb'd80c7f46'484eee3d_u128},
+ {Sign::POS, -145, 0xec4213b6'fb4e1c04'46679575'12a6bd26_u128},
+ {Sign::POS, -145, 0xf334f9fa'2547ede1'e505c36d'95a074fa_u128},
+ {Sign::POS, -145, 0xfa27e074'e6b1850f'5368655f'1ce3110b_u128},
+ {Sign::POS, -144, 0x808d6393'9fc72d83'c23a5ac5'7f06c112_u128},
+ {Sign::POS, -144, 0x8406d708'97f0f4a2'df39eb58'90580f93_u128},
+ {Sign::POS, -144, 0x87804a99'5bd7d4a2'cd896f3e'43f38669_u128},
+ {Sign::POS, -144, 0x8af9be45'eb7d8a41'83b16ff7'eecace8c_u128},
+ {Sign::POS, -144, 0x8e73320e'46e3d23d'21ec7ae8'ffa1531d_u128},
+ {Sign::POS, -144, 0x91eca5f2'6e0c6953'f227268d'464ae907_u128},
+ {Sign::POS, -144, 0x956619f2'60f90c44'680017af'3bbaf2d3_u128},
+ {Sign::POS, -144, 0x98df8e0e'1fab77cd'20c8069e'4ae400de_u128},
+ {Sign::POS, -144, 0x9c590245'aa2568ac'e381c465'1a67ee13_u128},
+ {Sign::POS, -144, 0x9fd27699'00689ba2'a0e23fff'd718794e_u128},
+ {Sign::POS, -144, 0xa34beb08'2276cd6d'73508b92'7f485b97_u128},
+ {Sign::POS, -144, 0xa6c55f93'1051bacc'9ee5e19f'2eecdb55_u128},
+ {Sign::POS, -144, 0xaa3ed439'c9fb207f'916daa3c'6c8fdc9d_u128},
+ {Sign::POS, -144, 0xadb848fc'4f74bb45'e265804b'77126ed3_u128},
+ {Sign::POS, -144, 0xb131bdda'a0c047df'52fd36ae'943fd7b4_u128},
+ {Sign::POS, -144, 0xb4ab32d4'bddf830b'ce16dd7f'60311bf6_u128},
+ {Sign::POS, -144, 0xb824a7ea'a6d4298b'6846c745'1d8105ac_u128},
+ {Sign::POS, -144, 0xbb9e1d1c'5b9ff81e'5fd38e2b'0650a884_u128},
+ {Sign::POS, -144, 0xbf179269'dc44ab85'1cb61936'9e1c641f_u128},
+ {Sign::POS, -144, 0xc29107d3'28c40080'3099a17e'0461648c_u128},
+ {Sign::POS, -144, 0xc60a7d58'411fb3d0'56dbb75e'4813a12b_u128},
+ {Sign::POS, -144, 0xc983f2f9'25598236'748c47b1'bbe45a07_u128},
+ {Sign::POS, -144, 0xccfd68b5'd5732873'986da106'4b5913e1_u128},
+ {Sign::POS, -144, 0xd076de8e'516e6348'faf478d3'd0b31300_u128},
+ {Sign::POS, -144, 0xd3f05482'994cef77'fe47f0b2'6ba754ff_u128},
+ {Sign::POS, -144, 0xd769ca92'ad1089c2'2e419b90'd8e709b7_u128},
+ {Sign::POS, -144, 0xdae340be'8cbaeee9'406d82ea'ca788b6f_u128},
+ {Sign::POS, -144, 0xde5cb706'384ddbaf'140a2bff'40e0d670_u128},
+ {Sign::POS, -144, 0xe1d62d69'afcb0cd5'b2089d06'e51d8034_u128},
+ {Sign::POS, -144, 0xe54fa3e8'f3343f1f'4d0c626a'636f2e4f_u128},
+ {Sign::POS, -144, 0xe8c91a84'028b2f4e'416b93f8'c6f48d30_u128},
+ {Sign::POS, -144, 0xec42913a'ddd19a25'152eda1d'd615c6f5_u128},
+ {Sign::POS, -144, 0xefbc080d'85093c66'78117318'6fc07a66_u128},
+ {Sign::POS, -144, 0xf3357efb'f833d2d5'43813830'e974324d_u128},
+ {Sign::POS, -144, 0xf6aef606'37531a34'7a9ea2ef'6e1f5d41_u128},
+ {Sign::POS, -144, 0xfa286d2c'4268cf47'4a3cd252'5dccc623_u128},
+ {Sign::POS, -144, 0xfda1e46e'1976aed1'08e19004'ae218d5d_u128},
+ {Sign::POS, -143, 0x808dade5'de3f3aca'9b62aaca'25d5d18a_u128},
+ {Sign::POS, -143, 0x824a69a2'95c0f02b'bee9a8d4'3e00613c_u128},
+ {Sign::POS, -143, 0x8407256d'334155ed'd8d4b69c'2056f729_u128},
+ {Sign::POS, -143, 0x85c3e145'b6c14a72'e7cc2860'5d7bb77e_u128},
+ {Sign::POS, -143, 0x87809d2c'2041ac1c'ff51b4bd'c834a8f1_u128},
+ {Sign::POS, -143, 0x893d5920'6fc3594e'47c0774a'a81c3561_u128},
+ {Sign::POS, -143, 0x8afa1522'a5473068'fe4cf331'ecb9eb62_u128},
+ },
+ // -log10(r) for the fourth step, generated by SageMath with:
+ //
+ // for i in range(-65, 65):
+ // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) );
+ // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
+ // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",",
+ // format_hex(m), "},");
+ /* .step_4 = */
+ {
+ {Sign::NEG, -151, 0xe1d54641'22cf95a4'e471a82b'bedbe0ae_u128},
+ {Sign::NEG, -151, 0xde5bd6ec'7f7bc110'af6e93be'8e4c1764_u128},
+ {Sign::NEG, -151, 0xdae26797'a490f80e'e44848f0'a5779499_u128},
+ {Sign::NEG, -151, 0xd768f842'920f3a98'90205533'f4e70566_u128},
+ {Sign::NEG, -151, 0xd3ef88ed'47f688a6'c01844ac'e3729e48_u128},
+ {Sign::NEG, -151, 0xd0761997'c646e232'8151a232'4e41c7c4_u128},
+ {Sign::NEG, -151, 0xccfcaa42'0d004734'e0edf74d'88cacafd_u128},
+ {Sign::NEG, -151, 0xc9833aec'1c22b7a6'ec0ecc3a'5cd27e58_u128},
+ {Sign::NEG, -151, 0xc609cb95'f3ae3381'afd5a7e7'0a6bf214_u128},
+ {Sign::NEG, -151, 0xc2905c3f'93a2babe'39640ff4'47f81ceb_u128},
+ {Sign::NEG, -151, 0xbf16ece8'fc004d55'95db88b5'422588b1_u128},
+ {Sign::NEG, -151, 0xbb9d7d92'2cc6eb40'd25d952f'9beffeec_u128},
+ {Sign::NEG, -151, 0xb8240e3b'25f69478'fc0bb71b'6ea03578_u128},
+ {Sign::NEG, -151, 0xb4aa9ee3'e78f48f7'20076ee3'49cb7b20_u128},
+ {Sign::NEG, -151, 0xb1312f8c'719108b4'4b723ba4'3353643d_u128},
+ {Sign::NEG, -151, 0xadb7c034'c3fbd3a9'8b6d9b2d'a7657754_u128},
+ {Sign::NEG, -151, 0xaa3e50dc'decfa9cf'ed1b0a01'987ad9b4_u128},
+ {Sign::NEG, -151, 0xa6c4e184'c20c8b20'7d9c0354'6f57fc11_u128},
+ {Sign::NEG, -151, 0xa34b722c'6db27794'4a12010d'0b0c4727_u128},
+ {Sign::NEG, -151, 0x9fd202d3'e1c16f24'5f9e7bc4'c0f1c851_u128},
+ {Sign::NEG, -151, 0x9c58937b'1e3971c9'cb62eac7'5cacde29_u128},
+ {Sign::NEG, -151, 0x98df2422'231a7f7d'9a80c413'202be52a_u128},
+ {Sign::NEG, -151, 0x9565b4c8'f0649838'da197c58'c3a6e445_u128},
+ {Sign::NEG, -151, 0x91ec456f'8617bbf4'974e86fb'759f3988_u128},
+ {Sign::NEG, -151, 0x8e72d615'e433eaa9'df415610'dadf46b3_u128},
+ {Sign::NEG, -151, 0x8af966bc'0ab92451'bf135a61'0e7a1ddc_u128},
+ {Sign::NEG, -151, 0x877ff761'f9a768e5'43e60366'a1cb2e09_u128},
+ {Sign::NEG, -151, 0x84068807'b0feb85d'7adabf4e'9c75efce_u128},
+ {Sign::NEG, -151, 0x808d18ad'30bf12b3'7112faf8'7c6591ee_u128},
+ {Sign::NEG, -152, 0xfa2752a4'f1d0efc0'676043ec'6b994be5_u128},
+ {Sign::NEG, -152, 0xf33473ef'12f5cfb9'9fa73d18'6649999d_u128},
+ {Sign::NEG, -152, 0xec419538'c4ecc544'a53db362'aa5cc6f0_u128},
+ {Sign::NEG, -152, 0xe54eb682'07b5d053'9266761d'e5e05f13_u128},
+ {Sign::NEG, -152, 0xde5bd7ca'db50f0d8'81645201'b36e17ba_u128},
+ {Sign::NEG, -152, 0xd768f913'3fbe26c5'8c7a112a'9a2b2a52_u128},
+ {Sign::NEG, -152, 0xd0761a5b'34fd720c'cdea7b1a'0dc7ad42_u128},
+ {Sign::NEG, -152, 0xc9833ba2'bb0ed2a0'5ff854b6'6e7ded1f_u128},
+ {Sign::NEG, -152, 0xc2905ce9'd1f24872'5ce6604b'0911c5ed_u128},
+ {Sign::NEG, -152, 0xbb9d7e30'79a7d374'def75d88'16cffc59_u128},
+ {Sign::NEG, -152, 0xb4aa9f76'b22f739a'006e0982'bd8d96ef_u128},
+ {Sign::NEG, -152, 0xadb7c0bc'7b8928d3'db8d1eb5'0fa7375c_u128},
+ {Sign::NEG, -152, 0xa6c4e201'd5b4f314'8a9754fe'0c0073a7_u128},
+ {Sign::NEG, -152, 0x9fd20346'c0b2d24e'27cf61a1'9e032f69_u128},
+ {Sign::NEG, -152, 0x98df248b'3c82c672'cd77f748'9d9ef50b_u128},
+ {Sign::NEG, -152, 0x91ec45cf'4924cf74'95d3c600'cf484f03_u128},
+ {Sign::NEG, -152, 0x8af96712'e698ed45'9b257b3c'e3f82109_u128},
+ {Sign::NEG, -152, 0x84068856'14df1fd7'f7afc1d4'792b015a_u128},
+ {Sign::NEG, -153, 0xfa275331'a7eece3b'8b6a8408'31c123d8_u128},
+ {Sign::NEG, -153, 0xec4195b6'47c38612'3ef142da'7335b35a_u128},
+ {Sign::NEG, -153, 0xde5bd83a'093c6718'3e79062c'7cbb3b7d_u128},
+ {Sign::NEG, -153, 0xd0761abc'ec597131'be870ed4'ed5b755b_u128},
+ {Sign::NEG, -153, 0xc2905d3e'f11aa442'f3a09874'3d20fb64_u128},
+ {Sign::NEG, -153, 0xb4aa9fc0'17800030'124ad974'bd15fbca_u128},
+ {Sign::NEG, -153, 0xa6c4e240'5f8984dd'4f0b030a'9742eb00_u128},
+ {Sign::NEG, -153, 0x98df24bf'c937322e'de664133'cead362d_u128},
+ {Sign::NEG, -153, 0x8af9673e'54890808'f4e1bab8'3f55f5a1_u128},
+ {Sign::NEG, -154, 0xfa275378'02fe0c9f'8e052253'3c713e98_u128},
+ {Sign::NEG, -154, 0xde5bd871'a03259cf'129bc1c6'f293726e_u128},
+ {Sign::NEG, -154, 0xc2905d69'80aef768'e0918216'6eeb17eb_u128},
+ {Sign::NEG, -154, 0xa6c4e25f'a473e535'60f08720'313daa3f_u128},
+ {Sign::NEG, -154, 0x8af96754'0b8122fc'fcc2ea56'6b3af38b_u128},
+ {Sign::NEG, -155, 0xde5bd88d'6bad6110'3a25757e'00f4e3a0_u128},
+ {Sign::NEG, -155, 0xa6c4e26f'46e91b3e'55d3f9e7'0cf177b8_u128},
+ {Sign::NEG, -156, 0xde5bd89b'516ae82a'3d4aac85'125398d0_u128},
+ {Sign::NEG, -157, 0xde5bd8a2'4449ac95'9ab5a849'a06f400d_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -157, 0xde5bd8b0'2a073729'0d3cc88f'd4ef34c2_u128},
+ {Sign::POS, -156, 0xde5bd8b7'1ce5fd51'225916c2'b3f33c90_u128},
+ {Sign::POS, -155, 0xa6c4e28e'8bd3930a'17847f98'acf08d54_u128},
+ {Sign::POS, -155, 0xde5bd8c5'02a38b5e'04439783'0931fddd_u128},
+ {Sign::POS, -154, 0x8af9677f'79717409'c2ab3859'13176984_u128},
+ {Sign::POS, -154, 0xa6c4e29e'2e48d4cc'e454dec8'2bde52e5_u128},
+ {Sign::POS, -154, 0xc2905dbe'9fd7e82f'fe1522b0'470d7d7f_u128},
+ {Sign::POS, -154, 0xde5bd8e0'ce1eae6a'a6e2721f'2afc3cce_u128},
+ {Sign::POS, -154, 0xfa275404'b91d27b4'75b3458e'ec3c106c_u128},
+ {Sign::POS, -153, 0x8af96795'3069aa22'80bf0ff2'f6cd9f93_u128},
+ {Sign::POS, -153, 0x98df2528'e2a09a29'f09cc73b'7013b906_u128},
+ {Sign::POS, -153, 0xa6c4e2bd'7333640c'55ee1480'619827c4_u128},
+ {Sign::POS, -153, 0xb4aaa052'e22207e5'7c2e48d7'72250b3c_u128},
+ {Sign::POS, -153, 0xc2905de9'2f6c85d1'2ed8ba8c'6fa81c98_u128},
+ {Sign::POS, -153, 0xd0761b80'5b12ddeb'3968c521'4f33fc4f_u128},
+ {Sign::POS, -153, 0xde5bd918'6515104f'6759c94e'2d017fad_u128},
+ {Sign::POS, -153, 0xec4196b1'4d731d19'84272d01'4c70fe58_u128},
+ {Sign::POS, -153, 0xfa27544b'142d0465'5b4c5b5f'180b9fe1_u128},
+ {Sign::POS, -152, 0x840688f2'dca16327'5c226261'10c254a4_u128},
+ {Sign::POS, -152, 0x8af967c0'9e5a3178'b345ef5d'90dd6545_u128},
+ {Sign::POS, -152, 0x91ec468e'cf40ed34'98ce9208'7c5cb614_u128},
+ {Sign::POS, -152, 0x98df255d'6f559668'f27a0a60'56dcfe57_u128},
+ {Sign::POS, -152, 0x9fd2042c'7e982d23'a6061afe'b7929f24_u128},
+ {Sign::POS, -152, 0xa6c4e2fb'fd08b172'99308918'494a4a20_u128},
+ {Sign::POS, -152, 0xadb7c1cb'eaa72363'b1b71c7c'ca69a844_u128},
+ {Sign::POS, -152, 0xb4aaa09c'47738304'd5579f97'0cf000a9_u128},
+ {Sign::POS, -152, 0xbb9d7f6d'136dd063'e9cfdf6c'f676df42_u128},
+ {Sign::POS, -152, 0xc2905e3e'4e960b8e'd4ddab9f'8032bbab_u128},
+ {Sign::POS, -152, 0xc9833d0f'f8ec3493'7c3ed66a'b6f39fe9_u128},
+ {Sign::POS, -152, 0xd0761be2'12704b7f'c5b134a5'bb25cf2e_u128},
+ {Sign::POS, -152, 0xd768fab4'9b225061'96f29dc2'c0d26ca0_u128},
+ {Sign::POS, -152, 0xde5bd987'93024346'd5c0ebcf'0fa0221e_u128},
+ {Sign::POS, -152, 0xe54eb85a'fa10243d'67d9fb73'02d3c705_u128},
+ {Sign::POS, -152, 0xec41972e'd04bf353'32fbabf2'095106f1_u128},
+ {Sign::POS, -152, 0xf3347603'15b5b096'1ce3df2a'a59b0889_u128},
+ {Sign::POS, -152, 0xfa2754d7'ca4d5c14'0b507996'6dd5143e_u128},
+ {Sign::POS, -151, 0x808d19d6'77097aed'71ffb125'05e19d89_u128},
+ {Sign::POS, -151, 0x84068941'40833efc'4657417a'9e657eae_u128},
+ {Sign::POS, -151, 0x877ff8ac'4193fa3d'758de3f1'68f9f8c9_u128},
+ {Sign::POS, -151, 0x8af96817'7a3bacb7'f2828ffc'57f43581_u128},
+ {Sign::POS, -151, 0x8e72d782'ea7a5672'b0143e5b'e77b1053_u128},
+ {Sign::POS, -151, 0x91ec46ee'924ff774'a121e91e'1d8769ef_u128},
+ {Sign::POS, -151, 0x9565b65a'71bc8fc4'b88a8b9e'89e47b9c_u128},
+ {Sign::POS, -151, 0x98df25c6'88c01f69'e92d2286'46302a9c_u128},
+ {Sign::POS, -151, 0x9c589532'd75aa66b'25e8abcb'f5db5b8c_u128},
+ {Sign::POS, -151, 0x9fd2049f'5d8c24cf'619c26b3'c62a45c8_u128},
+ {Sign::POS, -151, 0xa34b740c'1b549a9d'8f2693cf'6e34c6cc_u128},
+ {Sign::POS, -151, 0xa6c4e379'10b407dc'a166f4fe'2ee6b59a_u128},
+ {Sign::POS, -151, 0xaa3e52e6'3daa6c93'8b3c4d6c'd3003616_u128},
+ {Sign::POS, -151, 0xadb7c253'a237c8c9'3f85a195'af160c71_u128},
+ {Sign::POS, -151, 0xb13131c1'3e5c1c84'b121f740'a191f084_u128},
+ {Sign::POS, -151, 0xb4aaa12f'121767cc'd2f05583'12b2e136_u128},
+ {Sign::POS, -151, 0xb824109d'1d69aaa8'97cfc4bf'f48d77de_u128},
+ {Sign::POS, -151, 0xbb9d800b'6052e51e'f29f4ea7'c30c3ba5_u128},
+ {Sign::POS, -151, 0xbf16ef79'dad31736'd63dfe38'83eff4e9_u128},
+ {Sign::POS, -151, 0xc2905ee8'8cea40f7'358adfbd'c6d0009f_u128},
+ {Sign::POS, -151, 0xc609ce57'76986267'036500d0'a51aa3b6_u128},
+ {Sign::POS, -151, 0xc9833dc6'97dd7b8d'32ab7057'c2155e78_u128},
+ {Sign::POS, -151, 0xccfcad35'f0b98c70'b63d3e87'4add3ff0_u128},
+ {Sign::POS, -151, 0xd0761ca5'812c9518'80f97ce0'f6673948_u128},
+ {Sign::POS, -151, 0xd3ef8c15'4936958b'85bf3e34'0580712d_u128},
+ {Sign::POS, -151, 0xd768fb85'48d78dd0'b76d969d'42ce9734_u128},
+ {Sign::POS, -151, 0xdae26af5'800f7def'08e39b87'02d0373a_u128},
+ {Sign::POS, -151, 0xde5bda65'eede65ed'6d0063a9'23dd0cc6_u128},
+ }};
+
+// > P = fpminimax(log10(1 + x)/x, 3, [|128...|], [-0x1.0002143p-29 , 0x1p-29]);
+// > P;
+// > dirtyinfnorm(log10(1 + x)/x - P, [-0x1.0002143p-29 , 0x1p-29]);
+// 0x1.64fb8...p-123
+LIBC_INLINE_VAR constexpr Float128 BIG_COEFFS[4]{
+ {Sign::NEG, -131, 0xde5bd8a9'373f89a7'6903c4ce'1582517d_u128},
+ {Sign::POS, -130, 0x943d3b1b'7a1af679'b8a21791'624e2e8a_u128},
+ {Sign::NEG, -130, 0xde5bd8a9'37287195'355baaaf'abc25990_u128},
+ {Sign::POS, -129, 0xde5bd8a9'37287195'355baaaf'ad33dbd9_u128},
+};
+
+// Reuse the output of the fast pass range reduction.
+// -2^-8 <= m_x < 2^-7
+LIBC_INLINE static double log10_accurate(int e_x, int index, double m_x) {
+
+ Float128 e_x_f128(static_cast<float>(e_x));
+ Float128 sum = fputil::quick_mul(LOG10_2, e_x_f128);
+ sum = fputil::quick_add(sum, LOG10_TABLE.step_1[index]);
+
+ Float128 v_f128 = log_range_reduction(m_x, LOG10_TABLE, sum);
+
+ // Polynomial approximation
+ Float128 p = fputil::quick_mul(v_f128, BIG_COEFFS[0]);
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[1]));
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[2]));
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[3]));
+
+ Float128 r = fputil::quick_add(sum, p);
+
+ return static_cast<double>(r);
+}
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace log10_internal
+
+LIBC_INLINE static double log10(double x) {
+ using namespace log10_internal;
+ using namespace common_constants_internal;
+ using FPBits_t = typename fputil::FPBits<double>;
+
+ FPBits_t xbits(x);
+ uint64_t x_u = xbits.uintval();
+
+ int x_e = -FPBits_t::EXP_BIAS;
+
+ if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
+ // log10(1.0) = +0.0
+ return 0.0;
+ }
+
+ if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
+ xbits.uintval() > FPBits_t::max_normal().uintval())) {
+ if (x == 0.0) {
+ // return -Inf and raise FE_DIVBYZERO.
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits_t::inf(Sign::NEG).get_val();
+ }
+ if (xbits.is_neg() && !xbits.is_nan()) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
+ }
+ if (xbits.is_inf_or_nan()) {
+ return x;
+ }
+ // Normalize denormal inputs.
+ xbits = FPBits_t(x * 0x1.0p52);
+ x_e -= 52;
+ x_u = xbits.uintval();
+ }
+
+ // log10(x) = log10(2^x_e * x_m)
+ // = x_e * log10(2) + log10(x_m)
+
+ // Range reduction for log10(x_m):
+ // For each x_m, we would like to find r such that:
+ // -2^-8 <= r * x_m - 1 < 2^-7
+ int shifted = static_cast<int>(x_u >> 45);
+ int index = shifted & 0x7F;
+ double r = RD[index];
+
+ // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
+ // all 1's.
+ x_e += static_cast<int>((x_u + (1ULL << 45)) >> 52);
+ double e_x = static_cast<double>(x_e);
+
+ // hi is exact
+ double hi = fputil::multiply_add(e_x, LOG_2_HI, LOG_R_DD[index].hi);
+ // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err
+ // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo))
+ double lo = fputil::multiply_add(e_x, LOG_2_LO, LOG_R_DD[index].lo);
+
+ // Set m = 1.mantissa.
+ uint64_t x_m = (x_u & 0x000F'FFFF'FFFF'FFFFULL) | 0x3FF0'0000'0000'0000ULL;
+ double m = FPBits_t(x_m).get_val();
+
+ fputil::DoubleDouble r1;
+
+ // Perform exact range reduction
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ double u = fputil::multiply_add(r, m, -1.0); // exact
+#else
+ uint64_t c_m = x_m & 0x3FFF'E000'0000'0000ULL;
+ double c = FPBits_t(c_m).get_val();
+ double u = fputil::multiply_add(r, m - c, CD[index]); // exact
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+
+ // Error of u_sq = ulp(u^2);
+ double u_sq = u * u;
+ // Degree-7 minimax polynomial
+ double p0 = fputil::multiply_add(u, LOG_COEFFS[1], LOG_COEFFS[0]);
+ double p1 = fputil::multiply_add(u, LOG_COEFFS[3], LOG_COEFFS[2]);
+ double p2 = fputil::multiply_add(u, LOG_COEFFS[5], LOG_COEFFS[4]);
+ double p = fputil::polyeval(u_sq, lo, p0, p1, p2);
+
+ // Exact sum:
+ // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
+ r1 = fputil::exact_add(hi, u);
+ r1.lo += p;
+
+ // Quick double-double multiplication:
+ // r2.hi + r2.lo ~ r1 * log10(e),
+ // with error bounded by:
+ // 4*ulp( ulp(r2.hi) )
+ fputil::DoubleDouble r2 = fputil::quick_mult(r1, LOG10_E);
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return r2.hi + r2.lo;
+#else
+ // Technicallly error of r1.lo is bounded by:
+ // |hi|*ulp(log(2)_lo) + C*ulp(u^2)
+ // To simplify the error computation a bit, we replace |hi|*ulp(log(2)_lo)
+ // with the upper bound: 2^11 * ulp(log(2)_lo) = 2^-85.
+ // Total error is bounded by ~ C * ulp(u^2) + 2^-85.
+ double err = fputil::multiply_add(u_sq, P_ERR, HI_ERR);
+
+ // Lower bound from the result
+ double left = r2.hi + (r2.lo - err);
+ // Upper bound from the result
+ double right = r2.hi + (r2.lo + err);
+
+ // Ziv's test if fast pass is accurate enough.
+ if (left == right)
+ return left;
+
+ // Exact cases:
+ if (LIBC_UNLIKELY((x_u & 0x3FFFFF) == 0)) {
+ switch (x_u) {
+ case 0x4024000000000000: // x = 10.0
+ return 1.0;
+ case 0x4059000000000000: // x = 10^2
+ return 2.0;
+ case 0x408f400000000000: // x = 10^3
+ return 3.0;
+ case 0x40c3880000000000: // x = 10^4
+ return 4.0;
+ case 0x40f86a0000000000: // x = 10^5
+ return 5.0;
+ case 0x412e848000000000: // x = 10^6
+ return 6.0;
+ case 0x416312d000000000: // x = 10^7
+ return 7.0;
+ case 0x4197d78400000000: // x = 10^8
+ return 8.0;
+ case 0x41cdcd6500000000: // x = 10^9
+ return 9.0;
+ case 0x4202a05f20000000: // x = 10^10
+ return 10.0;
+ case 0x42374876e8000000: // x = 10^11
+ return 11.0;
+ case 0x426d1a94a2000000: // x = 10^12
+ return 12.0;
+ case 0x42a2309ce5400000: // x = 10^13
+ return 13.0;
+ }
+ } else {
+ switch (x_u) {
+ case 0x42d6bcc41e900000: // x = 10^14
+ return 14.0;
+ case 0x430c6bf526340000: // x = 10^15
+ return 15.0;
+ case 0x4341c37937e08000: // x = 10^16
+ return 16.0;
+ case 0x4376345785d8a000: // x = 10^17
+ return 17.0;
+ case 0x43abc16d674ec800: // x = 10^18
+ return 18.0;
+ case 0x43e158e460913d00: // x = 10^19
+ return 19.0;
+ case 0x4415af1d78b58c40: // x = 10^20
+ return 20.0;
+ case 0x444b1ae4d6e2ef50: // x = 10^21
+ return 21.0;
+ case 0x4480f0cf064dd592: // x = 10^22
+ return 22.0;
+ }
+ }
+
+ return log10_accurate(x_e, index, u);
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG10_H
diff --git a/libc/src/__support/math/log1p.h b/libc/src/__support/math/log1p.h
new file mode 100644
index 0000000..9950161
--- /dev/null
+++ b/libc/src/__support/math/log1p.h
@@ -0,0 +1,1070 @@
+//===-- Double-precision log1p(x) function --------------------------------===//
+//
+// 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_LOG1P_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG1P_H
+
+#include "common_constants.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/integer_literals.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+namespace log1p_internal {
+// 128-bit precision dyadic floating point numbers.
+using Float128 = typename fputil::DyadicFloat<128>;
+
+using LIBC_NAMESPACE::operator""_u128;
+
+using namespace common_constants_internal;
+
+// R1[i] = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7) )
+LIBC_INLINE_VAR constexpr double R1[129] = {
+ 0x1p0, 0x1.fcp-1, 0x1.f8p-1, 0x1.f4p-1, 0x1.fp-1, 0x1.ecp-1, 0x1.eap-1,
+ 0x1.e6p-1, 0x1.e2p-1, 0x1.dep-1, 0x1.dap-1, 0x1.d8p-1, 0x1.d4p-1, 0x1.dp-1,
+ 0x1.cep-1, 0x1.cap-1, 0x1.c8p-1, 0x1.c4p-1, 0x1.cp-1, 0x1.bep-1, 0x1.bap-1,
+ 0x1.b8p-1, 0x1.b4p-1, 0x1.b2p-1, 0x1.bp-1, 0x1.acp-1, 0x1.aap-1, 0x1.a6p-1,
+ 0x1.a4p-1, 0x1.a2p-1, 0x1.9ep-1, 0x1.9cp-1, 0x1.9ap-1, 0x1.98p-1, 0x1.94p-1,
+ 0x1.92p-1, 0x1.9p-1, 0x1.8ep-1, 0x1.8ap-1, 0x1.88p-1, 0x1.86p-1, 0x1.84p-1,
+ 0x1.82p-1, 0x1.8p-1, 0x1.7ep-1, 0x1.7ap-1, 0x1.78p-1, 0x1.76p-1, 0x1.74p-1,
+ 0x1.72p-1, 0x1.7p-1, 0x1.6ep-1, 0x1.6cp-1, 0x1.6ap-1, 0x1.68p-1, 0x1.66p-1,
+ 0x1.64p-1, 0x1.62p-1, 0x1.6p-1, 0x1.5ep-1, 0x1.5cp-1, 0x1.5ap-1, 0x1.58p-1,
+ 0x1.58p-1, 0x1.56p-1, 0x1.54p-1, 0x1.52p-1, 0x1.5p-1, 0x1.4ep-1, 0x1.4cp-1,
+ 0x1.4ap-1, 0x1.4ap-1, 0x1.48p-1, 0x1.46p-1, 0x1.44p-1, 0x1.42p-1, 0x1.42p-1,
+ 0x1.4p-1, 0x1.3ep-1, 0x1.3cp-1, 0x1.3cp-1, 0x1.3ap-1, 0x1.38p-1, 0x1.36p-1,
+ 0x1.36p-1, 0x1.34p-1, 0x1.32p-1, 0x1.3p-1, 0x1.3p-1, 0x1.2ep-1, 0x1.2cp-1,
+ 0x1.2cp-1, 0x1.2ap-1, 0x1.28p-1, 0x1.28p-1, 0x1.26p-1, 0x1.24p-1, 0x1.24p-1,
+ 0x1.22p-1, 0x1.2p-1, 0x1.2p-1, 0x1.1ep-1, 0x1.1cp-1, 0x1.1cp-1, 0x1.1ap-1,
+ 0x1.1ap-1, 0x1.18p-1, 0x1.16p-1, 0x1.16p-1, 0x1.14p-1, 0x1.14p-1, 0x1.12p-1,
+ 0x1.12p-1, 0x1.1p-1, 0x1.0ep-1, 0x1.0ep-1, 0x1.0cp-1, 0x1.0cp-1, 0x1.0ap-1,
+ 0x1.0ap-1, 0x1.08p-1, 0x1.08p-1, 0x1.06p-1, 0x1.06p-1, 0x1.04p-1, 0x1.04p-1,
+ 0x1.02p-1, 0x1.02p-1, 0x1p-1,
+};
+
+// Extra constants for exact range reduction when FMA instructions are not
+// available:
+// r * c - 1 for r = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7))
+// and c = 1 + i * 2^-7
+// with i = 0..128.
+[[maybe_unused]] LIBC_INLINE_VAR constexpr double RCM1[129] = {
+ 0.0, -0x1p-14, -0x1p-12, -0x1.2p-11, -0x1p-10, -0x1.9p-10,
+ 0x1.fp-10, 0x1.28p-10, 0x1p-12, -0x1.9p-11, -0x1.fp-10, 0x1.2p-10,
+ -0x1p-12, -0x1.cp-10, 0x1.1p-10, -0x1.5p-11, 0x1p-9, 0x1p-14,
+ -0x1p-9, 0x1.ap-12, -0x1.ep-10, 0x1.8p-12, -0x1.1p-9, -0x1p-15,
+ 0x1p-9, -0x1.ap-11, 0x1.1p-10, -0x1.f8p-10, -0x1p-12, 0x1.68p-10,
+ -0x1.fp-10, -0x1.cp-12, 0x1p-10, 0x1.3p-9, -0x1.6p-10, -0x1.4p-13,
+ 0x1p-10, 0x1.0cp-9, -0x1.08p-9, -0x1.2p-10, -0x1p-12, 0x1.2p-11,
+ 0x1.5p-10, 0x1p-9, 0x1.5p-9, -0x1.1cp-9, -0x1.cp-10, -0x1.58p-10,
+ -0x1p-10, -0x1.7p-11, -0x1p-11, -0x1.6p-12, -0x1p-12, -0x1.cp-13,
+ -0x1p-12, -0x1.6p-12, -0x1p-11, -0x1.7p-11, -0x1p-10, -0x1.58p-10,
+ -0x1.cp-10, -0x1.1cp-9, -0x1.6p-9, 0x1.5p-9, 0x1p-9, 0x1.5p-10,
+ 0x1.2p-11, -0x1p-12, -0x1.2p-10, -0x1.08p-9, -0x1.88p-9, 0x1.0cp-9,
+ 0x1p-10, -0x1.4p-13, -0x1.6p-10, -0x1.54p-9, 0x1.3p-9, 0x1p-10,
+ -0x1.cp-12, -0x1.fp-10, 0x1.8p-9, 0x1.68p-10, -0x1p-12, -0x1.f8p-10,
+ 0x1.7p-9, 0x1.1p-10, -0x1.ap-11, -0x1.6p-9, 0x1p-9, -0x1p-15,
+ -0x1.1p-9, 0x1.48p-9, 0x1.8p-12, -0x1.ep-10, 0x1.6p-9, 0x1.ap-12,
+ -0x1p-9, 0x1.48p-9, 0x1p-14, -0x1.4p-9, 0x1p-9, -0x1.5p-11,
+ -0x1.bp-9, 0x1.1p-10, -0x1.cp-10, 0x1.54p-9, -0x1p-12, -0x1.9cp-9,
+ 0x1.2p-10, -0x1.fp-10, 0x1.3p-9, -0x1.9p-11, 0x1.cp-9, 0x1p-12,
+ -0x1.88p-9, 0x1.28p-10, -0x1.2p-9, 0x1.fp-10, -0x1.9p-10, 0x1.4cp-9,
+ -0x1p-10, 0x1.9p-9, -0x1.2p-11, 0x1.c4p-9, -0x1p-12, 0x1.e8p-9,
+ -0x1p-14, 0x1.fcp-9, 0.0,
+};
+
+// Generated by Sollya with:
+// for i from 0 to 128 do {
+// r = 2^-8 * nearestint( 2^8 / (1 + i*2^-7) );
+// b = nearestint(log(r)*2^43) * 2^-43;
+// c = round(log(r) - b, D, RN);
+// print("{", -c, ",", -b, "},");
+// };
+// We replace LOG_R1_DD[128] with log(1.0) == 0.0
+alignas(16) LIBC_INLINE_VAR constexpr fputil::DoubleDouble LOG_R1_DD[129] = {
+ {0.0, 0.0},
+ {-0x1.0c76b999d2be8p-46, 0x1.010157589p-7},
+ {-0x1.3dc5b06e2f7d2p-45, 0x1.0205658938p-6},
+ {-0x1.aa0ba325a0c34p-45, 0x1.8492528c9p-6},
+ {0x1.111c05cf1d753p-47, 0x1.0415d89e74p-5},
+ {-0x1.c167375bdfd28p-45, 0x1.466aed42ep-5},
+ {-0x1.29efbec19afa2p-47, 0x1.67c94f2d4cp-5},
+ {0x1.0fc1a353bb42ep-45, 0x1.aaef2d0fbp-5},
+ {-0x1.e113e4fc93b7bp-47, 0x1.eea31c006cp-5},
+ {-0x1.5325d560d9e9bp-45, 0x1.1973bd1466p-4},
+ {0x1.cc85ea5db4ed7p-45, 0x1.3bdf5a7d1ep-4},
+ {-0x1.53a2582f4e1efp-48, 0x1.4d3115d208p-4},
+ {0x1.c1e8da99ded32p-49, 0x1.700d30aeacp-4},
+ {0x1.3115c3abd47dap-45, 0x1.9335e5d594p-4},
+ {-0x1.e42b6b94407c8p-47, 0x1.a4e7640b1cp-4},
+ {0x1.646d1c65aacd3p-45, 0x1.c885801bc4p-4},
+ {0x1.a89401fa71733p-46, 0x1.da72763844p-4},
+ {-0x1.534d64fa10afdp-45, 0x1.fe89139dbep-4},
+ {0x1.1ef78ce2d07f2p-45, 0x1.1178e8227ep-3},
+ {0x1.ca78e44389934p-45, 0x1.1aa2b7e23fp-3},
+ {0x1.39d6ccb81b4a1p-47, 0x1.2d1610c868p-3},
+ {0x1.62fa8234b7289p-51, 0x1.365fcb0159p-3},
+ {0x1.5837954fdb678p-45, 0x1.4913d8333bp-3},
+ {0x1.633e8e5697dc7p-45, 0x1.527e5e4a1bp-3},
+ {-0x1.27023eb68981cp-46, 0x1.5bf406b544p-3},
+ {-0x1.5118de59c21e1p-45, 0x1.6f0128b757p-3},
+ {-0x1.c661070914305p-46, 0x1.7898d85445p-3},
+ {-0x1.73d54aae92cd1p-47, 0x1.8beafeb39p-3},
+ {0x1.7f22858a0ff6fp-47, 0x1.95a5adcf7p-3},
+ {0x1.9904d6865817ap-45, 0x1.9f6c407089p-3},
+ {-0x1.c358d4eace1aap-47, 0x1.b31d8575bdp-3},
+ {-0x1.d4bc4595412b6p-45, 0x1.bd087383bep-3},
+ {-0x1.1ec72c5962bd2p-48, 0x1.c6ffbc6f01p-3},
+ {-0x1.84a7e75b6f6e4p-47, 0x1.d1037f2656p-3},
+ {0x1.212276041f43p-51, 0x1.e530effe71p-3},
+ {-0x1.a211565bb8e11p-51, 0x1.ef5ade4ddp-3},
+ {0x1.bcbecca0cdf3p-46, 0x1.f991c6cb3bp-3},
+ {-0x1.6f08c1485e94ap-46, 0x1.01eae5626c8p-2},
+ {0x1.7188b163ceae9p-45, 0x1.0c42d67616p-2},
+ {-0x1.c210e63a5f01cp-45, 0x1.1178e8227e8p-2},
+ {0x1.b9acdf7a51681p-45, 0x1.16b5ccbacf8p-2},
+ {0x1.ca6ed5147bdb7p-45, 0x1.1bf99635a68p-2},
+ {0x1.a87deba46baeap-47, 0x1.214456d0eb8p-2},
+ {0x1.c93c1df5bb3b6p-45, 0x1.269621134d8p-2},
+ {0x1.a9cfa4a5004f4p-45, 0x1.2bef07cdc9p-2},
+ {0x1.16ecdb0f177c8p-46, 0x1.36b6776be1p-2},
+ {0x1.83b54b606bd5cp-46, 0x1.3c25277333p-2},
+ {0x1.8e436ec90e09dp-47, 0x1.419b423d5e8p-2},
+ {-0x1.f27ce0967d675p-45, 0x1.4718dc271c8p-2},
+ {-0x1.e20891b0ad8a4p-45, 0x1.4c9e09e173p-2},
+ {0x1.ebe708164c759p-45, 0x1.522ae0738ap-2},
+ {0x1.fadedee5d40efp-46, 0x1.57bf753c8dp-2},
+ {-0x1.a0b2a08a465dcp-47, 0x1.5d5bddf596p-2},
+ {-0x1.db623e731aep-45, 0x1.630030b3abp-2},
+ {0x1.0a0d32756ebap-45, 0x1.68ac83e9c68p-2},
+ {0x1.721657c222d87p-46, 0x1.6e60ee6af18p-2},
+ {0x1.d8b0949dc60b3p-45, 0x1.741d876c678p-2},
+ {0x1.9ec7d2efd1778p-45, 0x1.79e26687cf8p-2},
+ {-0x1.72090c812566ap-45, 0x1.7fafa3bd818p-2},
+ {0x1.fd56f3333778ap-45, 0x1.85855776dc8p-2},
+ {-0x1.05ae1e5e7047p-45, 0x1.8b639a88b3p-2},
+ {-0x1.766b52ee6307dp-46, 0x1.914a8635bf8p-2},
+ {-0x1.52313a502d9fp-46, 0x1.973a3431358p-2},
+ {-0x1.52313a502d9fp-46, 0x1.973a3431358p-2},
+ {-0x1.6279e10d0c0bp-45, 0x1.9d32bea15fp-2},
+ {0x1.3c6457f9d79f5p-45, 0x1.a33440224f8p-2},
+ {0x1.e36f2bea77a5dp-46, 0x1.a93ed3c8ad8p-2},
+ {-0x1.17cc552774458p-45, 0x1.af5295248dp-2},
+ {0x1.095252d841995p-46, 0x1.b56fa044628p-2},
+ {0x1.7d85bf40a666dp-45, 0x1.bb9611b80ep-2},
+ {0x1.cec807fe8e18p-45, 0x1.c1c60693fap-2},
+ {0x1.cec807fe8e18p-45, 0x1.c1c60693fap-2},
+ {-0x1.9b6ddc15249aep-45, 0x1.c7ff9c74558p-2},
+ {-0x1.797c33ec7a6bp-47, 0x1.ce42f180648p-2},
+ {0x1.35bafe9a767a8p-45, 0x1.d490246def8p-2},
+ {-0x1.ea42d60dc616ap-46, 0x1.dae75484c98p-2},
+ {-0x1.ea42d60dc616ap-46, 0x1.dae75484c98p-2},
+ {-0x1.326b207322938p-46, 0x1.e148a1a2728p-2},
+ {-0x1.465505372bd08p-45, 0x1.e7b42c3ddbp-2},
+ {0x1.f27f45a470251p-45, 0x1.ee2a156b41p-2},
+ {0x1.f27f45a470251p-45, 0x1.ee2a156b41p-2},
+ {0x1.2cde56f014a8bp-46, 0x1.f4aa7ee0318p-2},
+ {0x1.085fa3c164935p-47, 0x1.fb358af7a48p-2},
+ {-0x1.53ba3b1727b1cp-47, 0x1.00e5ae5b208p-1},
+ {-0x1.53ba3b1727b1cp-47, 0x1.00e5ae5b208p-1},
+ {-0x1.4c45fe79539ep-47, 0x1.04360be7604p-1},
+ {0x1.6812241edf5fdp-45, 0x1.078bf0533c4p-1},
+ {0x1.f486b887e7e27p-46, 0x1.0ae76e2d054p-1},
+ {0x1.f486b887e7e27p-46, 0x1.0ae76e2d054p-1},
+ {0x1.c299807801742p-46, 0x1.0e4898611ccp-1},
+ {-0x1.58647bb9ddcb2p-45, 0x1.11af823c75cp-1},
+ {-0x1.58647bb9ddcb2p-45, 0x1.11af823c75cp-1},
+ {-0x1.edd97a293ae49p-45, 0x1.151c3f6f298p-1},
+ {0x1.4cc4ef8ab465p-46, 0x1.188ee40f23cp-1},
+ {0x1.4cc4ef8ab465p-46, 0x1.188ee40f23cp-1},
+ {0x1.cacdeed70e667p-51, 0x1.1c07849ae6p-1},
+ {-0x1.a7242c9fe81d3p-45, 0x1.1f8635fc618p-1},
+ {-0x1.a7242c9fe81d3p-45, 0x1.1f8635fc618p-1},
+ {0x1.2fc066e48667bp-46, 0x1.230b0d8bebcp-1},
+ {-0x1.b61f10522625p-47, 0x1.269621134dcp-1},
+ {-0x1.b61f10522625p-47, 0x1.269621134dcp-1},
+ {0x1.06d2be797882dp-45, 0x1.2a2786d0ecp-1},
+ {-0x1.7a6e507b9dc11p-46, 0x1.2dbf557b0ep-1},
+ {-0x1.7a6e507b9dc11p-46, 0x1.2dbf557b0ep-1},
+ {-0x1.74e93c5a0ed9cp-45, 0x1.315da443408p-1},
+ {-0x1.74e93c5a0ed9cp-45, 0x1.315da443408p-1},
+ {0x1.0b83f9527e6acp-46, 0x1.35028ad9d8cp-1},
+ {-0x1.18b7abb5569a4p-45, 0x1.38ae2171978p-1},
+ {-0x1.18b7abb5569a4p-45, 0x1.38ae2171978p-1},
+ {-0x1.2b7367cfe13c2p-47, 0x1.3c6080c36cp-1},
+ {-0x1.2b7367cfe13c2p-47, 0x1.3c6080c36cp-1},
+ {-0x1.6ce7930f0c74cp-45, 0x1.4019c2125ccp-1},
+ {-0x1.6ce7930f0c74cp-45, 0x1.4019c2125ccp-1},
+ {-0x1.d984f481051f7p-48, 0x1.43d9ff2f924p-1},
+ {-0x1.2cb6af94d60aap-45, 0x1.47a1527e8a4p-1},
+ {-0x1.2cb6af94d60aap-45, 0x1.47a1527e8a4p-1},
+ {0x1.f7115ed4c541cp-49, 0x1.4b6fd6f970cp-1},
+ {0x1.f7115ed4c541cp-49, 0x1.4b6fd6f970cp-1},
+ {-0x1.e6c516d93b8fbp-45, 0x1.4f45a835a5p-1},
+ {-0x1.e6c516d93b8fbp-45, 0x1.4f45a835a5p-1},
+ {0x1.5ccc45d257531p-47, 0x1.5322e268678p-1},
+ {0x1.5ccc45d257531p-47, 0x1.5322e268678p-1},
+ {0x1.9980bff3303ddp-47, 0x1.5707a26bb8cp-1},
+ {0x1.9980bff3303ddp-47, 0x1.5707a26bb8cp-1},
+ {0x1.dfa63ac10c9fbp-45, 0x1.5af405c3648p-1},
+ {0x1.dfa63ac10c9fbp-45, 0x1.5af405c3648p-1},
+ {0x1.202380cda46bep-45, 0x1.5ee82aa2418p-1},
+ {0x1.202380cda46bep-45, 0x1.5ee82aa2418p-1},
+ {0.0, 0.0},
+};
+
+// Degree-7 minimax polynomial log(1 + v) ~ v - v^2 / 2 + ...
+// generated by Sollya with:
+// > P = fpminimax(log(1 + x)/x, 6, [|1, 1, D...|],
+// [-0x1.69000000000edp-8, 0x1.7f00000000081p-8]);
+LIBC_INLINE_VAR constexpr double P_COEFFS[6] = {-0x1p-1,
+ 0x1.5555555555166p-2,
+ -0x1.fffffffdb7746p-3,
+ 0x1.99999a8718a6p-3,
+ -0x1.555874ce8ce22p-3,
+ 0x1.24335555ddbe5p-3};
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+// Extra errors from P is from using x^2 to reduce evaluation latency and
+// directional rounding.
+LIBC_INLINE_VAR constexpr double P_ERR = 0x1.0p-49;
+
+// log(2) with 128-bit precision generated by SageMath with:
+// def format_hex(value):
+// l = hex(value)[2:]
+// n = 8
+// x = [l[i:i + n] for i in range(0, len(l), n)]
+// return "0x" + "'".join(x) + "_u128"
+// (s, m, e) = RealField(128)(2).log().sign_mantissa_exponent();
+// print(format_hex(m));
+LIBC_INLINE_VAR constexpr Float128
+ LOG_2(Sign::POS,
+ /*exponent=*/-128, /*mantissa=*/
+ 0xb17217f7'd1cf79ab'c9e3b398'03f2f6af_u128);
+
+// -log(r1) with 128-bit precision generated by SageMath with:
+//
+// for i in range(129):
+// r = 2^-8 * round( 2^8 / (1 + i*2^(-7)) );
+// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
+// print("{Sign::POS,", e, ", format_hex(m), "},");
+LIBC_INLINE_VAR constexpr Float128 LOG_R1[129] = {
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -134, 0x8080abac'46f38946'662d417c'ed007a46_u128},
+ {Sign::POS, -133, 0x8102b2c4'9ac23a4f'91d082dc'e3ddcd38_u128},
+ {Sign::POS, -133, 0xc2492946'4655f45c'da5f3cc0'b3251dbd_u128},
+ {Sign::POS, -132, 0x820aec4f'3a222380'b9e3aea6'c444ef07_u128},
+ {Sign::POS, -132, 0xa33576a1'6f1f4c64'521016bd'904dc968_u128},
+ {Sign::POS, -132, 0xb3e4a796'a5dac208'27cca0bc'c06c2f92_u128},
+ {Sign::POS, -132, 0xd5779687'd887e0d1'a9dda170'56e45ed5_u128},
+ {Sign::POS, -132, 0xf7518e00'35c3dd83'606d8909'3278a939_u128},
+ {Sign::POS, -131, 0x8cb9de8a'32ab368a'a7c98595'30a45153_u128},
+ {Sign::POS, -131, 0x9defad3e'8f73217a'976d3b5b'45f6ca0b_u128},
+ {Sign::POS, -131, 0xa6988ae9'03f562ed'3e858f08'597b3a69_u128},
+ {Sign::POS, -131, 0xb8069857'560707a3'6a677b4c'8bec22e1_u128},
+ {Sign::POS, -131, 0xc99af2ea'ca4c4570'eaf51f66'692844ba_u128},
+ {Sign::POS, -131, 0xd273b205'8de1bd49'46bbf837'b4d320c6_u128},
+ {Sign::POS, -131, 0xe442c00d'e2591b47'196ab34c'e0bccd12_u128},
+ {Sign::POS, -131, 0xed393b1c'22351280'3f4e2e66'0317d55f_u128},
+ {Sign::POS, -131, 0xff4489ce'deab2ca6'c17bd40d'8d9291ec_u128},
+ {Sign::POS, -130, 0x88bc7411'3f23def1'9c5a0fe3'96f40f1e_u128},
+ {Sign::POS, -130, 0x8d515bf1'1fb94f1c'88713268'840cbcc0_u128},
+ {Sign::POS, -130, 0x968b0864'3409ceb6'65c0da50'6a088484_u128},
+ {Sign::POS, -130, 0x9b2fe580'ac80b17d'411a5b94'4aca8708_u128},
+ {Sign::POS, -130, 0xa489ec19'9dab06f2'a9fb6cf0'ecb411b7_u128},
+ {Sign::POS, -130, 0xa93f2f25'0dac67d1'cad2fb8d'48054ae0_u128},
+ {Sign::POS, -130, 0xadfa035a'a1ed8fdc'149767e4'10316d2c_u128},
+ {Sign::POS, -130, 0xb780945b'ab55dce4'34c7bc3d'32750fde_u128},
+ {Sign::POS, -130, 0xbc4c6c2a'226399ef'8f6ebcfb'2016a439_u128},
+ {Sign::POS, -130, 0xc5f57f59'c7f46155'aa8b6997'a402bf30_u128},
+ {Sign::POS, -130, 0xcad2d6e7'b80bf914'2c507fb7'a3d0bf6a_u128},
+ {Sign::POS, -130, 0xcfb62038'44b3209a'd0cb02f3'3f79c16c_u128},
+ {Sign::POS, -130, 0xd98ec2ba'de71e539'58a98f2a'd65bee9b_u128},
+ {Sign::POS, -130, 0xde8439c1'dec56877'4d57da94'5b5d0aaa_u128},
+ {Sign::POS, -130, 0xe37fde37'807b84e3'4e9a750b'6b68781d_u128},
+ {Sign::POS, -130, 0xe881bf93'2af3dac0'c524848e'3443e040_u128},
+ {Sign::POS, -130, 0xf29877ff'38809091'3b020fa1'820c9492_u128},
+ {Sign::POS, -130, 0xf7ad6f26'e7ff2ef7'54d2238f'75f969b1_u128},
+ {Sign::POS, -130, 0xfcc8e365'9d9bcbec'ca0cdf30'1431b60f_u128},
+ {Sign::POS, -129, 0x80f572b1'363487b9'f5bd0b5b'3479d5f4_u128},
+ {Sign::POS, -129, 0x86216b3b'0b17188b'163ceae8'8f720f1e_u128},
+ {Sign::POS, -129, 0x88bc7411'3f23def1'9c5a0fe3'96f40f1e_u128},
+ {Sign::POS, -129, 0x8b5ae65d'67db9acd'f7a51681'26a58b9a_u128},
+ {Sign::POS, -129, 0x8dfccb1a'd35ca6ed'5147bdb6'ddcaf59c_u128},
+ {Sign::POS, -129, 0x90a22b68'75c6a1f7'ae91aeba'609c8877_u128},
+ {Sign::POS, -129, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
+ {Sign::POS, -129, 0x95f783e6'e49a9cfa'4a5004f3'ef063313_u128},
+ {Sign::POS, -129, 0x9b5b3bb5'f088b766'd878bbe3'd392be25_u128},
+ {Sign::POS, -129, 0x9e1293b9'998c1daa'5b035eae'273a855f_u128},
+ {Sign::POS, -129, 0xa0cda11e'af46390d'bb243827'3918db7e_u128},
+ {Sign::POS, -129, 0xa38c6e13'8e20d831'f698298a'dddd7f32_u128},
+ {Sign::POS, -129, 0xa64f04f0'b961df76'e4f5275c'2d15c21f_u128},
+ {Sign::POS, -129, 0xa9157039'c51ebe70'8164c759'686a2209_u128},
+ {Sign::POS, -129, 0xabdfba9e'468fd6f6'f72ea077'49ce6bd3_u128},
+ {Sign::POS, -129, 0xaeadeefa'caf97d35'7dd6e688'ebb13b03_u128},
+ {Sign::POS, -129, 0xb1801859'd56249dc'18ce51ff'f99479cd_u128},
+ {Sign::POS, -129, 0xb45641f4'e350a0d3'2756eba0'0bc33978_u128},
+ {Sign::POS, -129, 0xb7307735'78cb90b2'be1116c3'466beb6d_u128},
+ {Sign::POS, -129, 0xba0ec3b6'33dd8b09'49dc60b2'b059a60b_u128},
+ {Sign::POS, -129, 0xbcf13343'e7d9ec7d'2efd1778'1bb3afec_u128},
+ {Sign::POS, -129, 0xbfd7d1de'c0a8df6f'37eda996'244bccb0_u128},
+ {Sign::POS, -129, 0xc2c2abbb'6e5fd56f'33337789'd592e296_u128},
+ {Sign::POS, -129, 0xc5b1cd44'596fa51e'1a18fb8f'9f9ef280_u128},
+ {Sign::POS, -129, 0xc8a5431a'dfb44ca5'688ce7c1'a75e341a_u128},
+ {Sign::POS, -129, 0xcb9d1a18'9ab56e76'2d7e9307'c70c0668_u128},
+ {Sign::POS, -129, 0xcb9d1a18'9ab56e76'2d7e9307'c70c0668_u128},
+ {Sign::POS, -129, 0xce995f50'af69d861'ef2f3f4f'861ad6a9_u128},
+ {Sign::POS, -129, 0xd19a2011'27d3c645'7f9d79f5'1dcc7301_u128},
+ {Sign::POS, -129, 0xd49f69e4'56cf1b79'5f53bd2e'406e66e7_u128},
+ {Sign::POS, -129, 0xd7a94a92'466e833a'ad88bba7'd0cee8e0_u128},
+ {Sign::POS, -129, 0xdab7d022'31484a92'96c20cca'6efe2ac5_u128},
+ {Sign::POS, -129, 0xddcb08dc'0717d85b'f40a666c'87842843_u128},
+ {Sign::POS, -129, 0xe0e30349'fd1cec80'7fe8e180'2aba24d6_u128},
+ {Sign::POS, -129, 0xe0e30349'fd1cec80'7fe8e180'2aba24d6_u128},
+ {Sign::POS, -129, 0xe3ffce3a'2aa64922'3eadb651'b49ac53a_u128},
+ {Sign::POS, -129, 0xe72178c0'323a1a0f'304e1653'e71d9973_u128},
+ {Sign::POS, -129, 0xea481236'f7d35baf'e9a767a8'0d6d97e8_u128},
+ {Sign::POS, -129, 0xed73aa42'64b0ade9'4f91cf4b'33e42998_u128},
+ {Sign::POS, -129, 0xed73aa42'64b0ade9'4f91cf4b'33e42998_u128},
+ {Sign::POS, -129, 0xf0a450d1'39366ca6'fc66eb64'08ff6433_u128},
+ {Sign::POS, -129, 0xf3da161e'ed6b9aaf'ac8d42f7'8d3e65d3_u128},
+ {Sign::POS, -129, 0xf7150ab5'a09f27f4'5a470250'd40ebe90_u128},
+ {Sign::POS, -129, 0xf7150ab5'a09f27f4'5a470250'd40ebe90_u128},
+ {Sign::POS, -129, 0xfa553f70'18c966f2'b780a545'a1b54dcf_u128},
+ {Sign::POS, -129, 0xfd9ac57b'd244217e'8f05924d'258c14c5_u128},
+ {Sign::POS, -128, 0x8072d72d'903d588b'89d1b09c'70c4010a_u128},
+ {Sign::POS, -128, 0x8072d72d'903d588b'89d1b09c'70c4010a_u128},
+ {Sign::POS, -128, 0x821b05f3'b01d6774'030d58c3'f7e2ea1f_u128},
+ {Sign::POS, -128, 0x83c5f829'9e2b4091'20f6fafe'8fbb68b9_u128},
+ {Sign::POS, -128, 0x8573b716'82a7d21a'e21f9f89'c1ab80b2_u128},
+ {Sign::POS, -128, 0x8573b716'82a7d21a'e21f9f89'c1ab80b2_u128},
+ {Sign::POS, -128, 0x87244c30'8e670a66'01e005d0'6dbfa8f8_u128},
+ {Sign::POS, -128, 0x88d7c11e'3ad53cdc'223111a7'07b6de2c_u128},
+ {Sign::POS, -128, 0x88d7c11e'3ad53cdc'223111a7'07b6de2c_u128},
+ {Sign::POS, -128, 0x8a8e1fb7'94b09134'2eb628db'a173c82d_u128},
+ {Sign::POS, -128, 0x8c477207'91e53313'be2ad194'15fe25a5_u128},
+ {Sign::POS, -128, 0x8c477207'91e53313'be2ad194'15fe25a5_u128},
+ {Sign::POS, -128, 0x8e03c24d'73003959'bddae1cc'ce247838_u128},
+ {Sign::POS, -128, 0x8fc31afe'30b2c6de'9b00bf16'7e95da67_u128},
+ {Sign::POS, -128, 0x8fc31afe'30b2c6de'9b00bf16'7e95da67_u128},
+ {Sign::POS, -128, 0x918586c5'f5e4bf01'9b92199e'd1a4bab1_u128},
+ {Sign::POS, -128, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
+ {Sign::POS, -128, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
+ {Sign::POS, -128, 0x9513c368'76083695'f3cbc416'a2418012_u128},
+ {Sign::POS, -128, 0x96dfaabd'86fa1646'be1188fb'c94e2f15_u128},
+ {Sign::POS, -128, 0x96dfaabd'86fa1646'be1188fb'c94e2f15_u128},
+ {Sign::POS, -128, 0x98aed221'a03458b6'1d2f8932'1647b358_u128},
+ {Sign::POS, -128, 0x98aed221'a03458b6'1d2f8932'1647b358_u128},
+ {Sign::POS, -128, 0x9a81456c'ec642e0f'e549f9aa'ea3cb5e1_u128},
+ {Sign::POS, -128, 0x9c5710b8'cbb73a42'a2554b2d'd4619e63_u128},
+ {Sign::POS, -128, 0x9c5710b8'cbb73a42'a2554b2d'd4619e63_u128},
+ {Sign::POS, -128, 0x9e304061'b5fda919'30603d87'b6df81ad_u128},
+ {Sign::POS, -128, 0x9e304061'b5fda919'30603d87'b6df81ad_u128},
+ {Sign::POS, -128, 0xa00ce109'2e5498c3'67879c5a'30cd1242_u128},
+ {Sign::POS, -128, 0xa00ce109'2e5498c3'67879c5a'30cd1242_u128},
+ {Sign::POS, -128, 0xa1ecff97'c91e267b'0b7efae0'8e597e16_u128},
+ {Sign::POS, -128, 0xa3d0a93f'45169a4a'83594fab'088c0d65_u128},
+ {Sign::POS, -128, 0xa3d0a93f'45169a4a'83594fab'088c0d65_u128},
+ {Sign::POS, -128, 0xa5b7eb7c'b860fb88'af6a62a0'dec6e073_u128},
+ {Sign::POS, -128, 0xa5b7eb7c'b860fb88'af6a62a0'dec6e073_u128},
+ {Sign::POS, -128, 0xa7a2d41a'd270c9d7'49362382'a768847a_u128},
+ {Sign::POS, -128, 0xa7a2d41a'd270c9d7'49362382'a768847a_u128},
+ {Sign::POS, -128, 0xa9917134'33c2b998'8ba4aea6'14d05701_u128},
+ {Sign::POS, -128, 0xa9917134'33c2b998'8ba4aea6'14d05701_u128},
+ {Sign::POS, -128, 0xab83d135'dc633301'7fe6607b'a902ef3c_u128},
+ {Sign::POS, -128, 0xab83d135'dc633301'7fe6607b'a902ef3c_u128},
+ {Sign::POS, -128, 0xad7a02e1'b24efd31'd60864fd'949b4bd3_u128},
+ {Sign::POS, -128, 0xad7a02e1'b24efd31'd60864fd'949b4bd3_u128},
+ {Sign::POS, -128, 0xaf741551'20c9011c'066d235e'e63073dd_u128},
+ {Sign::POS, -128, 0xaf741551'20c9011c'066d235e'e63073dd_u128},
+ {Sign::POS, 0, 0_u128},
+};
+
+// Logarithm range reduction - Step 2:
+// s(k) = 2^-18 round( 2^18 / (1 + k*2^-14) ) - 1 for k = -91 .. 96
+// Output range:
+// [-0x1.1037c00000040271p-15 , 0x1.108480000008096cp-15]
+LIBC_INLINE_VAR constexpr double S2[198] = {
+ 0x1.6ep-8, 0x1.6ap-8, 0x1.66p-8, 0x1.62p-8, 0x1.5dcp-8,
+ 0x1.59cp-8, 0x1.55cp-8, 0x1.51cp-8, 0x1.4dcp-8, 0x1.49cp-8,
+ 0x1.458p-8, 0x1.418p-8, 0x1.3d8p-8, 0x1.398p-8, 0x1.358p-8,
+ 0x1.318p-8, 0x1.2d8p-8, 0x1.294p-8, 0x1.254p-8, 0x1.214p-8,
+ 0x1.1d4p-8, 0x1.194p-8, 0x1.154p-8, 0x1.114p-8, 0x1.0dp-8,
+ 0x1.09p-8, 0x1.05p-8, 0x1.01p-8, 0x1.fap-9, 0x1.f2p-9,
+ 0x1.eap-9, 0x1.e2p-9, 0x1.d98p-9, 0x1.d18p-9, 0x1.c98p-9,
+ 0x1.c18p-9, 0x1.b98p-9, 0x1.b18p-9, 0x1.a98p-9, 0x1.a18p-9,
+ 0x1.998p-9, 0x1.91p-9, 0x1.89p-9, 0x1.81p-9, 0x1.79p-9,
+ 0x1.71p-9, 0x1.69p-9, 0x1.61p-9, 0x1.59p-9, 0x1.51p-9,
+ 0x1.49p-9, 0x1.41p-9, 0x1.388p-9, 0x1.308p-9, 0x1.288p-9,
+ 0x1.208p-9, 0x1.188p-9, 0x1.108p-9, 0x1.088p-9, 0x1.008p-9,
+ 0x1.f1p-10, 0x1.e1p-10, 0x1.d1p-10, 0x1.c1p-10, 0x1.b1p-10,
+ 0x1.a1p-10, 0x1.91p-10, 0x1.81p-10, 0x1.71p-10, 0x1.6p-10,
+ 0x1.5p-10, 0x1.4p-10, 0x1.3p-10, 0x1.2p-10, 0x1.1p-10,
+ 0x1p-10, 0x1.ep-11, 0x1.cp-11, 0x1.ap-11, 0x1.8p-11,
+ 0x1.6p-11, 0x1.4p-11, 0x1.2p-11, 0x1p-11, 0x1.cp-12,
+ 0x1.8p-12, 0x1.4p-12, 0x1p-12, 0x1.8p-13, 0x1p-13,
+ 0x1p-14, 0.0, -0x1p-14, -0x1p-13, -0x1.8p-13,
+ -0x1p-12, -0x1.4p-12, -0x1.8p-12, -0x1.cp-12, -0x1p-11,
+ -0x1.2p-11, -0x1.4p-11, -0x1.6p-11, -0x1.8p-11, -0x1.ap-11,
+ -0x1.cp-11, -0x1.ep-11, -0x1p-10, -0x1.1p-10, -0x1.2p-10,
+ -0x1.3p-10, -0x1.4p-10, -0x1.5p-10, -0x1.6p-10, -0x1.6fp-10,
+ -0x1.7fp-10, -0x1.8fp-10, -0x1.9fp-10, -0x1.afp-10, -0x1.bfp-10,
+ -0x1.cfp-10, -0x1.dfp-10, -0x1.efp-10, -0x1.ffp-10, -0x1.078p-9,
+ -0x1.0f8p-9, -0x1.178p-9, -0x1.1f8p-9, -0x1.278p-9, -0x1.2f8p-9,
+ -0x1.378p-9, -0x1.3fp-9, -0x1.47p-9, -0x1.4fp-9, -0x1.57p-9,
+ -0x1.5fp-9, -0x1.67p-9, -0x1.6fp-9, -0x1.77p-9, -0x1.7fp-9,
+ -0x1.87p-9, -0x1.8fp-9, -0x1.968p-9, -0x1.9e8p-9, -0x1.a68p-9,
+ -0x1.ae8p-9, -0x1.b68p-9, -0x1.be8p-9, -0x1.c68p-9, -0x1.ce8p-9,
+ -0x1.d68p-9, -0x1.dep-9, -0x1.e6p-9, -0x1.eep-9, -0x1.f6p-9,
+ -0x1.fep-9, -0x1.03p-8, -0x1.07p-8, -0x1.0bp-8, -0x1.0fp-8,
+ -0x1.12cp-8, -0x1.16cp-8, -0x1.1acp-8, -0x1.1ecp-8, -0x1.22cp-8,
+ -0x1.26cp-8, -0x1.2acp-8, -0x1.2e8p-8, -0x1.328p-8, -0x1.368p-8,
+ -0x1.3a8p-8, -0x1.3e8p-8, -0x1.428p-8, -0x1.464p-8, -0x1.4a4p-8,
+ -0x1.4e4p-8, -0x1.524p-8, -0x1.564p-8, -0x1.5a4p-8, -0x1.5ep-8,
+ -0x1.62p-8, -0x1.66p-8, -0x1.6ap-8, -0x1.6ep-8, -0x1.72p-8,
+ -0x1.75cp-8, -0x1.79cp-8, -0x1.7dcp-8,
+};
+
+// -log(r) for the second step, generated by SageMath with:
+//
+// for i in range(-91, 97):
+// r = 2^-18 * round( 2^18 / (1 + i*2^(-14)) );
+// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
+// print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",
+// format_hex(m), "},");
+LIBC_INLINE_VAR constexpr Float128 LOG_R2[198] = {
+ {Sign::NEG, -135, 0xb67dab2a'1a5742a4'a0e061c5'f7431c5e_u128},
+ {Sign::NEG, -135, 0xb4807f24'af682939'5d5bfe7b'969ed6ec_u128},
+ {Sign::NEG, -135, 0xb2834b35'b4d54d5f'4d08702d'dfabc23f_u128},
+ {Sign::NEG, -135, 0xb0860f5c'eba9be95'd4d36650'8b9953df_u128},
+ {Sign::NEG, -135, 0xae68f71a'a09e8847'ac18a289'f8f214a9_u128},
+ {Sign::NEG, -135, 0xac6baaee'd676e8f1'd5b42054'abb88c45_u128},
+ {Sign::NEG, -135, 0xaa6e56d8'7cd632d6'09809d58'ee484964_u128},
+ {Sign::NEG, -135, 0xa870fad7'54bb8791'b9e6fc7c'72f06d73_u128},
+ {Sign::NEG, -135, 0xa67396eb'1f231892'6f78d6d0'105c00e2_u128},
+ {Sign::NEG, -135, 0xa4762b13'9d0626e7'028f7126'29209148_u128},
+ {Sign::NEG, -135, 0xa258dfd1'0aedaa67'c98d898e'f172df02_u128},
+ {Sign::NEG, -135, 0xa05b63a3'73e60a83'fcc37c3c'3062bfa1_u128},
+ {Sign::NEG, -135, 0x9e5ddf89'cf42f501'3eb450db'05763c36_u128},
+ {Sign::NEG, -135, 0x9c605383'ddf1b88c'7146a86f'd458b775_u128},
+ {Sign::NEG, -135, 0x9a62bf91'60dcb286'c20a0c92'81474436_u128},
+ {Sign::NEG, -135, 0x986523b2'18eb4ed6'cdc57316'ec4aebc3_u128},
+ {Sign::NEG, -135, 0x96677fe5'c70207b9'c060dad7'4cef4273_u128},
+ {Sign::NEG, -135, 0x9449f92d'2ff44633'ed8def1a'3e433499_u128},
+ {Sign::NEG, -135, 0x924c4507'3220b5e0'3ce7a1f8'5c27b4fc_u128},
+ {Sign::NEG, -135, 0x904e88f3'68fea63f'f2ca8934'49f7f2cb_u128},
+ {Sign::NEG, -135, 0x8e50c4f1'956699ed'8d77d9fa'bd2853cf_u128},
+ {Sign::NEG, -135, 0x8c52f901'782e20ec'93e828d7'5b58ded4_u128},
+ {Sign::NEG, -135, 0x8a552522'd227d87a'9f9605b0'53c5acf0_u128},
+ {Sign::NEG, -135, 0x88574955'64236ae0'62a14939'3bca7241_u128},
+ {Sign::NEG, -135, 0x86398719'b66bac7c'aea6b56c'e89203d4_u128},
+ {Sign::NEG, -135, 0x843b9aef'044e4dcc'0242bd86'd00609b2_u128},
+ {Sign::NEG, -135, 0x823da6d4'c89c6927'daabf927'74bac84e_u128},
+ {Sign::NEG, -135, 0x803faaca'c419abf2'a1c6f3fc'242ef8d0_u128},
+ {Sign::NEG, -136, 0xfc834da1'6f0d9f57'a225ebc0'2e6d9dd4_u128},
+ {Sign::NEG, -136, 0xf88735cc'c7433381'c33f6ad3'40ae18a9_u128},
+ {Sign::NEG, -136, 0xf48b0e17'1249b6bc'70b2a4d3'8a242244_u128},
+ {Sign::NEG, -136, 0xf08ed67f'd190e280'1d548190'48b811b0_u128},
+ {Sign::NEG, -136, 0xec52ca07'ed95f236'9c21b650'afe9ede0_u128},
+ {Sign::NEG, -136, 0xe85671ad'ecd28aac'935519c9'6d30e463_u128},
+ {Sign::NEG, -136, 0xe45a0970'dc912ca7'ba88f6f2'e2672cfe_u128},
+ {Sign::NEG, -136, 0xe05d9150'3e298bc8'0b1a8b84'657ae069_u128},
+ {Sign::NEG, -136, 0xdc61094b'92ed70ef'ea3bff8d'197b20a1_u128},
+ {Sign::NEG, -136, 0xd8647162'5c28b9e5'cdbb931d'6fecc249_u128},
+ {Sign::NEG, -136, 0xd467c994'1b2158f5'd971d560'd5f00820_u128},
+ {Sign::NEG, -136, 0xd06b11e0'51175493'75563561'244c090b_u128},
+ {Sign::NEG, -136, 0xcc6e4a46'7f44c6fa'dc393c9a'3f3b380f_u128},
+ {Sign::NEG, -136, 0xc831a4c6'f6fa709d'e6abe6e9'e4ee2096_u128},
+ {Sign::NEG, -136, 0xc434bc61'24a0f16e'3ce3c822'8583a66e_u128},
+ {Sign::NEG, -136, 0xc037c413'c61bfd93'b96a79f5'c5a4963a_u128},
+ {Sign::NEG, -136, 0xbc3abbde'5c8d9bde'aaef2733'7008679f_u128},
+ {Sign::NEG, -136, 0xb83da3c0'6911e509'a49a3fca'ddc8bc5a_u128},
+ {Sign::NEG, -136, 0xb4407bb9'6cbf035a'e0254feb'785362fa_u128},
+ {Sign::NEG, -136, 0xb04343c8'e8a53245'9893a4e2'5ab9dc95_u128},
+ {Sign::NEG, -136, 0xac45fbee'5dcebe0b'5d8b0f40'a3708915_u128},
+ {Sign::NEG, -136, 0xa848a429'4d40035d'5f4c11c2'c7a58c69_u128},
+ {Sign::NEG, -136, 0xa44b3c79'37f76efd'b348cc5d'f706ffba_u128},
+ {Sign::NEG, -136, 0xa04dc4dd'9eed7d60'9159f2c5'5a18befd_u128},
+ {Sign::NEG, -136, 0x9c106456'3058bef3'bdfdee41'fe6a5a02_u128},
+ {Sign::NEG, -136, 0x9812cbe3'46475a24'4580ddf8'9853254d_u128},
+ {Sign::NEG, -136, 0x94152383'53489ffb'ac75e10d'61fc3ee8_u128},
+ {Sign::NEG, -136, 0x90176b35'd83ce8e2'cad9b30b'29736155_u128},
+ {Sign::NEG, -136, 0x8c19a2fa'55fe9b14'6f881deb'98fc45f3_u128},
+ {Sign::NEG, -136, 0x881bcad0'4d622a3e'70a04b63'b7248c96_u128},
+ {Sign::NEG, -136, 0x841de2b7'3f361722'b4823fb4'8035eddd_u128},
+ {Sign::NEG, -136, 0x801feaae'ac42ef38'3364ccb5'b13cd47f_u128},
+ {Sign::NEG, -137, 0xf843c56c'2a969897'e306977b'049f0ad5_u128},
+ {Sign::NEG, -137, 0xf0479599'f617a843'e3c4d9e9'619bc045_u128},
+ {Sign::NEG, -137, 0xe84b45e5'bc76702c'4356d525'b5e6432d_u128},
+ {Sign::NEG, -137, 0xe04ed64e'7f14697a'7839dcd7'989339ab_u128},
+ {Sign::NEG, -137, 0xd85246d3'3f47230b'4e21f045'ecb76f23_u128},
+ {Sign::NEG, -137, 0xd0559772'fe5840b0'902e248d'd4ba9b28_u128},
+ {Sign::NEG, -137, 0xc858c82c'bd857a72'a4444906'7ef92e01_u128},
+ {Sign::NEG, -137, 0xc05bd8ff'7e009bd2'17926207'cc22e4e6_u128},
+ {Sign::NEG, -137, 0xb85ec9ea'40ef8309'1c349622'f3fa5d82_u128},
+ {Sign::NEG, -137, 0xafe1c6ec'e1a058dd'97fa2fd0'c9dc723e_u128},
+ {Sign::NEG, -137, 0xa7e47606'048b1a65'983e8089'7cf1e60f_u128},
+ {Sign::NEG, -137, 0x9fe70534'1d236102'7199cd06'ae5d39b3_u128},
+ {Sign::NEG, -137, 0x97e97476'2c5e8f58'43cd18a7'2a051a96_u128},
+ {Sign::NEG, -137, 0x8febc3cb'332616ff'7b6d1248'c3e1fd40_u128},
+ {Sign::NEG, -137, 0x87edf332'325777c5'f5572a88'14c703af_u128},
+ {Sign::NEG, -138, 0xffe00554'55887de0'26828c92'649a3a39_u128},
+ {Sign::NEG, -138, 0xefe3e464'3a640cf3'82c550bd'1216d82a_u128},
+ {Sign::NEG, -138, 0xdfe78392'14b4e8ae'da6959f7'f0e01bf0_u128},
+ {Sign::NEG, -138, 0xcfeae2db'e5d6736d'da93e2fa'85a8f214_u128},
+ {Sign::NEG, -138, 0xbfee023f'af0c2480'b47505bf'a5a03b06_u128},
+ {Sign::NEG, -138, 0xaff0e1bb'718186ad'b1475a51'80a43520_u128},
+ {Sign::NEG, -138, 0x9ff3814d'2e4a36b2'a8740b91'c95df537_u128},
+ {Sign::NEG, -138, 0x8ff5e0f2'e661e1c6'57d895d3'5921b59c_u128},
+ {Sign::NEG, -139, 0xfff00155'35588833'3c56c598'c659c2a3_u128},
+ {Sign::NEG, -139, 0xdff3c0e4'97ea4eb1'2ef8ec33'ed9d782a_u128},
+ {Sign::NEG, -139, 0xbff7008f'f5e0c257'379eba7e'6465ff63_u128},
+ {Sign::NEG, -139, 0x9ff9c053'5073a370'3f972b78'3fcab757_u128},
+ {Sign::NEG, -140, 0xfff80055'51558885'de026e27'1ee0549d_u128},
+ {Sign::NEG, -140, 0xbffb8023'febc0c25'eceb47ea'01f6c632_u128},
+ {Sign::NEG, -141, 0xfffc0015'54d55888'7333c578'57e1ed52_u128},
+ {Sign::NEG, -142, 0xfffe0005'55455588'87dde026'fa704374_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -141, 0x80010002'aab2aac4'44999abe'2fe2cc65_u128},
+ {Sign::POS, -140, 0x8002000a'aaeaac44'4eef3815'81464ccb_u128},
+ {Sign::POS, -140, 0xc0048024'01440c26'dfeb4850'85f6f454_u128},
+ {Sign::POS, -139, 0x8004002a'acaac445'99abe3be'3a1c6e93_u128},
+ {Sign::POS, -139, 0xa0064053'5a37a37a'6bc1e20e'ac8448b4_u128},
+ {Sign::POS, -139, 0xc0090090'0a20c275'979eedc0'64c242fd_u128},
+ {Sign::POS, -139, 0xe00c40e4'bd6e4efd'c72446cc'1bf728bd_u128},
+ {Sign::POS, -138, 0x800800aa'baac446e'f381b821'bbb569e5_u128},
+ {Sign::POS, -138, 0x900a20f3'19a3e273'569b26aa'a485ea5c_u128},
+ {Sign::POS, -138, 0xa00c814d'7c6a37f8'2dcf56c8'3c80b028_u128},
+ {Sign::POS, -138, 0xb00f21bb'e3e388ee'5f697682'84463b9b_u128},
+ {Sign::POS, -138, 0xc0120240'510c284c'b48ea6c0'5e2773a1_u128},
+ {Sign::POS, -138, 0xd01522dc'c4f87991'14d9d761'96d8043a_u128},
+ {Sign::POS, -138, 0xe0188393'40d4f241'e016a611'a4415d72_u128},
+ {Sign::POS, -138, 0xf01c2465'c5e61b6f'661e135f'49a47c40_u128},
+ {Sign::POS, -137, 0x801002ab'2ac4499a'be6bf0fa'435e8383_u128},
+ {Sign::POS, -137, 0x88121333'7898871e'9a31ba0c'bc030353_u128},
+ {Sign::POS, -137, 0x901443cc'cd362c9f'54b57dfe'0c4c840f_u128},
+ {Sign::POS, -137, 0x98169478'296fad41'7ad1e9c3'15328f7e_u128},
+ {Sign::POS, -137, 0xa0190536'8e2389b3'1f3f686c'f3d6be22_u128},
+ {Sign::POS, -137, 0xa81b9608'fc3c50ec'f105b66e'c4703ede_u128},
+ {Sign::POS, -137, 0xb01e46f0'74b0a0f3'610848c6'8df4d233_u128},
+ {Sign::POS, -137, 0xb7a0e9ed'7613acb0'2e0efddf'33a20464_u128},
+ {Sign::POS, -137, 0xbfa3d900'8e042ffb'c2cdb3c7'50f127b4_u128},
+ {Sign::POS, -137, 0xc7a6e82b'a36a7073'bd953378'6d3f4c49_u128},
+ {Sign::POS, -137, 0xcfaa176f'b76c8eb1'82e237c9'a4d450e3_u128},
+ {Sign::POS, -137, 0xd7ad66cd'cb3cbe14'c00b46a4'd0e3dfd0_u128},
+ {Sign::POS, -137, 0xdfb0d646'e0194584'ea999c0d'f8546710_u128},
+ {Sign::POS, -137, 0xe7b465db'f74c8032'cec6c2a9'ad974f4f_u128},
+ {Sign::POS, -137, 0xefb8158e'122cde5a'2d2045da'1570a07c_u128},
+ {Sign::POS, -137, 0xf7bbe55e'321ce603'6752e9b2'381e3edc_u128},
+ {Sign::POS, -137, 0xffbfd54d'588b33c5'3c1ed527'28e00e40_u128},
+ {Sign::POS, -136, 0x83e1f2ae'43793dc3'493b0d87'3fb9a340_u128},
+ {Sign::POS, -136, 0x87e40ac6'5f6cc4a0'29e38750'c9d26893_u128},
+ {Sign::POS, -136, 0x8be632ef'80e9a0df'aab9e832'7258ac3f_u128},
+ {Sign::POS, -136, 0x8fe86b2a'28bf51b3'28bc403d'8a5f3c63_u128},
+ {Sign::POS, -136, 0x93eab376'd7c36377'f720c1c9'7227fcdc_u128},
+ {Sign::POS, -136, 0x97ed0bd6'0ed17018'6ad9a3e3'd11b66c1_u128},
+ {Sign::POS, -136, 0x9bef7448'4ecb1f6c'edb27b79'c90b4019_u128},
+ {Sign::POS, -136, 0x9fb1c4cd'27012e19'a092a0d7'ab21722a_u128},
+ {Sign::POS, -136, 0xa3b44c65'b71c2d85'535d52f0'939a4d02_u128},
+ {Sign::POS, -136, 0xa7b6e412'cadcb3dc'90a57e11'edc1864e_u128},
+ {Sign::POS, -136, 0xabb98bd4'e33c4381'68e9c901'60031159_u128},
+ {Sign::POS, -136, 0xafbc43ac'813a6ea3'bf60594f'929adeb8_u128},
+ {Sign::POS, -136, 0xb3bf0b9a'25dcd7a2'8a421588'86775205_u128},
+ {Sign::POS, -136, 0xb7c1e39e'522f316d'1ab45417'663dee9e_u128},
+ {Sign::POS, -136, 0xbbc4cbb9'87433fe4'6c51ae3c'e1aea68a_u128},
+ {Sign::POS, -136, 0xbfc7c3ec'4630d83c'7c52ae8b'40ebabb7_u128},
+ {Sign::POS, -136, 0xc3cacc37'1015e15d'a857126f'7cfaaa67_u128},
+ {Sign::POS, -136, 0xc7cde49a'66165446'14d05662'cd29464a_u128},
+ {Sign::POS, -136, 0xcb90da16'44d29bb7'8379db06'ef3cd6bb_u128},
+ {Sign::POS, -136, 0xcf9411aa'99ddb7de'9025f4c6'7dd38bb6_u128},
+ {Sign::POS, -136, 0xd3975958'f681086d'd6f8a61c'892032ee_u128},
+ {Sign::POS, -136, 0xd79ab121'dbf8714c'9a2f20b4'e2332d47_u128},
+ {Sign::POS, -136, 0xdb9e1905'cb85ea59'3c767d61'f51d375b_u128},
+ {Sign::POS, -136, 0xdfa19105'46717fca'd4b2bd65'bb25493c_u128},
+ {Sign::POS, -136, 0xe3a51920'ce095292'c96c1254'a30ef91f_u128},
+ {Sign::POS, -136, 0xe7a8b158'e3a198be'73e324ce'0946b214_u128},
+ {Sign::POS, -136, 0xebac59ae'08949dd8'cacd125a'12bac62c_u128},
+ {Sign::POS, -136, 0xef6fd620'b2b7a503'cafdc272'27b71eaa_u128},
+ {Sign::POS, -136, 0xf3739daf'959aaafc'688d4282'f6026aa3_u128},
+ {Sign::POS, -136, 0xf777755d'03f4e0b6'e54e9e38'04464cdd_u128},
+ {Sign::POS, -136, 0xfb7b5d29'7f388a12'cb78b383'f4b59dce_u128},
+ {Sign::POS, -136, 0xff7f5515'88de024f'ee055fc5'15062c04_u128},
+ {Sign::POS, -135, 0x81c1ae90'd131de38'207812b4'3382acdd_u128},
+ {Sign::POS, -135, 0x83c3baa7'26a721cc'dc90c4c4'b61f3a87_u128},
+ {Sign::POS, -135, 0x85c5cece'05941dbc'1a03f13f'b2c978b1_u128},
+ {Sign::POS, -135, 0x87c7eb05'aec1304f'b36f282e'83a7dc36_u128},
+ {Sign::POS, -135, 0x89a9eccd'56a980c0'd82a4661'6d4c393f_u128},
+ {Sign::POS, -135, 0x8bac18a6'40185360'bc6ff847'13c9babd_u128},
+ {Sign::POS, -135, 0x8dae4c90'b22574f4'9f7942a5'16fc2d8a_u128},
+ {Sign::POS, -135, 0x8fb0888c'eda546ab'15e50cfd'9b29b427_u128},
+ {Sign::POS, -135, 0x91b2cc9b'336f3718'9f465296'ae7dd49a_u128},
+ {Sign::POS, -135, 0x93b518bb'c45dc268'b49c1eb9'b348e6e4_u128},
+ {Sign::POS, -135, 0x95b76cee'e14e728e'daa320cd'64c9d9c7_u128},
+ {Sign::POS, -135, 0x9799a333'de49b963'75a91950'ffe1e3b5_u128},
+ {Sign::POS, -135, 0x999c070b'a32068cd'5c6abcbf'43f03f14_u128},
+ {Sign::POS, -135, 0x9b9e72f6'b295ad4f'5a9e7f26'5d1ed157_u128},
+ {Sign::POS, -135, 0x9da0e6f5'4d9318fd'efeb98d0'2a195c17_u128},
+ {Sign::POS, -135, 0x9fa36307'b5054ca8'2aa503a3'110ab5a7_u128},
+ {Sign::POS, -135, 0xa1a5e72e'29dbf808'd0fe7e05'869eb825_u128},
+ {Sign::POS, -135, 0xa3884a68'a750cb10'e80a28f4'e1e500d2_u128},
+ {Sign::POS, -135, 0xa58ade36'aeef9f0b'53106415'1ca6e30b_u128},
+ {Sign::POS, -135, 0xa78d7a19'82c4b08f'27c01ffa'8e2e3c4b_u128},
+ {Sign::POS, -135, 0xa9901e11'63cbbbf5'7ba9408d'c857d568_u128},
+ {Sign::POS, -135, 0xab92ca1e'93038d76'104d1e33'31d3b4fa_u128},
+ {Sign::POS, -135, 0xad957e41'516e0158'9343c846'fcdf9137_u128},
+ {Sign::POS, -135, 0xaf780e79'b2514889'3977e89a'ec59bfa2_u128},
+ {Sign::POS, -135, 0xb17ad246'ef3713bc'913d4e3d'c55c3e6e_u128},
+ {Sign::POS, -135, 0xb37d9e2a'7a56b09d'777b52a9'e70d8bcc_u128},
+ {Sign::POS, -135, 0xb5807224'94be0c91'55de916f'd30591de_u128},
+ {Sign::POS, -135, 0xb7834e35'7f7e2600'e79cfb37'be2861e4_u128},
+ {Sign::POS, -135, 0xb986325d'7bab0c89'90983104'd3805389_u128},
+ {Sign::POS, -135, 0xbb68ef9c'254aa378'59e3b2ec'71ce64f4_u128},
+ {Sign::POS, -135, 0xbd6be371'8c77636f'e83183bf'3dd612ef_u128},
+ {Sign::POS, -135, 0xbf6edf5e'c44d9d35'c4e3b0ac'2fd52b7f_u128},
+};
+
+// Logarithm range reduction - Step 3:
+// s(k) = 2^-21 round( 2^21 / (1 + k*2^-21) ) - 1 for k = -69 .. 69
+// Output range:
+// [-0x1.012bb800000800114p-22, 0x1p-22 ]
+LIBC_INLINE_VAR constexpr double S3[139] = {
+ 0x1.14p-15, 0x1.1p-15, 0x1.0cp-15, 0x1.08p-15, 0x1.04p-15, 0x1p-15,
+ 0x1.f8p-16, 0x1.fp-16, 0x1.e8p-16, 0x1.ep-16, 0x1.d8p-16, 0x1.dp-16,
+ 0x1.c8p-16, 0x1.cp-16, 0x1.b8p-16, 0x1.bp-16, 0x1.a8p-16, 0x1.ap-16,
+ 0x1.98p-16, 0x1.9p-16, 0x1.88p-16, 0x1.8p-16, 0x1.78p-16, 0x1.7p-16,
+ 0x1.68p-16, 0x1.6p-16, 0x1.58p-16, 0x1.5p-16, 0x1.48p-16, 0x1.4p-16,
+ 0x1.38p-16, 0x1.3p-16, 0x1.28p-16, 0x1.2p-16, 0x1.18p-16, 0x1.1p-16,
+ 0x1.08p-16, 0x1p-16, 0x1.fp-17, 0x1.ep-17, 0x1.dp-17, 0x1.cp-17,
+ 0x1.bp-17, 0x1.ap-17, 0x1.9p-17, 0x1.8p-17, 0x1.7p-17, 0x1.6p-17,
+ 0x1.5p-17, 0x1.4p-17, 0x1.3p-17, 0x1.2p-17, 0x1.1p-17, 0x1p-17,
+ 0x1.ep-18, 0x1.cp-18, 0x1.ap-18, 0x1.8p-18, 0x1.6p-18, 0x1.4p-18,
+ 0x1.2p-18, 0x1p-18, 0x1.cp-19, 0x1.8p-19, 0x1.4p-19, 0x1p-19,
+ 0x1.8p-20, 0x1p-20, 0x1p-21, 0.0, -0x1p-21, -0x1p-20,
+ -0x1.8p-20, -0x1p-19, -0x1.4p-19, -0x1.8p-19, -0x1.cp-19, -0x1p-18,
+ -0x1.2p-18, -0x1.4p-18, -0x1.6p-18, -0x1.8p-18, -0x1.ap-18, -0x1.cp-18,
+ -0x1.ep-18, -0x1p-17, -0x1.1p-17, -0x1.2p-17, -0x1.3p-17, -0x1.4p-17,
+ -0x1.5p-17, -0x1.6p-17, -0x1.7p-17, -0x1.8p-17, -0x1.9p-17, -0x1.ap-17,
+ -0x1.bp-17, -0x1.cp-17, -0x1.dp-17, -0x1.ep-17, -0x1.fp-17, -0x1p-16,
+ -0x1.08p-16, -0x1.1p-16, -0x1.18p-16, -0x1.2p-16, -0x1.28p-16, -0x1.3p-16,
+ -0x1.38p-16, -0x1.4p-16, -0x1.48p-16, -0x1.5p-16, -0x1.58p-16, -0x1.6p-16,
+ -0x1.68p-16, -0x1.7p-16, -0x1.78p-16, -0x1.8p-16, -0x1.88p-16, -0x1.9p-16,
+ -0x1.98p-16, -0x1.ap-16, -0x1.a8p-16, -0x1.bp-16, -0x1.b8p-16, -0x1.cp-16,
+ -0x1.c8p-16, -0x1.dp-16, -0x1.d8p-16, -0x1.ep-16, -0x1.e8p-16, -0x1.fp-16,
+ -0x1.f8p-16, -0x1p-15, -0x1.04p-15, -0x1.08p-15, -0x1.0cp-15, -0x1.1p-15,
+ -0x1.14p-15,
+};
+
+// -log(r) for the third step, generated by SageMath with:
+//
+// for i in range(-69, 70):
+// r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
+// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
+// print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",
+// format_hex(m), "},");
+LIBC_INLINE_VAR constexpr Float128 LOG_R3[139] = {
+ {Sign::NEG, -142, 0x89ff6b38'd5de2622'e39d3faf'42340ed7_u128},
+ {Sign::NEG, -142, 0x87ff6f80'ccb40f16'7ff33266'82c02485_u128},
+ {Sign::NEG, -142, 0x85ff73b8'c3cdf731'5caf4fbe'343cf928_u128},
+ {Sign::NEG, -142, 0x83ff77e0'bb2ade79'cdb6e554'348f7fe8_u128},
+ {Sign::NEG, -142, 0x81ff7bf8'b2c9c4f6'0ef009c2'457de25d_u128},
+ {Sign::NEG, -143, 0xffff0001'55535558'8883333c'57b57c74_u128},
+ {Sign::NEG, -143, 0xfbff07f1'45931f44'f32668f3'9c70d183_u128},
+ {Sign::NEG, -143, 0xf7ff0fc1'3650e7bd'459a73c6'a6486fe3_u128},
+ {Sign::NEG, -143, 0xf3ff1771'278aaecd'37b18cca'7dd3a29f_u128},
+ {Sign::NEG, -143, 0xefff1f01'193e7480'513f610d'21bcfc78_u128},
+ {Sign::NEG, -143, 0xebff2671'0b6a38e1'ea190b95'c0690b7b_u128},
+ {Sign::NEG, -143, 0xe7ff2dc0'fe0bfbfd'2a150f64'f0ad1743_u128},
+ {Sign::NEG, -143, 0xe3ff34f0'f121bddd'090b5174'e995e9d1_u128},
+ {Sign::NEG, -143, 0xdfff3c00'e4a97e8c'4ed512b9'b93ea2bf_u128},
+ {Sign::NEG, -143, 0xdbff42f0'd8a13e15'934cea21'7ab794a2_u128},
+ {Sign::NEG, -143, 0xd7ff49c0'cd06fc83'3e4ebe94'8afd2c76_u128},
+ {Sign::NEG, -143, 0xd3ff5070'c1d8b9df'87b7c0f5'bcfee2e1_u128},
+ {Sign::NEG, -143, 0xcfff5700'b7147634'77666622'8cb6371b_u128},
+ {Sign::NEG, -143, 0xcbff5d70'acb8318b'e53a60f3'514db358_u128},
+ {Sign::NEG, -143, 0xc7ff63c0'a2c1ebef'79149c3b'6e57fa86_u128},
+ {Sign::NEG, -143, 0xc3ff69f0'992fa568'aad734c9'8416df2a_u128},
+ {Sign::NEG, -143, 0xbfff7000'8fff5e00'c2657367'9ed28334_u128},
+ {Sign::NEG, -143, 0xbbff75f0'872f15c0'd7a3c6db'6540809f_u128},
+ {Sign::NEG, -143, 0xb7ff7bc0'7ebcccb1'd277bde6'45fb1aad_u128},
+ {Sign::NEG, -143, 0xb3ff8170'76a682dc'6ac80145'a4087793_u128},
+ {Sign::NEG, -143, 0xafff8700'6eea3849'287c4db3'0271e265_u128},
+ {Sign::NEG, -143, 0xabff8c70'6785ed00'637d6de4'2eeb151e_u128},
+ {Sign::NEG, -143, 0xa7ff91c0'6077a10a'43b5348b'6b898a8c_u128},
+ {Sign::NEG, -143, 0xa3ff96f0'59bd546e'c10e7657'978bd7f6_u128},
+ {Sign::NEG, -143, 0x9fff9c00'53550735'a37503f4'57310e59_u128},
+ {Sign::NEG, -143, 0x9bffa0f0'4d3cb966'82d5a40a'3aa022ff_u128},
+ {Sign::NEG, -143, 0x97ffa5c0'47726b08'c71e0d3e'e3df5f4d_u128},
+ {Sign::NEG, -143, 0x93ffaa70'41f41c23'a83ce035'2bdbd79b_u128},
+ {Sign::NEG, -143, 0x8fffaf00'3cbfccbe'2e21a18d'4680e8e4_u128},
+ {Sign::NEG, -143, 0x8bffb370'37d37cdf'30bcb3e4'e5dfbd28_u128},
+ {Sign::NEG, -143, 0x87ffb7c0'332d2c8d'57ff51d7'5c66d64a_u128},
+ {Sign::NEG, -143, 0x83ffbbf0'2ecadbcf'1bdb87fd'be299f43_u128},
+ {Sign::NEG, -144, 0xffff8000'55551555'88885dde'02700703_u128},
+ {Sign::NEG, -144, 0xf7ff87e0'4d94724c'd259ca80'3a0c1870_u128},
+ {Sign::NEG, -144, 0xefff8f80'464fce8f'e5141308'51c7070a_u128},
+ {Sign::NEG, -144, 0xe7ff96e0'3f832a2a'30a16898'f3073a64_u128},
+ {Sign::NEG, -144, 0xdfff9e00'392a8526'c4ed6451'7b2949ce_u128},
+ {Sign::NEG, -144, 0xd7ffa4e0'3341df90'51e4fb4e'32cf6350_u128},
+ {Sign::NEG, -144, 0xcfffab80'2dc53971'277672a8'8350bcce_u128},
+ {Sign::NEG, -144, 0xc7ffb1e0'28b092d3'35915377'2a490f06_u128},
+ {Sign::NEG, -144, 0xbfffb800'23ffebc0'0c265ece'6b481a0e_u128},
+ {Sign::NEG, -144, 0xb7ffbde0'1faf4440'db2781c0'3fa132f6_u128},
+ {Sign::NEG, -144, 0xafffc380'1bba9c5e'7287c95c'845ada33_u128},
+ {Sign::NEG, -144, 0xa7ffc8e0'181df421'423b56b1'263e5a77_u128},
+ {Sign::NEG, -144, 0x9fffce00'14d54b91'5a3752ca'4c076fa3_u128},
+ {Sign::NEG, -144, 0x97ffd2e0'11dca2b6'6a71e2b2'7eb3f573_u128},
+ {Sign::NEG, -144, 0x8fffd780'0f2ff997'c2e21b72'cff39d8f_u128},
+ {Sign::NEG, -144, 0x87ffdbe0'0ccb503c'537ff612'feb7ac9e_u128},
+ {Sign::NEG, -145, 0xffffc000'15554d55'58888733'33c57c18_u128},
+ {Sign::NEG, -145, 0xefffc7c0'1193f9d1'fa514218'42311c42_u128},
+ {Sign::NEG, -145, 0xdfffcf00'0e4aa5fa'2c4ed6de'475b942c_u128},
+ {Sign::NEG, -145, 0xcfffd5c0'0b7151d8'ce77678c'bb6fcb88_u128},
+ {Sign::NEG, -145, 0xbfffdc00'08fffd78'00c26629'a679ed3b_u128},
+ {Sign::NEG, -145, 0xafffe1c0'06eea8e1'23287cb9'd3072728_u128},
+ {Sign::NEG, -145, 0x9fffe700'0535541c'd5a37540'fd057315_u128},
+ {Sign::NEG, -145, 0x8fffebc0'03cbff32'f82e21c1'fce36810_u128},
+ {Sign::NEG, -146, 0xffffe000'05555455'5588887d'dde02702_u128},
+ {Sign::NEG, -146, 0xdfffe780'0392aa14'9ac4ed72'adf5b295_u128},
+ {Sign::NEG, -146, 0xbfffee00'023fffaf'000c2664'8066b482_u128},
+ {Sign::NEG, -146, 0x9ffff380'014d552e'455a3754'b292c077_u128},
+ {Sign::NEG, -147, 0xfffff000'01555535'55588888'33333c58_u128},
+ {Sign::NEG, -147, 0xbffff700'008ffff5'e000c266'5736679f_u128},
+ {Sign::NEG, -148, 0xfffff800'00555551'55558888'85ddde02_u128},
+ {Sign::NEG, -149, 0xfffffc00'00155554'd5555888'88733334_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -148, 0x80000200'000aaaaa'eaaaac44'444eeeef_u128},
+ {Sign::POS, -147, 0x80000400'002aaaac'aaaac444'459999ac_u128},
+ {Sign::POS, -147, 0xc0000900'0090000a'2000c266'7596679f_u128},
+ {Sign::POS, -146, 0x80000800'00aaaaba'aaac4444'6eeef381_u128},
+ {Sign::POS, -146, 0xa0000c80'014d557c'655a3755'f81815cc_u128},
+ {Sign::POS, -146, 0xc0001200'02400051'000c2668'4c66b482_u128},
+ {Sign::POS, -146, 0xe0001880'0392ab40'bac4ed7c'40fb07eb_u128},
+ {Sign::POS, -145, 0x80001000'02aaab2a'aac44449'999abe2c_u128},
+ {Sign::POS, -145, 0x90001440'03cc00cd'082e21d7'9cbb6812_u128},
+ {Sign::POS, -145, 0xa0001900'0535568d'd5a37569'adb01dc3_u128},
+ {Sign::POS, -145, 0xb0001e40'06eeac74'33287d01'e8c9d1d9_u128},
+ {Sign::POS, -145, 0xc0002400'09000288'00c266a3'2679ed48_u128},
+ {Sign::POS, -145, 0xd0002a40'0b7158d1'de776851'22b2764b_u128},
+ {Sign::POS, -145, 0xe0003100'0e4aaf5b'2c4ed810'a8063f03_u128},
+ {Sign::POS, -145, 0xf0003840'1194062e'0a5143e7'be891c8f_u128},
+ {Sign::POS, -144, 0x80002000'0aaaaeaa'ac4444ee'ef3813a1_u128},
+ {Sign::POS, -144, 0x88002420'0ccb5a6e'5b7ff7fe'1339025b_u128},
+ {Sign::POS, -144, 0x90002880'0f300668'42e21e26'caf39e33_u128},
+ {Sign::POS, -144, 0x98002d20'11dcb29e'f271e66f'a5554bc6_u128},
+ {Sign::POS, -144, 0xa0003200'14d55f19'5a3757e0'615cc676_u128},
+ {Sign::POS, -144, 0xa8003720'181e0bde'ca3b5d82'10ca5cab_u128},
+ {Sign::POS, -144, 0xb0003c80'1bbab8f6'f287d25f'3cb032bb_u128},
+ {Sign::POS, -144, 0xb8004220'1faf6669'e3278d84'0be28cdb_u128},
+ {Sign::POS, -144, 0xc0004800'24001440'0c266dfe'6b482076_u128},
+ {Sign::POS, -144, 0xc8004e20'28b0c282'3d9166de'380a6d3d_u128},
+ {Sign::POS, -144, 0xd0005480'2dc57139'a7768b35'6ba61e4b_u128},
+ {Sign::POS, -144, 0xd8005b20'3342206f'd9e51a18'49db73c1_u128},
+ {Sign::POS, -144, 0xe0006200'392ad02e'c4ed8a9d'907eb521_u128},
+ {Sign::POS, -144, 0xe8006920'3f838080'b8a197de'a928acd7_u128},
+ {Sign::POS, -144, 0xf0007080'46503170'65144cf7'dcc72d3b_u128},
+ {Sign::POS, -144, 0xf8007820'4d94e308'da5a1108'890d9f6a_u128},
+ {Sign::POS, -143, 0x80004000'2aaacaaa'c4445999'abe2ce2c_u128},
+ {Sign::POS, -143, 0x84004410'2ecb2431'1fdbbb4f'3bffc832_u128},
+ {Sign::POS, -143, 0x88004840'332d7e1d'97ff8f39'ec91b4ee_u128},
+ {Sign::POS, -143, 0x8c004c90'37d3d876'74bcfcf0'b3f0a95d_u128},
+ {Sign::POS, -143, 0x90005100'3cc03342'2e21f80c'a6813aff_u128},
+ {Sign::POS, -143, 0x94005590'41f48e87'6c3d4629'170ce87f_u128},
+ {Sign::POS, -143, 0x98005a40'4772ea4d'071e84e3'b80a8881_u128},
+ {Sign::POS, -143, 0x9c005f10'4d3d469a'06d62fdc'bdd6bec3_u128},
+ {Sign::POS, -143, 0xa0006400'5355a375'a375a6b7'01dc77c0_u128},
+ {Sign::POS, -143, 0xa4006910'59be00e7'450f3318'26ad6b05_u128},
+ {Sign::POS, -143, 0xa8006e40'60785ef6'83b60ea8'bd0aa459_u128},
+ {Sign::POS, -143, 0xac007390'6786bdab'277e6914'69dd13f5_u128},
+ {Sign::POS, -143, 0xb0007900'6eeb1d0d'287d6e0a'0d1e25eb_u128},
+ {Sign::POS, -143, 0xb4007e90'76a77d24'aec94b3b'e9b060f5_u128},
+ {Sign::POS, -143, 0xb8008440'7ebdddfa'1279365f'ce280cce_u128},
+ {Sign::POS, -143, 0xbc008a10'87303f95'dba5732f'3e83e04a_u128},
+ {Sign::POS, -143, 0xc0009000'9000a200'c2675967'9ed5b754_u128},
+ {Sign::POS, -143, 0xc4009610'99310543'aed95aca'5edb5109_u128},
+ {Sign::POS, -143, 0xc8009c40'a2c36967'b917091d'2687160f_u128},
+ {Sign::POS, -143, 0xcc00a290'acb9ce76'293d1c2a'0378e75d_u128},
+ {Sign::POS, -143, 0xd000a900'b7163478'776977bf'9766f5a7_u128},
+ {Sign::POS, -143, 0xd400af90'c1da9b78'4bbb31b1'4776a18b_u128},
+ {Sign::POS, -143, 0xd800b640'cd09037f'7e5297d7'6c8564ba_u128},
+ {Sign::POS, -143, 0xdc00bd10'd8a36c98'1751360f'8461c447_u128},
+ {Sign::POS, -143, 0xe000c400'e4abd6cc'4ed9dc3c'63f44c41_u128},
+ {Sign::POS, -143, 0xe400cb10'f1244226'8d10a446'6a5894d5_u128},
+ {Sign::POS, -143, 0xe800d240'fe0eaeb1'6a1af81b'b4e6510e_u128},
+ {Sign::POS, -143, 0xec00d991'0b6d1c77'ae1f97b0'542a677a_u128},
+ {Sign::POS, -143, 0xf000e101'19418b84'51469efe'81d014cc_u128},
+ {Sign::POS, -143, 0xf400e891'278dfbe2'7bb98c06'd77a18b4_u128},
+ {Sign::POS, -143, 0xf800f041'36546d9d'85a344d0'868bed17_u128},
+ {Sign::POS, -143, 0xfc00f811'4596e0c0'f7301d69'90e307cc_u128},
+ {Sign::POS, -142, 0x80008000'aaabaaac'4446eef3'8140138f_u128},
+ {Sign::POS, -142, 0x82008408'b2cbe5b8'10f5e432'96105497_u128},
+ {Sign::POS, -142, 0x84008820'bb2d2189'edbd4f83'ef63f730_u128},
+ {Sign::POS, -142, 0x86008c48'c3d05e27'feb654fd'541c638e_u128},
+ {Sign::POS, -142, 0x88009080'ccb69b98'7ffadeb8'882f7674_u128},
+ {Sign::POS, -142, 0x8a0094c8'd5e0d9e1'c5a59fd3'6bd44397_u128},
+};
+
+// Minimax polynomial generated by Sollya with:
+// > P = fpminimax((log(1 + x) - x)/x^2, 3, [|1, 128...|],
+// [-0x1.01928p-22 , 0x1p-22]);
+// > P;
+// > dirtyinfnorm(log(1 + x)/x - 1 - x*P, [-0x1.01928p-22 , 0x1p-22]);
+// 0x1.ce1e...p-116
+LIBC_INLINE_VAR constexpr Float128 BIG_COEFFS[4]{
+ {Sign::POS, -130, 0xccccccd7'4818e397'7ed78465'd460315b_u128},
+ {Sign::NEG, -129, 0x80000000'000478b0'c6388a23'871ce156_u128},
+ {Sign::POS, -129, 0xaaaaaaaa'aaaaaaaa'aa807bd8'67763262_u128},
+ {Sign::NEG, -128, 0x80000000'00000000'00000000'00000000_u128},
+};
+
+[[maybe_unused]] LIBC_INLINE static double
+log1p_accurate(int e_x, int index, fputil::DoubleDouble m_x) {
+ Float128 e_x_f128(static_cast<float>(e_x));
+ Float128 sum = fputil::quick_mul(LOG_2, e_x_f128);
+ sum = fputil::quick_add(sum, LOG_R1[index]);
+
+ // fputil::DoubleDouble v4;
+ Float128 v = fputil::quick_add(Float128(m_x.hi), Float128(m_x.lo));
+
+ // Skip 2nd range reduction step if |m_x| <= 2^-15.
+ if (m_x.hi > 0x1p-15 || m_x.hi < -0x1p-15) {
+ // Range reduction - Step 2.
+ // For k such that: k * 2^-14 - 2^-15 <= m_x.hi < k * 2^-14 + 2^-15,
+ // Let s_k = 2^-18 * round( 2^18 / (1 + k*2^-14) ) - 1
+ // Then the 2nd reduced argument is:
+ // (1 + s_k) * (1 + m_x) - 1 =
+ // = s_k + m_x + s_k * m_x
+ // Output range:
+ // -0x1.1037c00000040271p-15 <= v2.hi + v2.lo <= 0x1.108480000008096cp-15
+ int idx2 = static_cast<int>(0x1p14 * (m_x.hi + (91 * 0x1p-14 + 0x1p-15)));
+ sum = fputil::quick_add(sum, LOG_R2[idx2]);
+ Float128 s2 = Float128(S2[idx2]);
+ v = fputil::quick_add(fputil::quick_add(v, s2), fputil::quick_mul(v, s2));
+ }
+
+ // Skip 3rd range reduction step if |v| <= 2^-22.
+ if (v.exponent > -150) {
+ // Range reduction - Step 3.
+ // For k such that: k * 2^-21 - 2^-22 <= v2.hi < k * 2^-21 + 2^-22,
+ // Let s_k = 2^-21 * round( 2^21 / (1 + k*2^-21) ) - 1
+ // Then the 3rd reduced argument is:
+ // v3.hi + v3.lo ~ (1 + s_k) * (1 + v2.hi + v2.lo) - 1
+ // Output range:
+ // -0x1.012bb800000800114p-22 <= v3.hi + v3.lo <= 0x1p-22
+ int idx3 =
+ static_cast<int>(0x1p21 * (double(v) + (69 * 0x1p-21 + 0x1p-22)));
+ sum = fputil::quick_add(sum, LOG_R3[idx3]);
+ Float128 s3 = Float128(S3[idx3]);
+ v = fputil::quick_add(fputil::quick_add(v, s3), fputil::quick_mul(v, s3));
+ }
+
+ // Polynomial approximation
+ Float128 p = fputil::quick_mul(v, BIG_COEFFS[0]);
+ p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[1]));
+ p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[2]));
+ p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[3]));
+ p = fputil::quick_add(v, fputil::quick_mul(v, p));
+
+ Float128 r = fputil::quick_add(sum, p);
+
+ return static_cast<double>(r);
+}
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace log1p_internal
+
+LIBC_INLINE static double log1p(double x) {
+ using namespace log1p_internal;
+ using FPBits_t = typename fputil::FPBits<double>;
+
+ constexpr int EXP_BIAS = FPBits_t::EXP_BIAS;
+ constexpr int FRACTION_LEN = FPBits_t::FRACTION_LEN;
+ FPBits_t xbits(x);
+ uint64_t x_u = xbits.uintval();
+
+ fputil::DoubleDouble x_dd{0.0, 0.0};
+
+ uint16_t x_exp = xbits.get_biased_exponent();
+
+ if (x_exp >= EXP_BIAS) {
+ // |x| >= 1
+ if (LIBC_UNLIKELY(x_u >= 0x4650'0000'0000'0000ULL)) {
+ // x >= 2^102 or x is negative, inf, or NaN
+ if (LIBC_UNLIKELY(x_u > FPBits_t::max_normal().uintval())) {
+ // x <= -1.0 or x is Inf or NaN
+ if (x_u == 0xbff0'0000'0000'0000ULL) {
+ // x = -1.0
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits_t::inf(Sign::NEG).get_val();
+ }
+ if (xbits.is_neg() && !xbits.is_nan()) {
+ // x < -1.0
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
+ }
+ // x is +Inf or NaN
+ if (xbits.is_inf() && xbits.is_pos())
+ return x;
+
+ if (xbits.is_signaling_nan())
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
+ }
+ x_dd.hi = x;
+ } else {
+ x_dd = fputil::exact_add(x, 1.0);
+ }
+ } else {
+ // |x| < 1
+ if (LIBC_UNLIKELY(xbits.get_biased_exponent() <
+ EXP_BIAS - FRACTION_LEN - 1)) {
+ // Quick return when |x| < 2^-53.
+ // Since log(1 + x) = x - x^2/2 + x^3/3 - ...,
+ // for |x| < 2^-53,
+ // x > log(1 + x) > x - x^2 > x(1 - 2^-54) > x - ulp(x)/2
+ // Thus,
+ // log(1 + x) = nextafter(x, -inf) for FE_DOWNWARD, or
+ // FE_TOWARDZERO and x > 0,
+ // = x otherwise.
+ if (x + x == 0.0)
+ return x + x; // Handle FTZ/DAZ correctly.
+
+ volatile float tp = 1.0f;
+ volatile float tn = -1.0f;
+ bool rdp = (tp - 0x1p-25f != tp);
+ bool rdn = (tn - 0x1p-24f != tn);
+
+ if (x > 0 && rdp) {
+ return FPBits_t(x_u - 1).get_val();
+ }
+
+ if (x < 0 && rdn) {
+ return FPBits_t(x_u + 1).get_val();
+ }
+
+ return x;
+ }
+ x_dd = fputil::exact_add(1.0, x);
+ }
+
+ // At this point, x_dd is the exact sum of 1 + x:
+ // x_dd.hi + x_dd.lo = x + 1.0 exactly.
+ // |x_dd.hi| >= 2^-54
+ // |x_dd.lo| < ulp(x_dd.hi)
+
+ FPBits_t xhi_bits(x_dd.hi);
+ uint64_t xhi_frac = xhi_bits.get_mantissa();
+ x_u = xhi_bits.uintval();
+ // Range reduction:
+ // Find k such that |x_hi - k * 2^-7| <= 2^-8.
+ int idx = static_cast<int>((xhi_frac + (1ULL << (FRACTION_LEN - 8))) >>
+ (FRACTION_LEN - 7));
+ int x_e = xhi_bits.get_exponent() + (idx >> 7);
+ double e_x = static_cast<double>(x_e);
+
+ // hi is exact
+ // ulp(hi) = ulp(LOG_2_HI) = ulp(LOG_R1_DD[idx].hi) = 2^-43
+ double hi = fputil::multiply_add(e_x, LOG_2_HI, LOG_R1_DD[idx].hi);
+ // lo errors < |e_x| * ulp(LOG_2_LO) + ulp(LOG_R1[idx].lo)
+ // <= 2^11 * 2^(-43-53) = 2^-85
+ double lo = fputil::multiply_add(e_x, LOG_2_LO, LOG_R1_DD[idx].lo);
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Error bound of e_x * log(2) - log(r1)
+ constexpr double ERR_HI[2] = {0x1.0p-85, 0.0};
+ double err_hi = ERR_HI[hi == 0.0];
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ // Scale x_dd by 2^(-xh_bits.get_exponent()).
+ int64_t s_u = static_cast<int64_t>(x_u & FPBits_t::EXP_MASK) -
+ (static_cast<int64_t>(EXP_BIAS) << FRACTION_LEN);
+ // Normalize arguments:
+ // 1 <= m_dd.hi < 2
+ // |m_dd.lo| < 2^-52.
+ // This is exact.
+ uint64_t m_hi = FPBits_t::one().uintval() | xhi_frac;
+
+ uint64_t m_lo =
+ FPBits_t(x_dd.lo).abs().get_val() > x_dd.hi * 0x1.0p-127
+ ? static_cast<uint64_t>(cpp::bit_cast<int64_t>(x_dd.lo) - s_u)
+ : 0;
+
+ fputil::DoubleDouble m_dd{FPBits_t(m_lo).get_val(), FPBits_t(m_hi).get_val()};
+
+ // Perform range reduction:
+ // r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1
+ // = (r * m_dd.hi - 1) + r * m_dd.lo
+ // = v_hi + (v_lo.hi + v_lo.lo)
+ // where:
+ // v_hi = r * m_dd.hi - 1 (exact)
+ // v_lo.hi + v_lo.lo = r * m_dd.lo (exact)
+ // Bounds on the values:
+ // -0x1.69000000000edp-8 < r * m - 1 < 0x1.7f00000000081p-8
+ // |v_lo.hi| <= |r| * |m_dd.lo| < 2^-52
+ // |v_lo.lo| < ulp(v_lo.hi) <= 2^(-52 - 53) = 2^(-105)
+ double r = R1[idx];
+ fputil::DoubleDouble v_lo = fputil::exact_mult(m_dd.lo, r);
+
+ // Perform exact range reduction
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ double v_hi = fputil::multiply_add(r, m_dd.hi, -1.0); // Exact.
+#else
+ // c = 1 + idx * 2^-7.
+ double c = FPBits_t((static_cast<uint64_t>(idx) << (FRACTION_LEN - 7)) +
+ uint64_t(0x3FF0'0000'0000'0000ULL))
+ .get_val();
+ double v_hi = fputil::multiply_add(r, m_dd.hi - c, RCM1[idx]); // Exact
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+
+ // Range reduction output:
+ // -0x1.69000000000edp-8 < v_hi + v_lo < 0x1.7f00000000081p-8
+ // |v_dd.lo| < ulp(v_dd.hi) <= 2^(-7 - 53) = 2^-60
+ fputil::DoubleDouble v_dd = fputil::exact_add(v_hi, v_lo.hi);
+ v_dd.lo += v_lo.lo;
+
+ // Exact sum:
+ // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
+ fputil::DoubleDouble r1 = fputil::exact_add(hi, v_dd.hi);
+
+ // Overall error is bounded by:
+ // C * ulp(v_sq) + err_hi
+ double v_sq = v_dd.hi * v_dd.hi;
+ double p0 = fputil::multiply_add(v_dd.hi, P_COEFFS[1], P_COEFFS[0]);
+ double p1 = fputil::multiply_add(v_dd.hi, P_COEFFS[3], P_COEFFS[2]);
+ double p2 = fputil::multiply_add(v_dd.hi, P_COEFFS[5], P_COEFFS[4]);
+ double p = fputil::polyeval(v_sq, (v_dd.lo + r1.lo) + lo, p0, p1, p2);
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return r1.hi + p;
+#else
+ double err = fputil::multiply_add(v_sq, P_ERR, err_hi);
+
+ double left = r1.hi + (p - err);
+ double right = r1.hi + (p + err);
+
+ // Ziv's test to see if fast pass is accurate enough.
+ if (left == right)
+ return left;
+
+ return log1p_accurate(x_e, idx, v_dd);
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG1P_H
diff --git a/libc/src/__support/math/log2.h b/libc/src/__support/math/log2.h
new file mode 100644
index 0000000..79ec907
--- /dev/null
+++ b/libc/src/__support/math/log2.h
@@ -0,0 +1,978 @@
+//===-- Double-precision log2(x) function ---------------------------------===//
+//
+// 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_LOG2_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG2_H
+
+#include "common_constants.h"
+#include "log_range_reduction.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/integer_literals.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+namespace log2_internal {
+// 128-bit precision dyadic floating point numbers.
+using Float128 = typename fputil::DyadicFloat<128>;
+
+using LIBC_NAMESPACE::operator""_u128;
+
+using namespace common_constants_internal;
+using namespace math::log_range_reduction_internal;
+
+LIBC_INLINE_VAR constexpr fputil::DoubleDouble LOG2_E = {0x1.777d0ffda0d24p-56,
+ 0x1.71547652b82fep0};
+
+alignas(16) LIBC_INLINE_VAR const fputil::DoubleDouble LOG_R1[128] = {
+ {0.0, 0.0},
+ {0x1.46662d417cedp-62, 0x1.010157588de71p-7},
+ {0x1.27c8e8416e71fp-60, 0x1.0205658935847p-6},
+ {-0x1.d192d0619fa67p-60, 0x1.8492528c8cabfp-6},
+ {0x1.c05cf1d753622p-59, 0x1.0415d89e74444p-5},
+ {-0x1.cdd6f7f4a137ep-59, 0x1.466aed42de3eap-5},
+ {0x1.a8be97660a23dp-60, 0x1.894aa149fb343p-5},
+ {-0x1.e48fb0500efd4p-59, 0x1.ccb73cdddb2ccp-5},
+ {-0x1.dd7009902bf32p-58, 0x1.08598b59e3a07p-4},
+ {-0x1.7558367a6acf6p-59, 0x1.1973bd1465567p-4},
+ {0x1.7a976d3b5b45fp-59, 0x1.3bdf5a7d1ee64p-4},
+ {0x1.f38745c5c450ap-58, 0x1.5e95a4d9791cbp-4},
+ {-0x1.72566212cdd05p-61, 0x1.700d30aeac0e1p-4},
+ {-0x1.478a85704ccb7p-58, 0x1.9335e5d594989p-4},
+ {-0x1.0057eed1ca59fp-59, 0x1.b6ac88dad5b1cp-4},
+ {0x1.a38cb559a6706p-58, 0x1.c885801bc4b23p-4},
+ {-0x1.a2bf991780d3fp-59, 0x1.ec739830a112p-4},
+ {-0x1.ac9f4215f9393p-58, 0x1.fe89139dbd566p-4},
+ {-0x1.0e63a5f01c691p-58, 0x1.1178e8227e47cp-3},
+ {-0x1.c6ef1d9b2ef7ep-59, 0x1.1aa2b7e23f72ap-3},
+ {-0x1.499a3f25af95fp-58, 0x1.2d1610c86813ap-3},
+ {0x1.7d411a5b944adp-58, 0x1.365fcb0159016p-3},
+ {-0x1.0d5604930f135p-58, 0x1.4913d8333b561p-3},
+ {-0x1.71a9682395bfdp-61, 0x1.527e5e4a1b58dp-3},
+ {-0x1.d34f0f4621bedp-60, 0x1.6574ebe8c133ap-3},
+ {-0x1.8de59c21e166cp-57, 0x1.6f0128b756abcp-3},
+ {-0x1.1232ce70be781p-57, 0x1.823c16551a3c2p-3},
+ {0x1.55aa8b6997a4p-58, 0x1.8beafeb38fe8cp-3},
+ {0x1.142c507fb7a3dp-58, 0x1.95a5adcf7017fp-3},
+ {0x1.bcafa9de97203p-57, 0x1.a93ed3c8ad9e3p-3},
+ {-0x1.6353ab386a94dp-57, 0x1.b31d8575bce3dp-3},
+ {0x1.dd355f6a516d7p-60, 0x1.bd087383bd8adp-3},
+ {0x1.60629242471a2p-57, 0x1.d1037f2655e7bp-3},
+ {0x1.aa11d49f96cb9p-58, 0x1.db13db0d4894p-3},
+ {0x1.2276041f43042p-59, 0x1.e530effe71012p-3},
+ {-0x1.08ab2ddc708ap-58, 0x1.ef5ade4dcffe6p-3},
+ {0x1.f665066f980a2p-57, 0x1.f991c6cb3b379p-3},
+ {0x1.cdb16ed4e9138p-56, 0x1.07138604d5862p-2},
+ {0x1.162c79d5d11eep-58, 0x1.0c42d676162e3p-2},
+ {-0x1.0e63a5f01c691p-57, 0x1.1178e8227e47cp-2},
+ {0x1.66fbd28b40935p-56, 0x1.16b5ccbacfb73p-2},
+ {-0x1.12aeb84249223p-57, 0x1.1bf99635a6b95p-2},
+ {0x1.e0efadd9db02bp-56, 0x1.269621134db92p-2},
+ {-0x1.82dad7fd86088p-56, 0x1.2bef07cdc9354p-2},
+ {-0x1.3d69909e5c3dcp-56, 0x1.314f1e1d35ce4p-2},
+ {-0x1.324f0e883858ep-58, 0x1.36b6776be1117p-2},
+ {-0x1.2ad27e50a8ec6p-56, 0x1.3c25277333184p-2},
+ {0x1.0dbb243827392p-57, 0x1.419b423d5e8c7p-2},
+ {0x1.8fb4c14c56eefp-60, 0x1.4718dc271c41bp-2},
+ {-0x1.123615b147a5dp-58, 0x1.4c9e09e172c3cp-2},
+ {-0x1.8f7e9b38a6979p-57, 0x1.522ae0738a3d8p-2},
+ {-0x1.0908d15f88b63p-57, 0x1.57bf753c8d1fbp-2},
+ {-0x1.6541148cbb8a2p-56, 0x1.5d5bddf595f3p-2},
+ {0x1.dc18ce51fff99p-57, 0x1.630030b3aac49p-2},
+ {0x1.a64eadd740178p-58, 0x1.68ac83e9c6a14p-2},
+ {0x1.657c222d868cdp-58, 0x1.6e60ee6af1972p-2},
+ {0x1.84a4ee3059583p-56, 0x1.741d876c67bb1p-2},
+ {-0x1.c168817443f22p-56, 0x1.79e26687cfb3ep-2},
+ {-0x1.219024acd3b77p-58, 0x1.7fafa3bd8151cp-2},
+ {-0x1.486666443b153p-56, 0x1.85855776dcbfbp-2},
+ {-0x1.70f2f38238303p-56, 0x1.8b639a88b2df5p-2},
+ {-0x1.ad4bb98c1f2c5p-56, 0x1.914a8635bf68ap-2},
+ {-0x1.89d2816cf838fp-57, 0x1.973a3431356aep-2},
+ {0x1.87bcbcfd3e187p-59, 0x1.9d32bea15ed3bp-2},
+ {-0x1.ba8062860ae23p-57, 0x1.a33440224fa79p-2},
+ {-0x1.ba8062860ae23p-57, 0x1.a33440224fa79p-2},
+ {0x1.bcafa9de97203p-56, 0x1.a93ed3c8ad9e3p-2},
+ {0x1.9d56c45dd3e86p-56, 0x1.af5295248cddp-2},
+ {0x1.494b610665378p-56, 0x1.b56fa04462909p-2},
+ {0x1.6fd02999b21e1p-59, 0x1.bb9611b80e2fbp-2},
+ {-0x1.bfc00b8f3feaap-56, 0x1.c1c60693fa39ep-2},
+ {-0x1.bfc00b8f3feaap-56, 0x1.c1c60693fa39ep-2},
+ {0x1.223eadb651b4ap-57, 0x1.c7ff9c74554c9p-2},
+ {0x1.0798270b29f39p-56, 0x1.ce42f18064743p-2},
+ {0x1.d7f4d3b3d406bp-56, 0x1.d490246defa6bp-2},
+ {-0x1.0b5837185a661p-56, 0x1.dae75484c9616p-2},
+ {-0x1.ac81cc8a4dfb8p-56, 0x1.e148a1a2726cep-2},
+ {-0x1.ac81cc8a4dfb8p-56, 0x1.e148a1a2726cep-2},
+ {0x1.57d646a17bc6ap-56, 0x1.e7b42c3ddad73p-2},
+ {-0x1.74b71fb5e57e3p-62, 0x1.ee2a156b413e5p-2},
+ {-0x1.0d487f5aba5e5p-57, 0x1.f4aa7ee03192dp-2},
+ {-0x1.0d487f5aba5e5p-57, 0x1.f4aa7ee03192dp-2},
+ {0x1.7e8f05924d259p-57, 0x1.fb358af7a4884p-2},
+ {0x1.1713a36138e19p-57, 0x1.00e5ae5b207abp-1},
+ {-0x1.17f9e54e78104p-57, 0x1.04360be7603adp-1},
+ {-0x1.17f9e54e78104p-57, 0x1.04360be7603adp-1},
+ {0x1.2241edf5fd1f7p-57, 0x1.078bf0533c568p-1},
+ {0x1.0d710fcfc4e0dp-55, 0x1.0ae76e2d054fap-1},
+ {0x1.0d710fcfc4e0dp-55, 0x1.0ae76e2d054fap-1},
+ {0x1.3300f002e836ep-55, 0x1.0e4898611cce1p-1},
+ {-0x1.91eee7772c7c2p-55, 0x1.11af823c75aa8p-1},
+ {-0x1.91eee7772c7c2p-55, 0x1.11af823c75aa8p-1},
+ {0x1.342eb628dba17p-56, 0x1.151c3f6f29612p-1},
+ {0x1.89df1568ca0bp-55, 0x1.188ee40f23ca6p-1},
+ {0x1.89df1568ca0bp-55, 0x1.188ee40f23ca6p-1},
+ {0x1.59bddae1ccce2p-56, 0x1.1c07849ae6007p-1},
+ {-0x1.2164ff40e9817p-56, 0x1.1f8635fc61659p-1},
+ {-0x1.2164ff40e9817p-56, 0x1.1f8635fc61659p-1},
+ {-0x1.fcc8dbccc25cbp-57, 0x1.230b0d8bebc98p-1},
+ {0x1.e0efadd9db02bp-55, 0x1.269621134db92p-1},
+ {0x1.e0efadd9db02bp-55, 0x1.269621134db92p-1},
+ {-0x1.6a0c343be95dcp-56, 0x1.2a2786d0ec107p-1},
+ {-0x1.b941ee770436bp-56, 0x1.2dbf557b0df43p-1},
+ {-0x1.b941ee770436bp-56, 0x1.2dbf557b0df43p-1},
+ {0x1.6c3a5f12642c9p-57, 0x1.315da4434068bp-1},
+ {0x1.6c3a5f12642c9p-57, 0x1.315da4434068bp-1},
+ {-0x1.f01ab6065515cp-56, 0x1.35028ad9d8c86p-1},
+ {0x1.21512aa596ea3p-55, 0x1.38ae2171976e7p-1},
+ {0x1.21512aa596ea3p-55, 0x1.38ae2171976e7p-1},
+ {0x1.1930603d87b6ep-56, 0x1.3c6080c36bfb5p-1},
+ {0x1.1930603d87b6ep-56, 0x1.3c6080c36bfb5p-1},
+ {0x1.86cf0f38b461ap-57, 0x1.4019c2125ca93p-1},
+ {-0x1.84f481051f71ap-56, 0x1.43d9ff2f923c5p-1},
+ {-0x1.84f481051f71ap-56, 0x1.43d9ff2f923c5p-1},
+ {0x1.2541aca7d5844p-55, 0x1.47a1527e8a2d3p-1},
+ {0x1.2541aca7d5844p-55, 0x1.47a1527e8a2d3p-1},
+ {0x1.c457b531506f6p-55, 0x1.4b6fd6f970c1fp-1},
+ {0x1.c457b531506f6p-55, 0x1.4b6fd6f970c1fp-1},
+ {0x1.d749362382a77p-56, 0x1.4f45a835a4e19p-1},
+ {0x1.d749362382a77p-56, 0x1.4f45a835a4e19p-1},
+ {0x1.988ba4aea614dp-56, 0x1.5322e26867857p-1},
+ {0x1.988ba4aea614dp-56, 0x1.5322e26867857p-1},
+ {0x1.80bff3303dd48p-55, 0x1.5707a26bb8c66p-1},
+ {0x1.80bff3303dd48p-55, 0x1.5707a26bb8c66p-1},
+ {-0x1.6714fbcd8135bp-55, 0x1.5af405c3649ep-1},
+ {-0x1.6714fbcd8135bp-55, 0x1.5af405c3649ep-1},
+ {0x1.1c066d235ee63p-56, 0x1.5ee82aa24192p-1},
+ {0.0, 0.0},
+};
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+// Extra errors from P is from using x^2 to reduce evaluation latency.
+LIBC_INLINE_VAR constexpr double P_ERR = 0x1.0p-49;
+
+alignas(16) LIBC_INLINE_VAR constexpr LogRR LOG2_TABLE = {
+ // -log2(r) with 128-bit precision generated by SageMath with:
+ // def format_hex(value):
+ // l = hex(value)[2:]
+ // n = 8
+ // x = [l[i:i + n] for i in range(0, len(l), n)]
+ // return "0x" + "'".join(x) + "_u128"
+ // for i in range(1, 127):
+ // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) );
+ // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
+ // print("{Sign::POS,", e, ", format_hex(m), "},");
+ /* .step_1 = */ {
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -134, 0xb963dd10'7b993ada'e8c25163'0adb856a_u128},
+ {Sign::POS, -133, 0xba1f7430'f9aab1b2'a41b08fb'e05f82d0_u128},
+ {Sign::POS, -132, 0x8c25c726'2b57c149'1f06c085'bc1b865d_u128},
+ {Sign::POS, -132, 0xbb9ca64e'cac6aaef'2e1c07f0'438ebac0_u128},
+ {Sign::POS, -132, 0xeb75e8f8'ff5ff022'aacc0e21'd6541224_u128},
+ {Sign::POS, -131, 0x8dd99530'02a4e866'31514aef'39ce6303_u128},
+ {Sign::POS, -131, 0xa62b07f3'457c4070'50799bea'aab2940c_u128},
+ {Sign::POS, -131, 0xbeb024b6'7dda6339'da288fc6'15a727dc_u128},
+ {Sign::POS, -131, 0xcb0657cd'5dbe4f6f'22dbbace'd44516ce_u128},
+ {Sign::POS, -131, 0xe3da945b'878e27d0'd939dcee'cdd9ce05_u128},
+ {Sign::POS, -131, 0xfce4aee0'e88b2749'9596a8e2'e84c8f45_u128},
+ {Sign::POS, -130, 0x84bf1c67'3032495d'243efd93'25954cfe_u128},
+ {Sign::POS, -130, 0x916d6e15'59a4b696'91d79938'e7226384_u128},
+ {Sign::POS, -130, 0x9e37db28'66f2850b'22563c9e'd9462091_u128},
+ {Sign::POS, -130, 0xa4a7c31d'c6f9a5d5'3a53ca11'81015ada_u128},
+ {Sign::POS, -130, 0xb19d45fa'1be70855'3eb8023e'ed65d601_u128},
+ {Sign::POS, -130, 0xb823018e'3cfc25f0'ce5cabbd'2d753d9b_u128},
+ {Sign::POS, -130, 0xc544c055'fde99333'54dbf16f'b0695ee3_u128},
+ {Sign::POS, -130, 0xcbe0e589'e3f6042d'5196a85a'067c6739_u128},
+ {Sign::POS, -130, 0xd930124b'ea9a2c66'f349845e'48955078_u128},
+ {Sign::POS, -130, 0xdfe33d3f'ffa66037'815ef705'cfaef035_u128},
+ {Sign::POS, -130, 0xed61169f'220e97f2'2ba704dc'aa76f41d_u128},
+ {Sign::POS, -130, 0xf42be9e9'b09b3def'2062f36b'c14d0d93_u128},
+ {Sign::POS, -129, 0x80ecdde7'd30ea2ed'13288019'4144b02b_u128},
+ {Sign::POS, -129, 0x845e706c'afd1bf61'54880de6'3812fd49_u128},
+ {Sign::POS, -129, 0x8b4e029b'1f8ac391'a87c02ea'f36e2c29_u128},
+ {Sign::POS, -129, 0x8ecc164e'a93841ae'9804237e'c8d9431d_u128},
+ {Sign::POS, -129, 0x924e6958'9e6b6268'20f81ca9'5d9e7968_u128},
+ {Sign::POS, -129, 0x995ff71b'8773432d'124bc6f1'acf95dc4_u128},
+ {Sign::POS, -129, 0x9cef470a'acfb7bf9'5a5e8e21'bff3336b_u128},
+ {Sign::POS, -129, 0xa08300be'1f651473'4e53fa33'29f65894_u128},
+ {Sign::POS, -129, 0xa7b7dd96'762cc3c7'2742d729'6a39eed6_u128},
+ {Sign::POS, -129, 0xab591735'abc724e4'f359c554'4bc5e134_u128},
+ {Sign::POS, -129, 0xaefee78f'75707221'6b6c874d'd96e1d75_u128},
+ {Sign::POS, -129, 0xb2a95a4c'c313bb59'21006678'c0a5c390_u128},
+ {Sign::POS, -129, 0xb6587b43'2e47501b'6d40900b'25024b32_u128},
+ {Sign::POS, -129, 0xbdc4f816'7955698f'89e2eb55'3b279b3d_u128},
+ {Sign::POS, -129, 0xc1826c86'08fe9951'd58525aa'd392ca50_u128},
+ {Sign::POS, -129, 0xc544c055'fde99333'54dbf16f'b0695ee3_u128},
+ {Sign::POS, -129, 0xc90c0049'26e9dbfb'88d5eae3'326327bb_u128},
+ {Sign::POS, -129, 0xccd83954'b6359379'46dfa05b'ddfded8c_u128},
+ {Sign::POS, -129, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
+ {Sign::POS, -129, 0xd85b3fa7'a3407fa8'7b11f1c5'160c515c_u128},
+ {Sign::POS, -129, 0xdc3be2bd'8d837f7f'1339e567'7ec44dd0_u128},
+ {Sign::POS, -129, 0xe021c2cf'17ed9bdb'ea2b8c7b'b0ee9c8b_u128},
+ {Sign::POS, -129, 0xe40cee16'a2ff21c4'aec56233'2791fe38_u128},
+ {Sign::POS, -129, 0xe7fd7308'd6895b14'71682eba'cca79cfa_u128},
+ {Sign::POS, -129, 0xebf36055'e1abc61e'a5ad5ce9'fb5a7bb6_u128},
+ {Sign::POS, -129, 0xefeec4ea'c371584e'32251905'31a852c5_u128},
+ {Sign::POS, -129, 0xf3efaff2'9c559a77'da8ad649'da21eab0_u128},
+ {Sign::POS, -129, 0xf7f630d8'08fc2ada'4c3e2ea7'c15c3d1e_u128},
+ {Sign::POS, -129, 0xfc025746'86680cc6'bcb9bfa9'852e0d35_u128},
+ {Sign::POS, -128, 0x800a1995'f0019518'ce032f41'd1e774e8_u128},
+ {Sign::POS, -128, 0x8215ea5c'd3e4c4c7'9b39ffee'bc29372a_u128},
+ {Sign::POS, -128, 0x8424a633'5c777e0b'87f95f1b'efb6f806_u128},
+ {Sign::POS, -128, 0x86365578'62acb7ce'b987b42e'3bb332a1_u128},
+ {Sign::POS, -128, 0x884b00ae'f726cec5'139a7ba8'3bf2d136_u128},
+ {Sign::POS, -128, 0x8a62b07f'3457c407'050799be'aaab2941_u128},
+ {Sign::POS, -128, 0x8c7d6db7'169e0cda'8bd74461'7e9b7d52_u128},
+ {Sign::POS, -128, 0x8e9b414b'5a92a606'046ad444'333ceb10_u128},
+ {Sign::POS, -128, 0x90bc3458'61bf3d52'ef4c737f'ba4f5d66_u128},
+ {Sign::POS, -128, 0x92e05023'1df57d6f'ae441c09'd761c549_u128},
+ {Sign::POS, -128, 0x95079e1a'0382dc79'6e36aa9c'e90a3879_u128},
+ {Sign::POS, -128, 0x973227d6'027ebd8a'0efca1a1'84e93809_u128},
+ {Sign::POS, -128, 0x973227d6'027ebd8a'0efca1a1'84e93809_u128},
+ {Sign::POS, -128, 0x995ff71b'8773432d'124bc6f1'acf95dc4_u128},
+ {Sign::POS, -128, 0x9b9115db'83a3dd2d'352bea51'e58ea9e8_u128},
+ {Sign::POS, -128, 0x9dc58e34'7d37696d'266d6cdc'959153bc_u128},
+ {Sign::POS, -128, 0x9ffd6a73'a78eaf35'4527d82c'8214ddca_u128},
+ {Sign::POS, -128, 0xa238b516'0413106e'404cabb7'6d600e3c_u128},
+ {Sign::POS, -128, 0xa238b516'0413106e'404cabb7'6d600e3c_u128},
+ {Sign::POS, -128, 0xa47778c9'8bcc86a1'cab7d2ec'23f0eef3_u128},
+ {Sign::POS, -128, 0xa6b9c06e'6211646b'761c48dd'859de2d3_u128},
+ {Sign::POS, -128, 0xa8ff9718'10a5e181'7fd3b7d7'e5d148bb_u128},
+ {Sign::POS, -128, 0xab49080e'cda53208'c27c6780'd92b4d11_u128},
+ {Sign::POS, -128, 0xad961ed0'cb91d406'db502402'c94092cd_u128},
+ {Sign::POS, -128, 0xad961ed0'cb91d406'db502402'c94092cd_u128},
+ {Sign::POS, -128, 0xafe6e713'93eeda29'3432ef6b'732b6843_u128},
+ {Sign::POS, -128, 0xb23b6cc5'6cc84c99'bb324da7'e046e792_u128},
+ {Sign::POS, -128, 0xb493bc0e'c9954243'b21709ce'430c8e24_u128},
+ {Sign::POS, -128, 0xb493bc0e'c9954243'b21709ce'430c8e24_u128},
+ {Sign::POS, -128, 0xb6efe153'c7e319f6'e91ad16e'cff10111_u128},
+ {Sign::POS, -128, 0xb94fe935'b83e3eb5'ce31e481'cd797e79_u128},
+ {Sign::POS, -128, 0xbbb3e094'b3d228d3'da3e961a'96c580fa_u128},
+ {Sign::POS, -128, 0xbbb3e094'b3d228d3'da3e961a'96c580fa_u128},
+ {Sign::POS, -128, 0xbe1bd491'3f3fda43'f396598a'ae91499a_u128},
+ {Sign::POS, -128, 0xc087d28d'fb2febb8'ae4cceb0'f621941b_u128},
+ {Sign::POS, -128, 0xc087d28d'fb2febb8'ae4cceb0'f621941b_u128},
+ {Sign::POS, -128, 0xc2f7e831'632b6670'6c1855c4'2078f81b_u128},
+ {Sign::POS, -128, 0xc56c2367'9b4d206e'169535fb'8bf577c8_u128},
+ {Sign::POS, -128, 0xc56c2367'9b4d206e'169535fb'8bf577c8_u128},
+ {Sign::POS, -128, 0xc7e49264'4d64237e'3b24cecc'60217942_u128},
+ {Sign::POS, -128, 0xca6143a4'9626d820'3dc2687f'cf939696_u128},
+ {Sign::POS, -128, 0xca6143a4'9626d820'3dc2687f'cf939696_u128},
+ {Sign::POS, -128, 0xcce245f1'031e41fa'0a62e6ad'd1a901a0_u128},
+ {Sign::POS, -128, 0xcf67a85f'a1f89a04'5bb6e231'38ad51e1_u128},
+ {Sign::POS, -128, 0xcf67a85f'a1f89a04'5bb6e231'38ad51e1_u128},
+ {Sign::POS, -128, 0xd1f17a56'21fb01ac'7fc60a51'03092bae_u128},
+ {Sign::POS, -128, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
+ {Sign::POS, -128, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
+ {Sign::POS, -128, 0xd712ac0c'f811659d'8e2d7d37'8127d823_u128},
+ {Sign::POS, -128, 0xd9aa2c3b'0ea3cbc1'5c1a7f14'b168b365_u128},
+ {Sign::POS, -128, 0xd9aa2c3b'0ea3cbc1'5c1a7f14'b168b365_u128},
+ {Sign::POS, -128, 0xdc465cd1'55a90942'b7579f0f'8d3d514b_u128},
+ {Sign::POS, -128, 0xdc465cd1'55a90942'b7579f0f'8d3d514b_u128},
+ {Sign::POS, -128, 0xdee74ee6'4b0c38d3'b087205e'b55aea85_u128},
+ {Sign::POS, -128, 0xe18d13ee'805a4de3'424a2623'd60dfb16_u128},
+ {Sign::POS, -128, 0xe18d13ee'805a4de3'424a2623'd60dfb16_u128},
+ {Sign::POS, -128, 0xe437bdbf'5254459c'4d3a591a'e6854787_u128},
+ {Sign::POS, -128, 0xe437bdbf'5254459c'4d3a591a'e6854787_u128},
+ {Sign::POS, -128, 0xe6e75e91'b9cca551'8dcdb6b2'4c5c5cdf_u128},
+ {Sign::POS, -128, 0xe99c0905'36ece983'33ac7d9e'bba8a53c_u128},
+ {Sign::POS, -128, 0xe99c0905'36ece983'33ac7d9e'bba8a53c_u128},
+ {Sign::POS, -128, 0xec55d022'd80e3d27'fb2eede4'b59d8959_u128},
+ {Sign::POS, -128, 0xec55d022'd80e3d27'fb2eede4'b59d8959_u128},
+ {Sign::POS, -128, 0xef14c760'5d60654c'308b4546'66de8f99_u128},
+ {Sign::POS, -128, 0xef14c760'5d60654c'308b4546'66de8f99_u128},
+ {Sign::POS, -128, 0xf1d902a3'7aaa5085'8383cb0c'e23bebd4_u128},
+ {Sign::POS, -128, 0xf1d902a3'7aaa5085'8383cb0c'e23bebd4_u128},
+ {Sign::POS, -128, 0xf4a29645'38813c67'64fc87b4'a41f7b70_u128},
+ {Sign::POS, -128, 0xf4a29645'38813c67'64fc87b4'a41f7b70_u128},
+ {Sign::POS, -128, 0xf7719715'7665f689'3f5d7d82'b65c5686_u128},
+ {Sign::POS, -128, 0xf7719715'7665f689'3f5d7d82'b65c5686_u128},
+ {Sign::POS, -128, 0xfa461a5e'8f4b759d'6476077b'9fbd41ae_u128},
+ {Sign::POS, -128, 0xfa461a5e'8f4b759d'6476077b'9fbd41ae_u128},
+ {Sign::POS, -128, 0xfd2035e9'221ef5d0'0e3909ff'd0d61778_u128},
+ {Sign::POS, 0, 0_u128},
+ },
+ // -log2(r) for the second step, generated by SageMath with:
+ //
+ // for i in range(-2^6, 2^7 + 1):
+ // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) );
+ // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
+ // print("{Sign::NEG," if s == 1 else "{Sign::POS,", e, ",
+ // format_hex(m), "},");
+ /* .step_2 = */
+ {
+ {Sign::NEG, -135, 0xb9061559'18954401'b5cfed58'337e848a_u128},
+ {Sign::NEG, -135, 0xb6264958'a3c7fa2b'ffaf2ac1'b1d20910_u128},
+ {Sign::NEG, -135, 0xb34671e4'39aa448e'52521a39'50ea2ed8_u128},
+ {Sign::NEG, -135, 0xb0668efb'7ef48ab7'f87e1abd'ee10fd95_u128},
+ {Sign::NEG, -135, 0xad86a09e'185af0e8'fbd43bbc'c24c5e43_u128},
+ {Sign::NEG, -135, 0xaaa6a6cb'aa8d57ce'2f4f5d48'f9796742_u128},
+ {Sign::NEG, -135, 0xa7c6a183'da375c3d'3477fd67'c1cab6b3_u128},
+ {Sign::NEG, -135, 0xa4e690c6'4c0056f0'7b4d33eb'381fe558_u128},
+ {Sign::NEG, -135, 0xa2067492'a48b5c43'3ce25e48'cb498dea_u128},
+ {Sign::NEG, -135, 0x9f264ce8'88773bed'70b0fcc9'e4330983_u128},
+ {Sign::NEG, -135, 0x9c4619c7'9c5e80bf'bc9e4267'd3189b22_u128},
+ {Sign::NEG, -135, 0x9965db2f'84d7705f'5fb3d896'326615c4_u128},
+ {Sign::NEG, -135, 0x9685911f'e6740b02'178b5831'1e96d323_u128},
+ {Sign::NEG, -135, 0x93a53b98'65c20b2a'006bf8b6'cf73d847_u128},
+ {Sign::NEG, -135, 0x90c4da98'a74ae561'7019f6e6'4a580a02_u128},
+ {Sign::NEG, -135, 0x8de46e20'4f93c7f6'cb5733cf'0eb4191d_u128},
+ {Sign::NEG, -135, 0x8b03f62f'031d9ab8'56148d4f'c5e415b6_u128},
+ {Sign::NEG, -135, 0x882372c4'6664feaf'fe5370f4'25872623_u128},
+ {Sign::NEG, -135, 0x8542e3e0'1de24ddf'21b72a14'57ee70d6_u128},
+ {Sign::NEG, -135, 0x81aa211f'1e332fcf'abff4f89'968bed0b_u128},
+ {Sign::NEG, -136, 0xfd92f0cf'88d75f24'86410a67'6480a5a7_u128},
+ {Sign::NEG, -136, 0xf7d1886b'2a876289'44280889'021970e4_u128},
+ {Sign::NEG, -136, 0xf2100910'6a42bc14'32eb139d'9812090d_u128},
+ {Sign::NEG, -136, 0xec4e72be'90cd2d2d'bef9dd41'e8e42810_u128},
+ {Sign::NEG, -136, 0xe68cc574'e6e1e5d7'689d08ca'6c7c3eb1_u128},
+ {Sign::NEG, -136, 0xe0cb0132'b5338423'01ef259a'7f69821d_u128},
+ {Sign::NEG, -136, 0xdb0925f7'446c13a9'e22cea71'b7bb8467_u128},
+ {Sign::NEG, -136, 0xd54733c1'dd2d0d04'0e5bb273'03f542fe_u128},
+ {Sign::NEG, -136, 0xcf852a91'c80f553f'57453c8d'5dc64ce1_u128},
+ {Sign::NEG, -136, 0xc9c30a66'4da33d56'6cc7add1'fc09ef92_u128},
+ {Sign::NEG, -136, 0xc400d33e'b67081a7'e678d728'0de1c07f_u128},
+ {Sign::NEG, -136, 0xbe3e851a'4af6496d'419bbeb2'239bdc39_u128},
+ {Sign::NEG, -136, 0xb87c1ff8'53ab2631'd4676d1d'81755809_u128},
+ {Sign::NEG, -136, 0xb2b9a3d8'18fd1349'b69dfef7'ac2e2890_u128},
+ {Sign::NEG, -136, 0xacf710b8'e3517548'9f72fa0a'8fccabc0_u128},
+ {Sign::NEG, -136, 0xa7346699'fb051978'b8bfe6a3'addb988e_u128},
+ {Sign::NEG, -136, 0xa171a57a'a86c3551'67862c8e'c9dcd60d_u128},
+ {Sign::NEG, -136, 0x9baecd5a'33d265ee'09bd3370'909e28a6_u128},
+ {Sign::NEG, -136, 0x95ebde37'e57aaf84'a96bc611'b991419b_u128},
+ {Sign::NEG, -136, 0x9028d813'059f7cdc'a50bb80f'203f0d62_u128},
+ {Sign::NEG, -136, 0x8a65baea'dc729ec5'4d36cd47'4f65a317_u128},
+ {Sign::NEG, -136, 0x84a286be'b21d4b8c'779be241'ef4874a3_u128},
+ {Sign::NEG, -137, 0xfdbe771b'9d803cea'0e76a962'fa65ace3_u128},
+ {Sign::NEG, -137, 0xf237b2ae'f4e62e5a'd3d35627'464a5267_u128},
+ {Sign::NEG, -137, 0xe6b0c035'fa8b328c'162ef4b0'e838c363_u128},
+ {Sign::NEG, -137, 0xdb299faf'3e7cd74f'77bb10b9'76b3b9ca_u128},
+ {Sign::NEG, -137, 0xcfa25119'50b77014'209853ce'e70bc58b_u128},
+ {Sign::NEG, -137, 0xc41ad472'c12614d3'63f9b57c'baf2e58d_u128},
+ {Sign::NEG, -137, 0xb89329ba'1fa2a0fd'4fca1c93'1bd6e6d6_u128},
+ {Sign::NEG, -137, 0xad0b50ed'fbf5b265'26d26e43'4a53490a_u128},
+ {Sign::NEG, -137, 0xa1834a0c'e5d6a82d'c55e0790'78dc86a0_u128},
+ {Sign::NEG, -137, 0x95fb1515'6ceba1b5'f05b9d5b'd28f540b_u128},
+ {Sign::NEG, -137, 0x8a72b206'20c97d84'8ef87f1a'11cdb727_u128},
+ {Sign::NEG, -138, 0xfdd441bb'21e7b069'9d687011'4c1183cf_u128},
+ {Sign::NEG, -138, 0xe6c2c334'99ba16c4'63d514ff'f97e86f3_u128},
+ {Sign::NEG, -138, 0xcfb0e875'c7cc5929'11a38190'1eadd883_u128},
+ {Sign::NEG, -138, 0xb89eb17b'cabe1857'a9d69d37'bc0a5bac_u128},
+ {Sign::NEG, -138, 0xa18c1e43'c10c6898'2dc97c9f'fefd2497_u128},
+ {Sign::NEG, -138, 0x8a792eca'c911cf92'0dcdc8af'cb2ac09a_u128},
+ {Sign::NEG, -139, 0xe6cbc61c'020c8446'dd454eb3'a1489470_u128},
+ {Sign::NEG, -139, 0xb8a47615'0dfe4470'87803586'4d84b319_u128},
+ {Sign::NEG, -139, 0x8a7c6d7a'f1de7942'7ce595cc'53b8342c_u128},
+ {Sign::NEG, -140, 0xb8a7588f'd29b1baa'4710b590'49899141_u128},
+ {Sign::NEG, -141, 0xb8a8c9d8'be9ae994'5957f633'309d74e3_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -141, 0xb8abac81'ab576f3b'8268aba0'30b1adf6_u128},
+ {Sign::POS, -140, 0xb8ad1de1'ac9ea6a5'1511cba2'fb213a10_u128},
+ {Sign::POS, -139, 0x8a82eb77'08262500'6379fb9f'd9bc6235_u128},
+ {Sign::POS, -139, 0xb8b000b8'c65957cc'b6fe1bf6'01ee27d5_u128},
+ {Sign::POS, -139, 0xe6ddcebb'd72d3f7f'8c6e6069'3a14e6d0_u128},
+ {Sign::POS, -138, 0x8a862ac3'0095c084'e9bcfd0c'62eaa2ca_u128},
+ {Sign::POS, -138, 0xa19dca8e'85918b6d'73b21420'9a5234a7_u128},
+ {Sign::POS, -138, 0xb8b5c6c3'5e142a9b'347d4ca3'109fe4db_u128},
+ {Sign::POS, -138, 0xcfce1f64'6dca7745'37a62c48'783bb066_u128},
+ {Sign::POS, -138, 0xe6e6d474'9883fbe3'0794b643'7fb56344_u128},
+ {Sign::POS, -138, 0xfdffe5f6'c232f658'1cb9a45e'd90318e6_u128},
+ {Sign::POS, -137, 0x8a8ca9f6'e7762d0f'bc118e5d'bbef7dbc_u128},
+ {Sign::POS, -137, 0x96198f2e'5173e93b'b4c0fb95'35907cf8_u128},
+ {Sign::POS, -137, 0xa1a6a2a3'113fe246'c051d2c5'f00a9bb9_u128},
+ {Sign::POS, -137, 0xad33e456'9918a8d5'55326987'8c1e5110_u128},
+ {Sign::POS, -137, 0xb8c1544a'5b4e2caf'bc906750'b0ce372c_u128},
+ {Sign::POS, -137, 0xc44ef27f'ca41bdd8'4c50eaa6'3be294b6_u128},
+ {Sign::POS, -137, 0xcfdcbef8'58660da1'b6cb28db'8c065b44_u128},
+ {Sign::POS, -137, 0xdb6ab9b5'783f2fc5'70479336'830ceb05_u128},
+ {Sign::POS, -137, 0xe6f8e2b8'9c629b7a'2a458c83'1f6aeb49_u128},
+ {Sign::POS, -137, 0xf2873a03'37772c8a'6489ba5b'd391e206_u128},
+ {Sign::POS, -137, 0xfe15bf96'bc35246b'13f6fda5'10aeec3b_u128},
+ {Sign::POS, -136, 0x84d239ba'4eb315a9'2f9a0ef9'e8250836_u128},
+ {Sign::POS, -136, 0x8a99aacf'26f2a8a7'389019e8'22b70f1e_u128},
+ {Sign::POS, -136, 0x9061330a'a04f87ae'308beeff'a12cf669_u128},
+ {Sign::POS, -136, 0x9628d26d'7448a43f'9886a71b'25a2085d_u128},
+ {Sign::POS, -136, 0x9bf088f8'5c65a56b'70ba9ceb'e0b969c3_u128},
+ {Sign::POS, -136, 0xa1b856ac'1236e85b'cd855dc7'05ea2bea_u128},
+ {Sign::POS, -136, 0xa7803b89'4f5580e0'7736196b'11afb331_u128},
+ {Sign::POS, -136, 0xad483790'cd6339fa'94c99761'b8eab3d8_u128},
+ {Sign::POS, -136, 0xb3104ac3'460a9668'6194b8c0'40814736_u128},
+ {Sign::POS, -136, 0xb8d87521'72fed130'edde8d24'c7a999cc_u128},
+ {Sign::POS, -136, 0xbea0b6ac'0dfbde2f'ea6b01eb'de42f1d0_u128},
+ {Sign::POS, -136, 0xc4690f63'd0c66aa1'7ef732b6'9334cf50_u128},
+ {Sign::POS, -136, 0xca317f49'752bddae'2ba86275'fcfc2d72_u128},
+ {Sign::POS, -136, 0xcffa065d'b50258f6'b56ea44e'185bf99f_u128},
+ {Sign::POS, -136, 0xd5c2a4a1'4a28b920'1d5c3bbe'b6902bfe_u128},
+ {Sign::POS, -136, 0xdb8b5a14'ee86965f'a2f2bb9e'156b0f37_u128},
+ {Sign::POS, -136, 0xe15426b9'5c0c4506'd166eb8d'a06ab5ef_u128},
+ {Sign::POS, -136, 0xe71d0a8f'4cb2d60f'97dc7bae'4219de0f_u128},
+ {Sign::POS, -136, 0xece60597'7a7c17a8'6c9a8e76'98f416c4_u128},
+ {Sign::POS, -136, 0xf2af17d2'9f7295c0'7b3a20aa'5289695e_u128},
+ {Sign::POS, -136, 0xf8784141'75a99a93'ddcf578e'e2c2897b_u128},
+ {Sign::POS, -136, 0xfe4181e4'b73d2f37'e10ebd96'c3ec30ec_u128},
+ {Sign::POS, -135, 0x82056cde'8f290e13'a9b7baec'b34ba577_u128},
+ {Sign::POS, -135, 0x8430f56d'5e1edfd1'2da910dc'61c182da_u128},
+ {Sign::POS, -135, 0x8715b5a8'f27bed90'faca09dc'7e0ba8b5_u128},
+ {Sign::POS, -135, 0x89fa8180'19a2cace'0d723876'173c0947_u128},
+ {Sign::POS, -135, 0x8cdf58f3'30b64515'4e6651df'154e8f8c_u128},
+ {Sign::POS, -135, 0x8fc43c02'94dd8af3'ee54b77d'3bc34b6d_u128},
+ {Sign::POS, -135, 0x92a92aae'a3442c3d'ad07dde9'b5f92cce_u128},
+ {Sign::POS, -135, 0x958e24f7'b91a1a53'261aacf9'44b638f0_u128},
+ {Sign::POS, -135, 0x98732ade'3393a868'232f5d64'a85b219d_u128},
+ {Sign::POS, -135, 0x9b583c62'6fe98bc9'f3a958bb'706093fc_u128},
+ {Sign::POS, -135, 0x9e3d5984'cb58dc25'c9eaa059'e7b0333a_u128},
+ {Sign::POS, -135, 0xa1228245'a32313cf'1e154029'663243c0_u128},
+ {Sign::POS, -135, 0xa407b6a5'548e1006'16515200'e283d006_u128},
+ {Sign::POS, -135, 0xa6ecf6a4'3ce4113d'f498168a'3337ca4f_u128},
+ {Sign::POS, -135, 0xa9d24242'b973bb63'8a04a89f'0548a10f_u128},
+ {Sign::POS, -135, 0xacb79981'27901623'afaad01f'25772805_u128},
+ {Sign::POS, -135, 0xaf9cfc5f'e4908d31'c4f47950'543fe0b8_u128},
+ {Sign::POS, -135, 0xb2826adf'4dd0f08e'338655e6'77d0d3ec_u128},
+ {Sign::POS, -135, 0xb567e4ff'c0b174cc'f8ac2ce1'9d009541_u128},
+ {Sign::POS, -135, 0xb84d6ac1'9a96b35c'344d5e7d'd7b2f465_u128},
+ {Sign::POS, -135, 0xbb32fc25'38e9aaca'bd6a217f'b4598ec7_u128},
+ {Sign::POS, -135, 0xbe18992a'f917bf0e'bc21ff36'8f562b75_u128},
+ {Sign::POS, -135, 0xc0fe41d3'3892b9cc'4944139c'cbf2cb9a_u128},
+ {Sign::POS, -135, 0xc3e3f61e'54d0ca9c'1369970c'8b67e6b5_u128},
+ {Sign::POS, -135, 0xc6c9b60c'ab4c8752'099b370e'2d04a530_u128},
+ {Sign::POS, -135, 0xc9af819e'9984ec44'0b81c3d4'8aff589f_u128},
+ {Sign::POS, -135, 0xcc9558d4'7cfd5c90'9f22b809'93be311b_u128},
+ {Sign::POS, -135, 0xcf7b3bae'b33da265'ac29209c'8d8985ae_u128},
+ {Sign::POS, -135, 0xd2612a2d'99d1ef47'3cbb6a52'0292351d_u128},
+ {Sign::POS, -135, 0xd5472451'8e4adc56'43de9ae4'0507ef24_u128},
+ {Sign::POS, -135, 0xd82d2a1a'ee3d6a97'69677b90'2ea4df3a_u128},
+ {Sign::POS, -135, 0xdb133b8a'17430339'db7a3aff'74967bd5_u128},
+ {Sign::POS, -135, 0xddf9589f'66f977de'25990c82'a0066ac6_u128},
+ {Sign::POS, -135, 0xe0df815b'3b0302dd'0d424aac'f4babf55_u128},
+ {Sign::POS, -135, 0xe30c278d'9936c595'f8e3e7eb'5a7bdebb_u128},
+ {Sign::POS, -135, 0xe5f264ad'b62d5810'5ef8bf5a'df5deebe_u128},
+ {Sign::POS, -135, 0xe8d8ad75'590bdf92'331d1996'5368fc82_u128},
+ {Sign::POS, -135, 0xebbf01e4'df85219e'901c30c4'27e358b8_u128},
+ {Sign::POS, -135, 0xeea561fc'a7504dc1'aeac7e98'57253b06_u128},
+ {Sign::POS, -135, 0xf18bcdbd'0e28fdd7'e2113e58'93ab5b40_u128},
+ {Sign::POS, -135, 0xf4724526'71cf3654'9a4efc80'ae977826_u128},
+ {Sign::POS, -135, 0xf758c839'30076689'6bf3ba83'19332c9f_u128},
+ {Sign::POS, -135, 0xfa3f56f5'a69a68ed'1d732d30'2e75018b_u128},
+ {Sign::POS, -135, 0xfd25f15c'33558362'ba179c5d'bcceec01_u128},
+ {Sign::POS, -134, 0x80064bb6'9a0533c0'5543f53b'8ad85039_u128},
+ {Sign::POS, -134, 0x8179a494'8347996b'e971a556'5b93cb67_u128},
+ {Sign::POS, -134, 0x82ed0348'045f379d'5b399644'ba714691_u128},
+ {Sign::POS, -134, 0x846067d1'4c3b8982'5079f1e0'ec4b8496_u128},
+ {Sign::POS, -134, 0x85d3d230'89ce40b0'6aba4990'a32e8873_u128},
+ {Sign::POS, -134, 0x87474265'ec0b4548'e16770c3'a404291c_u128},
+ {Sign::POS, -134, 0x88bab871'a1e8b61c'1edb7ffb'1d6b3eab_u128},
+ {Sign::POS, -134, 0x8a2e3453'da5ee8cd'603243e1'ba7c7865_u128},
+ {Sign::POS, -134, 0x8ba1b60c'c46869f6'57ea5c03'ea4621dd_u128},
+ {Sign::POS, -134, 0x8d153d9c'8f01fd4a'd3534cbf'43bd7fd8_u128},
+ {Sign::POS, -134, 0x8e88cb03'692a9dbc'62c8c807'5dc91cd5_u128},
+ {Sign::POS, -134, 0x8ffc5e41'81e37d9e'04bb70a5'e3db7b85_u128},
+ {Sign::POS, -134, 0x916ff757'083006c7'd3875ba3'2159547a_u128},
+ {Sign::POS, -134, 0x9286adfc'a91ba28d'5c94c80e'7a8f66b1_u128},
+ {Sign::POS, -134, 0x93fa514b'a0517623'52d313c4'7b4f91db_u128},
+ {Sign::POS, -134, 0x956dfa72'866fc57d'80829e9f'3957a4c3_u128},
+ {Sign::POS, -134, 0x96e1a971'8a824be5'1cd49179'72015ae7_u128},
+ {Sign::POS, -134, 0x98555e48'db96fcd2'1af23c29'ef3032da_u128},
+ {Sign::POS, -134, 0x99c918f8'a8be040e'e7f7bf24'0be67b80_u128},
+ {Sign::POS, -134, 0x9b3cd981'2109c5dc'2bbe3cd4'f7d868fa_u128},
+ {Sign::POS, -134, 0x9cb09fe2'738edf14'8c75d6a4'c5ae460d_u128},
+ {Sign::POS, -134, 0x9e246c1c'cf642550'750fb989'c9a06186_u128},
+ {Sign::POS, -134, 0x9f983e30'63a2a709'de787e24'4901bdf9_u128},
+ {Sign::POS, -134, 0xa10c161d'5f65abc0'1ba3205f'f729efa4_u128},
+ {Sign::POS, -134, 0xa27ff3e3'f1cab41b'a864d2a0'38fb19cd_u128},
+ {Sign::POS, -134, 0xa3f3d784'49f17a11'fb21f083'a5fec56d_u128},
+ {Sign::POS, -134, 0xa567c0fe'96fbf109'594c5552'bcc377f5_u128},
+ {Sign::POS, -134, 0xa6dbb053'080e45fc'aeb35a35'3fc5a503_u128},
+ {Sign::POS, -134, 0xa84fa581'cc4edf9f'67a5c051'30c0f330_u128},
+ {Sign::POS, -134, 0xa9c3a08b'12e65e81'4de5cafd'e1caf46f_u128},
+ {Sign::POS, -134, 0xab37a16f'0aff9d32'686fce3d'160e88fd_u128},
+ {Sign::POS, -134, 0xacaba82d'e3c7b066'de1375b3'af6749a6_u128},
+ {Sign::POS, -134, 0xadc2b114'c632da56'24356904'8ac4affe_u128},
+ {Sign::POS, -134, 0xaf36c213'19b80ea2'd6796227'dcd39551_u128},
+ {Sign::POS, -134, 0xb0aad8ec'cfb38d51'abc92653'86172074_u128},
+ {Sign::POS, -134, 0xb21ef5a2'175ac65e'0caac9f1'7896f2ce_u128},
+ {Sign::POS, -134, 0xb3931833'1fe56492'1c65a3c7'f828972b_u128},
+ {Sign::POS, -134, 0xb50740a0'188d4daa'abdc6644'6a4286d9_u128},
+ {Sign::POS, -134, 0xb67b6ee9'308ea27b'2f3bbe8e'8d72abec_u128},
+ {Sign::POS, -134, 0xb7efa30e'9727bf11'b67dbdd7'f03d168c_u128},
+ },
+ // -log2(r) for the third step, generated by SageMath with:
+ //
+ // for i in range(-80, 81):
+ // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
+ // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
+ // print("{Sign::NEG," if (s == 1) else "{Sign::POS,", e, ",
+ // format_hex(m), "},");
+ /* .step_3 = */
+ {
+ {Sign::NEG, -142, 0xe6d3a96b'978fc16e'26f2c63c'0827ccbb_u128},
+ {Sign::NEG, -142, 0xe3f107a9'fbfc50ca'4b56fe66'7c8ec091_u128},
+ {Sign::NEG, -142, 0xe10e65d1'4b937265'647d7618'1aec10fc_u128},
+ {Sign::NEG, -142, 0xde2bc3e1'8653b4f5'99e8f4d5'379eca79_u128},
+ {Sign::NEG, -142, 0xdb4921da'ac3ba730'f07da899'90c20623_u128},
+ {Sign::NEG, -142, 0xd8667fbc'bd49d7cd'4a812184'8531851a_u128},
+ {Sign::NEG, -142, 0xd583dd87'b97cd580'679a4d85'4ae13619_u128},
+ {Sign::NEG, -142, 0xd2a13b3b'a0d32eff'e4d17407'2487a514_u128},
+ {Sign::NEG, -142, 0xcfbe98d8'734b7301'3c90319d'969b54be_u128},
+ {Sign::NEG, -142, 0xccdbf65e'30e43039'c6a173b0'9ba301e6_u128},
+ {Sign::NEG, -142, 0xc9f953cc'd99bf55e'b8317428'd7d8d06b_u128},
+ {Sign::NEG, -142, 0xc716b124'6d715125'23cdb51b'cc2061cd_u128},
+ {Sign::NEG, -142, 0xc4340e64'ec62d241'f964fc78'084fd515_u128},
+ {Sign::NEG, -142, 0xc1516b8e'566f076a'06474fb1'5ccbb015_u128},
+ {Sign::NEG, -142, 0xbe6ec8a0'ab947f51'f525ef6d'0b75b1c3_u128},
+ {Sign::NEG, -142, 0xbb8c259b'ebd1c8ae'4e13532d'f7ee8da7_u128},
+ {Sign::NEG, -142, 0xb8a98280'17257233'76832500'd72a9027_u128},
+ {Sign::NEG, -142, 0xb5c6df4d'2d8e0a95'b14a3d28'5e592ba0_u128},
+ {Sign::NEG, -142, 0xb2e43c03'2f0a2089'1e9e9dc9'711f6e20_u128},
+ {Sign::NEG, -142, 0xb00198a2'1b9842c1'bc176e97'4f255fac_u128},
+ {Sign::NEG, -142, 0xad1ef529'f336fff3'64acf87f'c0f648e6_u128},
+ {Sign::NEG, -142, 0xaa3c519a'b5e4e6d1'd0b8a157'4433e1f8_u128},
+ {Sign::NEG, -142, 0xa759adf4'63a08610'95f4e785'371c69a9_u128},
+ {Sign::NEG, -142, 0xa4770a36'fc686c63'277d5db0'0363a46f_u128},
+ {Sign::NEG, -142, 0xa1946662'803b287c'd5cea669'485ec36c_u128},
+ {Sign::NEG, -142, 0x9eb1c276'ef174910'cec66fda'04833322_u128},
+ {Sign::NEG, -142, 0x9bcf1e74'48fb5cd2'1da36f6e'be3851db_u128},
+ {Sign::NEG, -142, 0x98ec7a5a'8de5f273'ab055d83'abfc0d82_u128},
+ {Sign::NEG, -142, 0x9609d629'bdd598a8'3cecf110'dbda68e9_u128},
+ {Sign::NEG, -142, 0x932731e1'd8c8de22'76bbdb56'5a37e84b_u128},
+ {Sign::NEG, -142, 0x90448d82'debe5194'd934c388'57eee4f3_u128},
+ {Sign::NEG, -142, 0x8d61e90c'cfb481b1'c27b427b'4fbfc7db_u128},
+ {Sign::NEG, -142, 0x8a7f447f'aba9fd2b'6e13de50'2b142b39_u128},
+ {Sign::NEG, -142, 0x879c9fdb'729d52b3'f4e40620'6614e2ba_u128},
+ {Sign::NEG, -142, 0x84b9fb20'248d10fd'4d320daa'3312ea6c_u128},
+ {Sign::NEG, -142, 0x81d7564d'c177c6b9'4aa528fc'9d433c1a_u128},
+ {Sign::NEG, -143, 0xfde962c8'92b80533'3c8ad047'559b1622_u128},
+ {Sign::NEG, -143, 0xf82418c7'7870a69f'acf765a8'fc5bcc31_u128},
+ {Sign::NEG, -143, 0xf25ece98'34168f1a'be238832'edd27f20_u128},
+ {Sign::NEG, -143, 0xec99843a'c5a6dc07'02644bfc'a329b708_u128},
+ {Sign::NEG, -143, 0xe6d439af'2d1eaac6'c6d05a78'8e614744_u128},
+ {Sign::NEG, -143, 0xe10eeef5'6a7b18bc'133fe9cc'57a8c1d0_u128},
+ {Sign::NEG, -143, 0xdb49a40d'7db94348'aa4cb429'195fb5dd_u128},
+ {Sign::NEG, -143, 0xd58458f7'66d647ce'0951ef23'9abbb959_u128},
+ {Sign::NEG, -143, 0xcfbf0db3'25cf43ad'686c430c'89143d35_u128},
+ {Sign::NEG, -143, 0xc9f9c240'baa15447'ba79c248'afd42c12_u128},
+ {Sign::NEG, -143, 0xc43476a0'254996fd'ad19e0a9'2f115327_u128},
+ {Sign::NEG, -143, 0xbe6f2ad1'65c5292f'a8ad6ac3'b0c99520_u128},
+ {Sign::NEG, -143, 0xb8a9ded4'7c11283d'd0567d4a'9cc5e6a1_u128},
+ {Sign::NEG, -143, 0xb2e492a9'682ab188'01f87c65'4b231443_u128},
+ {Sign::NEG, -143, 0xad1f4650'2a0ee26d'd6380b08'358051bc_u128},
+ {Sign::NEG, -143, 0xa759f9c8'c1bad84e'a07b024d'26d391f6_u128},
+ {Sign::NEG, -143, 0xa194ad13'2f2bb089'6ee868cb'69e3a7d8_u128},
+ {Sign::NEG, -143, 0x9bcf602f'725e887d'0a6869ef'f6682f73_u128},
+ {Sign::NEG, -143, 0x960a131d'8b507d87'f6a44d55'9ccf3f61_u128},
+ {Sign::NEG, -143, 0x9044c5dd'79fead08'72066e1d'30a8e210_u128},
+ {Sign::NEG, -143, 0x8a7f786f'3e66345c'75ba3245'b1b856af_u128},
+ {Sign::NEG, -143, 0x84ba2ad2'd88430e1'b5ac0204'73ab198f_u128},
+ {Sign::NEG, -144, 0xfde9ba10'90ab7feb'41127e3a'88eb6741_u128},
+ {Sign::NEG, -144, 0xf25f1e1f'1baffdea'bf807875'22aca1c4_u128},
+ {Sign::NEG, -144, 0xe6d481d1'5210167b'af00688b'14fa3adc_u128},
+ {Sign::NEG, -144, 0xdb49e527'33c60457'4d72837c'8ab4d1e5_u128},
+ {Sign::NEG, -144, 0xcfbf4820'c0cc0236'4e38ac27'bb252090_u128},
+ {Sign::NEG, -144, 0xc434aabd'f91c4ad0'da3661f9'292f59e8_u128},
+ {Sign::NEG, -144, 0xb8aa0cfe'dcb118de'8fd0af9b'dfd21488_u128},
+ {Sign::NEG, -144, 0xad1f6ee3'6b84a716'82ee19a9'abf0bfa5_u128},
+ {Sign::NEG, -144, 0xa194d06b'a591302f'3cf68d5b'5369a251_u128},
+ {Sign::NEG, -144, 0x960a3197'8ad0eede'bcd34f38'c977647e_u128},
+ {Sign::NEG, -144, 0x8a7f9267'1b3e1dda'76eee9c9'605e2143_u128},
+ {Sign::NEG, -145, 0xfde9e5b4'ada5efae'aa6a3887'f0c803ab_u128},
+ {Sign::NEG, -145, 0xe6d4a5e2'7b136f13'6e25927e'582ac191_u128},
+ {Sign::NEG, -145, 0xcfbf6557'9eb92f4a'e2ebcac2'f3a8e9eb_u128},
+ {Sign::NEG, -145, 0xb8aa2414'188ba5bb'9d9acc22'd5690751_u128},
+ {Sign::NEG, -145, 0xa194e217'e87f47cb'1e12604b'6d4132ef_u128},
+ {Sign::NEG, -145, 0x8a7f9f63'0e888add'cf340d2a'cb9b92a9_u128},
+ {Sign::NEG, -146, 0xe6d4b7eb'1537c8ae'0dc5e49f'bde3c520_u128},
+ {Sign::NEG, -146, 0xb8aa2f9e'b95b9332'0c074c95'57c01188_u128},
+ {Sign::NEG, -146, 0x8a7fa5e1'09656009'f0f82818'ff9b654f_u128},
+ {Sign::NEG, -147, 0xb8aa3564'0a7c33eb'd4cd6120'78bbe9b0_u128},
+ {Sign::NEG, -148, 0xb8aa3846'b33aaecf'f08cf68f'42e09fa0_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -148, 0xb8aa3e0c'0513f9b1'68bd0fac'df0ddaaf_u128},
+ {Sign::POS, -147, 0xb8aa40ee'ae2ec9b3'192af653'dd41575b_u128},
+ {Sign::POS, -146, 0x8a7fb2dd'018e4892'3b5c8984'2e540a51_u128},
+ {Sign::POS, -146, 0xb8aa46b4'00c0bee3'34ad8ebd'd8b2750c_u128},
+ {Sign::POS, -146, 0xe6d4dbfc'54c5dd1b'70b12bd6'98e5be74_u128},
+ {Sign::POS, -145, 0x8a7fb95a'feda5c46'08c7e424'efbd90e1_u128},
+ {Sign::POS, -145, 0xa1950570'7dd23344'31b8eba7'74a1de77_u128},
+ {Sign::POS, -145, 0xb8aa523e'a755fe32'ee400e8c'68838733_u128},
+ {Sign::POS, -145, 0xcfbf9fc5'7b7147be'0e71fa0b'5603bc2f_u128},
+ {Sign::POS, -145, 0xe6d4ee04'fa2f9a92'7763c919'd8ac65f1_u128},
+ {Sign::POS, -145, 0xfdea3cfd'239c815e'232b270b'b6046ec1_u128},
+ {Sign::POS, -144, 0x8a7fc656'fbe1c368'106f3919'7e068972_u128},
+ {Sign::POS, -144, 0x960a6e8b'bb581acc'4a4a6f40'12941bd9_u128},
+ {Sign::POS, -144, 0xa195171c'd0370c34'5bb34c11'20b3e54b_u128},
+ {Sign::POS, -144, 0xad1fc00a'3a845cf9'6bb67313'92a3147a_u128},
+ {Sign::POS, -144, 0xb8aa6953'fa45d275'2be1268d'cee3c8fc_u128},
+ {Sign::POS, -144, 0xc43512fa'0f813201'd84158d5'd50251a9_u128},
+ {Sign::POS, -144, 0xcfbfbcfc'7a3c40fa'3765bda1'5d0ef0fa_u128},
+ {Sign::POS, -144, 0xdb4a675b'3a7cc4b9'9a5ddb55'f9cc27d9_u128},
+ {Sign::POS, -144, 0xe6d51216'5048829b'dcba1c59'3d918775_u128},
+ {Sign::POS, -144, 0xf25fbd2d'bba53ffd'648be060'e1e30a95_u128},
+ {Sign::POS, -144, 0xfdea68a1'7c98c23b'22658dc2'f1bcf6e8_u128},
+ {Sign::POS, -143, 0x84ba8a38'c9946759'48ad5162'fb4a236e_u128},
+ {Sign::POS, -143, 0x8a7fe04e'ffad9560'db7fe378'9405ce3a_u128},
+ {Sign::POS, -143, 0x90453693'609acde3'91b56e2e'4f2e5ed8_u128},
+ {Sign::POS, -143, 0x960a8d05'ec5ef390'f8998880'c3bb4d76_u128},
+ {Sign::POS, -143, 0x9bcfe3a6'a2fce918'e2b87805'2f67efee_u128},
+ {Sign::POS, -143, 0xa1953a75'8477912b'67df3991'93f707c0_u128},
+ {Sign::POS, -143, 0xa75a9172'90d1ce78'e51b89e4'd5d095e1_u128},
+ {Sign::POS, -143, 0xad1fe89d'c80e83b1'fcbbee4e'dbf9f47d_u128},
+ {Sign::POS, -143, 0xb2e53ff7'2a309387'964fbd58'b168371b_u128},
+ {Sign::POS, -143, 0xb8aa977e'b73ae0aa'dea7276c'a7acd135_u128},
+ {Sign::POS, -143, 0xbe6fef34'6f304dcd'47d33f7e'7afc83a6_u128},
+ {Sign::POS, -143, 0xc4354718'5213bda0'892603b3'77909123_u128},
+ {Sign::POS, -143, 0xc9fa9f2a'5fe812d6'9f32660a'a06239fb_u128},
+ {Sign::POS, -143, 0xcfbff76a'98b03021'cbcc5504'd7407f6c_u128},
+ {Sign::POS, -143, 0xd5854fd8'fc6ef834'9608c44d'06402ebe_u128},
+ {Sign::POS, -143, 0xdb4aa875'8b274dc1'ca3db560'4a863477_u128},
+ {Sign::POS, -143, 0xe1100140'44dc137c'7a024036'206c37d6_u128},
+ {Sign::POS, -143, 0xe6d55a39'29902c17'fc2e9be8'90ff7ee3_u128},
+ {Sign::POS, -143, 0xec9ab360'39467a47'ecdc275c'60da1b53_u128},
+ {Sign::POS, -143, 0xf2600cb5'7401e0c0'2d6571e9'4056607f_u128},
+ {Sign::POS, -143, 0xf8256638'd9c54234'e4664401'fd1ca2a7_u128},
+ {Sign::POS, -143, 0xfdeabfea'6a93815a'7dbba7dc'b50b3fd7_u128},
+ {Sign::POS, -142, 0x81d80ce5'1337c072'd541f90d'853c794b_u128},
+ {Sign::POS, -142, 0x84bab9ec'06ae11c5'b08f6539'2ce8b75b_u128},
+ {Sign::POS, -142, 0x879d670a'0fae2600'6e969a29'f8462436_u128},
+ {Sign::POS, -142, 0x8a80143f'2e396e7d'cfc8cbca'a2bf130c_u128},
+ {Sign::POS, -142, 0x8d62c18b'62515c98'b737e48c'19421e68_u128},
+ {Sign::POS, -142, 0x90456eee'abf761ac'2a9689b9'97c50c0b_u128},
+ {Sign::POS, -142, 0x93281c69'0b2cef13'52381fcc'c774d66b_u128},
+ {Sign::POS, -142, 0x960ac9fa'7ff37629'7910cec1'dd92dc10_u128},
+ {Sign::POS, -142, 0x98ed77a3'0a4c684a'0cb5866b'baff34cb_u128},
+ {Sign::POS, -142, 0x9bd02562'aa3936d0'9d5c02c8'0c702d11_u128},
+ {Sign::POS, -142, 0x9eb2d339'5fbb5318'dddad053'6b56e775_u128},
+ {Sign::POS, -142, 0xa1958127'2ad42e7e'a3a9505d'7f71247a_u128},
+ {Sign::POS, -142, 0xa4782f2c'0b853a5d'e6dfbd5d'210830d7_u128},
+ {Sign::POS, -142, 0xa75add48'01cfe812'c2372f44'7bdcfa45_u128},
+ {Sign::POS, -142, 0xaa3d8b7b'0db5a8f9'73099fd5'32c14b05_u128},
+ {Sign::POS, -142, 0xad2039c5'2f37ee6e'5951eef4'83de2c37_u128},
+ {Sign::POS, -142, 0xb002e826'665829cd'f7abe6ff'6da76f1e_u128},
+ {Sign::POS, -142, 0xb2e5969e'b317cc74'f354411e'd47c5d7b_u128},
+ {Sign::POS, -142, 0xb5c8452e'157847c0'1428a99b'a8f5911f_u128},
+ {Sign::POS, -142, 0xb8aaf3d4'8d7b0d0c'44a7c433'0edff2c8_u128},
+ {Sign::POS, -142, 0xbb8da292'1b218db6'91f1306a'84e4e07b_u128},
+ {Sign::POS, -142, 0xbe705166'be6d3b1c'2bc58de4'0cdf7b6a_u128},
+ {Sign::POS, -142, 0xc1530052'775f869a'648680b2'54df1d99_u128},
+ {Sign::POS, -142, 0xc435af55'45f9e18e'b136b5ac'e0d6f74d_u128},
+ {Sign::POS, -142, 0xc7185e6f'2a3dbd56'a979e6c4'34fad480_u128},
+ {Sign::POS, -142, 0xc9fb0da0'242c8b50'0794df56'00c90a5a_u128},
+ {Sign::POS, -142, 0xccddbce8'33c7bcd8'a86d8081'4ac18cf1_u128},
+ {Sign::POS, -142, 0xcfc06c47'5910c34e'8b8ac57a'9cca2d56_u128},
+ {Sign::POS, -142, 0xd2a31bbd'9409100f'd314c7e0'3140001f_u128},
+ {Sign::POS, -142, 0xd585cb4a'e4b2147a'c3d4c40e'20b5ec89_u128},
+ {Sign::POS, -142, 0xd8687aef'4b0d41ed'c5351d72'9060644e_u128},
+ {Sign::POS, -142, 0xdb4b2aaa'c71c09c7'614162e1'e12e445d_u128},
+ {Sign::POS, -142, 0xde2dda7d'58dfdd66'44a652ea'df8ede85_u128},
+ {Sign::POS, -142, 0xe1108a67'005a2e29'3eb1e02a'f3e52c3c_u128},
+ {Sign::POS, -142, 0xe3f33a67'bd8c6d6f'415335a2'53a82aa2_u128},
+ {Sign::POS, -142, 0xe6d5ea7f'90780c97'611abb08'33305fe1_u128},
+ },
+ // -log2(r) for the fourth step, generated by SageMath with:
+ //
+ // for i in range(-65, 65):
+ // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) );
+ // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
+ // print("{Sign::NEG," if (s == 1) else "{Sign::POS,", e, ",
+ // format_hex(m), "},");
+ /* .step_4 = */
+ {
+ {Sign::NEG, -149, 0xbb8ce299'0b5d0b90'ef1bffe5'65ce0a46_u128},
+ {Sign::NEG, -149, 0xb8aa39b8'07a576e4'bea32445'60ca3d99_u128},
+ {Sign::NEG, -149, 0xb5c790d6'd5c354df'8b91f71c'eefa31a2_u128},
+ {Sign::NEG, -149, 0xb2e4e7f5'75b6a57b'9096e3d6'84001c0e_u128},
+ {Sign::NEG, -149, 0xb0023f13'e77f68b3'086054c7'94367f36_u128},
+ {Sign::NEG, -149, 0xad1f9632'2b1d9e80'2d9cb330'94afe4de_u128},
+ {Sign::NEG, -149, 0xaa3ced50'409146dd'3afa673c'fb3698f3_u128},
+ {Sign::NEG, -149, 0xa75a446e'27da61c4'6b27d803'3e4c6450_u128},
+ {Sign::NEG, -149, 0xa4779b8b'e0f8ef2f'f8d36b84'd52a477b_u128},
+ {Sign::NEG, -149, 0xa194f2a9'6becef1a'1eab86ae'37c03565_u128},
+ {Sign::NEG, -149, 0x9eb249c6'c8b6617d'175e8d56'deb4ce2c_u128},
+ {Sign::NEG, -149, 0x9bcfa0e3'f7554653'1d9ae241'436519da_u128},
+ {Sign::NEG, -149, 0x98ecf800'f7c99d96'6c0ee71a'dfe44325_u128},
+ {Sign::NEG, -149, 0x960a4f1d'ca136741'3d68fc7c'2efb522f_u128},
+ {Sign::NEG, -149, 0x9327a63a'6e32a34d'cc5781e8'ac28e749_u128},
+ {Sign::NEG, -149, 0x9044fd56'e42751b6'5388d5ce'd3a0f5af_u128},
+ {Sign::NEG, -149, 0x8d625473'2bf17275'0dab5588'224c7e4a_u128},
+ {Sign::NEG, -149, 0x8a7fab8f'45910584'356d5d59'15c94a70_u128},
+ {Sign::NEG, -149, 0x879d02ab'31060ade'057d4871'2c69a6a7_u128},
+ {Sign::NEG, -149, 0x84ba59c6'ee50827c'b88970ea'e5341d60_u128},
+ {Sign::NEG, -149, 0x81d7b0e2'7d706c5a'89402fcb'bfe331bb_u128},
+ {Sign::NEG, -150, 0xfdea0ffb'bccb90e3'649fba08'79ca348b_u128},
+ {Sign::NEG, -150, 0xf824be32'22612d78'dccd9edf'bab6f777_u128},
+ {Sign::NEG, -150, 0xf25f6c68'2ba1ae69'f066b9aa'4636478e_u128},
+ {Sign::NEG, -150, 0xec9a1a9d'd88d13ab'14c7b3cb'21578781_u128},
+ {Sign::NEG, -150, 0xe6d4c8d3'29235d30'bf4d347b'528f56e1_u128},
+ {Sign::NEG, -150, 0xe10f7708'1d648aef'6553e0c9'e1b70799_u128},
+ {Sign::NEG, -150, 0xdb4a253c'b5509cdb'7c385b9b'd80c1375_u128},
+ {Sign::NEG, -150, 0xd584d370'f0e792e9'795745ac'402f919d_u128},
+ {Sign::NEG, -150, 0xcfbf81a4'd0296d0d'd20d3d8c'2625ac1b_u128},
+ {Sign::NEG, -150, 0xc9fa2fd8'53162b3c'fbb6dfa2'97551554_u128},
+ {Sign::NEG, -150, 0xc434de0b'79adcd6b'6bb0c62c'a2867d91_u128},
+ {Sign::NEG, -150, 0xbe6f8c3e'43f0538d'9757893d'57e40877_u128},
+ {Sign::NEG, -150, 0xb8aa3a70'b1ddbd97'f407bebd'c8f8c28e_u128},
+ {Sign::NEG, -150, 0xb2e4e8a2'c3760b7e'f71dfa6d'08b016be_u128},
+ {Sign::NEG, -150, 0xad1f96d4'78b93d37'15f6cde0'2b5543ce_u128},
+ {Sign::NEG, -150, 0xa75a4505'd1a752b4'c5eec882'4692d1e9_u128},
+ {Sign::NEG, -150, 0xa194f336'ce404bec'7c627794'7172081a_u128},
+ {Sign::NEG, -150, 0x9bcfa167'6e8428d2'aeae662d'c45a61ce_u128},
+ {Sign::NEG, -150, 0x960a4f97'b272e95b'd22f1d3b'59110455_u128},
+ {Sign::NEG, -150, 0x9044fdc7'9a0c8d7c'5c412380'4ab83462_u128},
+ {Sign::NEG, -150, 0x8a7fabf7'25511528'c240fd95'b5cecb89_u128},
+ {Sign::NEG, -150, 0x84ba5a26'54408055'798b2dea'b82fadc4_u128},
+ {Sign::NEG, -151, 0xfdea10aa'4db59ded'eef86988'e2227ddb_u128},
+ {Sign::NEG, -151, 0xf25f6d07'3a400203'62e1207c'0209b090_u128},
+ {Sign::NEG, -151, 0xe6d4c963'6e202cd4'39897891'13ec7bee_u128},
+ {Sign::NEG, -151, 0xdb4a25be'e9561e49'5daa6556'5e562909_u128},
+ {Sign::NEG, -151, 0xcfbf8219'abe1d64b'b9fcd606'2a84acbd_u128},
+ {Sign::NEG, -151, 0xc434de73'b5c354c4'3939b586'c46792b3_u128},
+ {Sign::NEG, -151, 0xb8aa3acd'06fa999b'c619ea6a'7a9ee85e_u128},
+ {Sign::NEG, -151, 0xad1f9725'9f87a4bb'4b5656ef'9e7a27fd_u128},
+ {Sign::NEG, -151, 0xa194f37d'7f6a760b'b3a7d900'83f7239c_u128},
+ {Sign::NEG, -151, 0x960a4fd4'a6a30d75'e9c74a33'81c0f016_u128},
+ {Sign::NEG, -151, 0x8a7fac2b'15316ae2'd86d7fca'f12ed012_u128},
+ {Sign::NEG, -152, 0xfdea1101'962b1c76'd4a6956a'5c863e0f_u128},
+ {Sign::NEG, -152, 0xe6d4c9ab'909eeed1'1462ef19'2f547877_u128},
+ {Sign::NEG, -152, 0xcfbf8254'19be4ca6'45819d2f'1d72eb8b_u128},
+ {Sign::NEG, -152, 0xb8aa3afb'318935c8'3d742790'eedbe719_u128},
+ {Sign::NEG, -152, 0xa194f3a0'd7ffaa08'd1ac0d7b'70d74492_u128},
+ {Sign::NEG, -152, 0x8a7fac45'0d21a939'd79ac583'75f83d0c_u128},
+ {Sign::NEG, -153, 0xe6d4c9cf'a1de665a'49637b2b'ac367e87_u128},
+ {Sign::NEG, -153, 0xb8aa3b12'46d08f69'1cc4b5ee'dcc78b35_u128},
+ {Sign::NEG, -153, 0x8a7fac52'0919cd43'd43bf48a'42745836_u128},
+ {Sign::NEG, -154, 0xb8aa3b1d'd1743f1c'3557bdcf'592619eb_u128},
+ {Sign::NEG, -155, 0xb8aa3b23'96c617ae'6bdc2e83'd3ebb0c4_u128},
+ {Sign::POS, 0, 0_u128},
+ {Sign::POS, -155, 0xb8aa3b2f'2169ca44'2d5b4005'0e44e8ab_u128},
+ {Sign::POS, -154, 0xb8aa3b34'e6bba447'b8560371'b8f04afe_u128},
+ {Sign::POS, -153, 0x8a7fac6c'010a1f14'c79a43cc'c70459cc_u128},
+ {Sign::POS, -153, 0xb8aa3b40'715f59c0'22c25632'f519f77f_u128},
+ {Sign::POS, -153, 0xe6d4ca17'c45d8282'42c10a31'4e35fb9e_u128},
+ {Sign::POS, -152, 0x8a7fac78'fd024cdb'be5a212e'd7b949e4_u128},
+ {Sign::POS, -152, 0xa194f3e7'892a4fde'12dcf94e'f5c5b918_u128},
+ {Sign::POS, -152, 0xb8aa3b57'86a6ca76'49781013'e57110ce_u128},
+ {Sign::POS, -152, 0xcfbf82c8'f577bcd2'8cba70c0'85c12cb3_u128},
+ {Sign::POS, -152, 0xe6d4ca3b'd59d2721'07332f3f'b09328b8_u128},
+ {Sign::POS, -152, 0xfdea11b0'2717098f'e3716824'3a9d8b14_u128},
+ {Sign::POS, -151, 0x8a7fac92'f4f2b226'a6022054'79b93722_u128},
+ {Sign::POS, -151, 0x960a504e'8f041bc3'b5bd7358'52c0d583_u128},
+ {Sign::POS, -151, 0xa194f40a'e1bfc1b6'36324863'0b0d812d_u128},
+ {Sign::POS, -151, 0xad1f97c7'ed25a415'3ca83f0e'02b823c0_u128},
+ {Sign::POS, -151, 0xb8aa3b85'b135c2f7'de66fb46'974bc4fd_u128},
+ {Sign::POS, -151, 0xc434df44'2df01e75'30b6254e'23c69fc2_u128},
+ {Sign::POS, -151, 0xcfbf8303'6354b6a4'48dd69ba'009b370c_u128},
+ {Sign::POS, -151, 0xdb4a26c3'51638b9c'3c247973'83b16af5_u128},
+ {Sign::POS, -151, 0xe6d4ca83'f81c9d74'1fd309b8'00678db7_u128},
+ {Sign::POS, -151, 0xf25f6e45'577fec43'0930d418'c79378a3_u128},
+ {Sign::POS, -151, 0xfdea1207'6f8d7820'0d85967b'2783a12c_u128},
+ {Sign::POS, -150, 0x84ba5ae5'2022a091'210c898c'360016ed_u128},
+ {Sign::POS, -150, 0x8a7facc6'e4d3a3b0'5e19883e'ef2605ab_u128},
+ {Sign::POS, -150, 0x9044fea9'05d9c579'488dacc6'629300ae_u128},
+ {Sign::POS, -150, 0x960a508b'833505f7'6b0cdebd'3264e3e3_u128},
+ {Sign::POS, -150, 0x9bcfa26e'5ce56536'503b07e7'ff788dc2_u128},
+ {Sign::POS, -150, 0xa194f451'92eae341'82bc1435'696a69d1_u128},
+ {Sign::POS, -150, 0xa75a4635'25458024'8d33f1be'0e96fb1f_u128},
+ {Sign::POS, -150, 0xad1f9819'13f53bea'fa4690c4'8c1b66c9_u128},
+ {Sign::POS, -150, 0xb2e4e9fd'5efa16a0'5497e3b5'7dd5fe75_u128},
+ {Sign::POS, -150, 0xb8aa3be2'06541050'26cbdf27'7e66cad5_u128},
+ {Sign::POS, -150, 0xbe6f8dc7'0a032905'fb8679db'27301625_u128},
+ {Sign::POS, -150, 0xc434dfac'6a0760cd'5d6bacbb'1056f6aa_u128},
+ {Sign::POS, -150, 0xc9fa3192'2660b7b1'd71f72db'd0c3d936_u128},
+ {Sign::POS, -150, 0xcfbf8378'3f0f2dbe'f345c97b'fe230ba2_u128},
+ {Sign::POS, -150, 0xd584d55e'b412c300'3c82b004'2ce54751_u128},
+ {Sign::POS, -150, 0xdb4a2745'856b7781'3d7a2806'f0403bae_u128},
+ {Sign::POS, -150, 0xe10f792c'b3194b4d'80d03540'da2f18ae_u128},
+ {Sign::POS, -150, 0xe6d4cb14'3d1c3e70'9128dd98'7b73194f_u128},
+ {Sign::POS, -150, 0xec9a1cfc'237450f5'f928291e'63940e14_u128},
+ {Sign::POS, -150, 0xf25f6ee4'662182e9'4372220d'20e0e78a_u128},
+ {Sign::POS, -150, 0xf824c0cd'0523d455'faaad4c9'407040c7_u128},
+ {Sign::POS, -150, 0xfdea12b6'007b4547'a9764fe1'4e20e9e4_u128},
+ {Sign::POS, -149, 0x81d7b24f'ac13eae4'ed3c5206'ea4d3942_u128},
+ {Sign::POS, -149, 0x84ba5b44'8614c2f4'0c2af218'aea6da27_u128},
+ {Sign::POS, -149, 0x879d0439'8e402ad6'f6d912ac'383aaeba_u128},
+ {Sign::POS, -149, 0x8a7fad2e'c4962293'7298bf5c'ca8b3d95_u128},
+ {Sign::POS, -149, 0x8d625624'2916aa2f'44bc04da'a8808214_u128},
+ {Sign::POS, -149, 0x9044ff19'bbc1c1b0'3294f0eb'14683198_u128},
+ {Sign::POS, -149, 0x9327a80f'7c97691c'01759268'4ff600c3_u128},
+ {Sign::POS, -149, 0x960a5105'6b97a078'76aff941'9c43e8b9_u128},
+ {Sign::POS, -149, 0x98ecf9fb'88c267cb'5796367b'39d26c63_u128},
+ {Sign::POS, -149, 0x9bcfa2f1'd417bf1a'697a5c2e'6888ddaa_u128},
+ {Sign::POS, -149, 0x9eb24be8'4d97a66b'71ae7d89'67b5a2b7_u128},
+ {Sign::POS, -149, 0xa194f4de'f5421dc4'3584aecf'760e7b39_u128},
+ {Sign::POS, -149, 0xa4779dd5'cb17252a'7a4f0558'd1b0c59e_u128},
+ {Sign::POS, -149, 0xa75a46cc'cf16bca4'055f9792'b821c455_u128},
+ {Sign::POS, -149, 0xaa3cefc4'0140e436'9c087cff'664ee311_u128},
+ {Sign::POS, -149, 0xad1f98bb'61959be8'039bce36'188dfc04_u128},
+ {Sign::POS, -149, 0xb00241b2'f014e3be'016ba4e3'0a9d9d21_u128},
+ {Sign::POS, -149, 0xb2e4eaaa'acbebbbe'5aca1bc7'77a54d5e_u128},
+ {Sign::POS, -149, 0xb5c793a2'979323ee'd5094eb9'9a35d1f0_u128},
+ {Sign::POS, -149, 0xb8aa3c9a'b0921c55'357b5aa4'ac49738d_u128},
+ }};
+
+// > P = fpminimax(log2(1 + x)/x, 3, [|128...|], [-0x1.0002143p-29 , 0x1p-29]);
+// > P;
+// > dirtyinfnorm(log2(1 + x)/x - P, [-0x1.0002143p-29 , 0x1p-29]);
+// 0x1.27ad5...p-121
+LIBC_INLINE_VAR constexpr Float128 BIG_COEFFS[4]{
+ {Sign::NEG, -129, 0xb8aa3b29'5c2b21e3'3eccf694'0d66bbcc_u128},
+ {Sign::POS, -129, 0xf6384ee1'd01febc9'ee39a6d6'49394bb1_u128},
+ {Sign::NEG, -128, 0xb8aa3b29'5c17f0bb'be87fed0'67ea2ad5_u128},
+ {Sign::POS, -127, 0xb8aa3b29'5c17f0bb'be87fed0'691d3e3f_u128},
+};
+
+// Reuse the output of the fast pass range reduction.
+// -2^-8 <= m_x < 2^-7
+LIBC_INLINE static double log2_accurate(int e_x, int index, double m_x) {
+
+ Float128 sum(static_cast<float>(e_x));
+ sum = fputil::quick_add(sum, LOG2_TABLE.step_1[index]);
+
+ Float128 v_f128 = log_range_reduction(m_x, LOG2_TABLE, sum);
+
+ // Polynomial approximation
+ Float128 p = fputil::quick_mul(v_f128, BIG_COEFFS[0]);
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[1]));
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[2]));
+ p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[3]));
+
+ Float128 r = fputil::quick_add(sum, p);
+
+ return static_cast<double>(r);
+}
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace log2_internal
+
+LIBC_INLINE static double log2(double x) {
+ using namespace log2_internal;
+ using namespace common_constants_internal;
+ using FPBits_t = typename fputil::FPBits<double>;
+
+ FPBits_t xbits(x);
+ uint64_t x_u = xbits.uintval();
+
+ int x_e = -FPBits_t::EXP_BIAS;
+
+ if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
+ // log2(1.0) = +0.0
+ return 0.0;
+ }
+
+ if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
+ xbits.uintval() > FPBits_t::max_normal().uintval())) {
+ if (x == 0.0) {
+ // return -Inf and raise FE_DIVBYZERO.
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits_t::inf(Sign::NEG).get_val();
+ }
+ if (xbits.is_neg() && !xbits.is_nan()) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits_t::quiet_nan().get_val();
+ }
+ if (xbits.is_inf_or_nan()) {
+ return x;
+ }
+ // Normalize denormal inputs.
+ xbits = FPBits_t(x * 0x1.0p52);
+ x_e -= 52;
+ x_u = xbits.uintval();
+ }
+
+ // log2(x) = log2(2^x_e * x_m)
+ // = x_e + log2(x_m)
+ // Range reduction for log2(x_m):
+ // For each x_m, we would like to find r such that:
+ // -2^-8 <= r * x_m - 1 < 2^-7
+ int shifted = static_cast<int>(x_u >> 45);
+ int index = shifted & 0x7F;
+ double r = RD[index];
+
+ // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
+ // all 1's.
+ x_e += static_cast<int>((x_u + (1ULL << 45)) >> 52);
+ double e_x = static_cast<double>(x_e);
+
+ // Set m = 1.mantissa.
+ uint64_t x_m = (x_u & 0x000F'FFFF'FFFF'FFFFULL) | 0x3FF0'0000'0000'0000ULL;
+ double m = FPBits_t(x_m).get_val();
+
+ fputil::DoubleDouble r1;
+
+ // Perform exact range reduction
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ double u = fputil::multiply_add(r, m, -1.0); // exact
+#else
+ uint64_t c_m = x_m & 0x3FFF'E000'0000'0000ULL;
+ double c = FPBits_t(c_m).get_val();
+ double u = fputil::multiply_add(r, m - c, CD[index]); // exact
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+
+ // Exact sum:
+ // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
+ r1 = fputil::exact_add(LOG_R1[index].hi, u);
+
+ // Error of u_sq = ulp(u^2);
+ double u_sq = u * u;
+ // Degree-7 minimax polynomial
+ double p0 = fputil::multiply_add(u, LOG_COEFFS[1], LOG_COEFFS[0]);
+ double p1 = fputil::multiply_add(u, LOG_COEFFS[3], LOG_COEFFS[2]);
+ double p2 = fputil::multiply_add(u, LOG_COEFFS[5], LOG_COEFFS[4]);
+ double p = fputil::polyeval(u_sq, LOG_R1[index].lo, p0, p1, p2);
+
+ r1.lo += p;
+
+ // Quick double-double multiplication:
+ // r2.hi + r2.lo ~ r1 * log2(e),
+ // with error bounded by:
+ // 4*ulp( ulp(r2.hi) )
+ fputil::DoubleDouble r2 = fputil::quick_mult(r1, LOG2_E);
+ fputil::DoubleDouble r3 = fputil::exact_add(e_x, r2.hi);
+ r3.lo += r2.lo;
+
+ // Overall, if we choose sufficiently large constant C, the total error is
+ // bounded by (C * ulp(u^2)).
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ return r3.hi + r3.lo;
+#else
+ // Total error is bounded by ~ C * ulp(u^2).
+ double err = u_sq * P_ERR;
+ // Lower bound from the result
+ double left = r3.hi + (r3.lo - err);
+ // Upper bound from the result
+ double right = r3.hi + (r3.lo + err);
+
+ // Ziv's test if fast pass is accurate enough.
+ if (left == right)
+ return left;
+
+ return log2_accurate(x_e, index, u);
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG2_H
diff --git a/libc/src/__support/math/logbf.h b/libc/src/__support/math/logbf.h
new file mode 100644
index 0000000..1b0daf9
--- /dev/null
+++ b/libc/src/__support/math/logbf.h
@@ -0,0 +1,26 @@
+//===-- Implementation header for logbf -------------------------*- 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_MATH_LOGBF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF_H
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float logbf(float x) { return fputil::logb(x); }
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF_H
diff --git a/libc/src/__support/math/logbf128.h b/libc/src/__support/math/logbf128.h
new file mode 100644
index 0000000..d18efc5
--- /dev/null
+++ b/libc/src/__support/math/logbf128.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for logbf128-----------------------*- 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_MATH_LOGBF128_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF128_H
+
+#include "include/llvm-libc-types/float128.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float128 logbf128(float128 x) {
+ return fputil::logb(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT128
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF128_H
diff --git a/libc/src/__support/math/logbf16.h b/libc/src/__support/math/logbf16.h
new file mode 100644
index 0000000..239e57b
--- /dev/null
+++ b/libc/src/__support/math/logbf16.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for logbf16 -----------------------*- 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_MATH_LOGBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 logbf16(float16 x) {
+ return fputil::logb(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGBF16_H
diff --git a/libc/src/__support/math/logf.h b/libc/src/__support/math/logf.h
new file mode 100644
index 0000000..e96fe28
--- /dev/null
+++ b/libc/src/__support/math/logf.h
@@ -0,0 +1,192 @@
+//===-- Single-precision log(x) function ----------------------------------===//
+//
+// 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_LOGF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
+
+#include "common_constants.h" // Lookup table for (1/f) and log(f)
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h"
+
+// This is an algorithm for log(x) in single precision which is correctly
+// rounded for all rounding modes, based on the implementation of log(x) from
+// the RLIBM project at:
+// https://people.cs.rutgers.edu/~sn349/rlibm
+
+// Step 1 - Range reduction:
+// For x = 2^m * 1.mant, log(x) = m * log(2) + log(1.m)
+// If x is denormal, we normalize it by multiplying x by 2^23 and subtracting
+// m by 23.
+
+// Step 2 - Another range reduction:
+// To compute log(1.mant), let f be the highest 8 bits including the hidden
+// bit, and d be the difference (1.mant - f), i.e. the remaining 16 bits of the
+// mantissa. Then we have the following approximation formula:
+// log(1.mant) = log(f) + log(1.mant / f)
+// = log(f) + log(1 + d/f)
+// ~ log(f) + P(d/f)
+// since d/f is sufficiently small.
+// log(f) and 1/f are then stored in two 2^7 = 128 entries look-up tables.
+
+// Step 3 - Polynomial approximation:
+// To compute P(d/f), we use a single degree-5 polynomial in double precision
+// which provides correct rounding for all but few exception values.
+// For more detail about how this polynomial is obtained, please refer to the
+// paper:
+// Lim, J. and Nagarakatte, S., "One Polynomial Approximation to Produce
+// Correctly Rounded Results of an Elementary Function for Multiple
+// Representations and Rounding Modes", Proceedings of the 49th ACM SIGPLAN
+// Symposium on Principles of Programming Languages (POPL-2022), Philadelphia,
+// USA, January 16-22, 2022.
+// https://people.cs.rutgers.edu/~sn349/papers/rlibmall-popl-2022.pdf
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float logf(float x) {
+ using namespace common_constants_internal;
+ constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
+ using FPBits = typename fputil::FPBits<float>;
+
+ FPBits xbits(x);
+ uint32_t x_u = xbits.uintval();
+
+ int m = -FPBits::EXP_BIAS;
+
+ using fputil::round_result_slightly_down;
+ using fputil::round_result_slightly_up;
+
+ // Small inputs
+ if (x_u < 0x4c5d65a5U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Hard-to-round cases.
+ switch (x_u) {
+ case 0x3f7f4d6fU: // x = 0x1.fe9adep-1f
+ return round_result_slightly_up(-0x1.659ec8p-9f);
+ case 0x41178febU: // x = 0x1.2f1fd6p+3f
+ return round_result_slightly_up(0x1.1fcbcep+1f);
+#ifdef LIBC_TARGET_CPU_HAS_FMA
+ case 0x3f800000U: // x = 1.0f
+ return 0.0f;
+#else
+ case 0x1e88452dU: // x = 0x1.108a5ap-66f
+ return round_result_slightly_up(-0x1.6d7b18p+5f);
+#endif // LIBC_TARGET_CPU_HAS_FMA
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Subnormal inputs.
+ if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
+ if (x == 0.0f) {
+ // Return -inf and raise FE_DIVBYZERO
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits::inf(Sign::NEG).get_val();
+ }
+ // Normalize denormal inputs.
+ xbits = FPBits(xbits.get_val() * 0x1.0p23f);
+ m -= 23;
+ x_u = xbits.uintval();
+ }
+ } else {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Hard-to-round cases.
+ switch (x_u) {
+ case 0x4c5d65a5U: // x = 0x1.bacb4ap+25f
+ return round_result_slightly_down(0x1.1e0696p+4f);
+ case 0x65d890d3U: // x = 0x1.b121a6p+76f
+ return round_result_slightly_down(0x1.a9a3f2p+5f);
+ case 0x6f31a8ecU: // x = 0x1.6351d8p+95f
+ return round_result_slightly_down(0x1.08b512p+6f);
+ case 0x7a17f30aU: // x = 0x1.2fe614p+117f
+ return round_result_slightly_up(0x1.451436p+6f);
+#ifndef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ case 0x500ffb03U: // x = 0x1.1ff606p+33f
+ return round_result_slightly_up(0x1.6fdd34p+4f);
+ case 0x5cd69e88U: // x = 0x1.ad3d1p+58f
+ return round_result_slightly_up(0x1.45c146p+5f);
+ case 0x5ee8984eU: // x = 0x1.d1309cp+62f;
+ return round_result_slightly_up(0x1.5c9442p+5f);
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Exceptional inputs.
+ if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
+ if (x_u == 0x8000'0000U) {
+ // Return -inf and raise FE_DIVBYZERO
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits::inf(Sign::NEG).get_val();
+ }
+ if (xbits.is_neg() && !xbits.is_nan()) {
+ // Return NaN and raise FE_INVALID
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ // x is +inf or nan
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ return x;
+ }
+ }
+
+#ifndef LIBC_TARGET_CPU_HAS_FMA
+ // Returning the correct +0 when x = 1.0 for non-FMA targets with FE_DOWNWARD
+ // rounding mode.
+ if (LIBC_UNLIKELY((x_u & 0x007f'ffffU) == 0))
+ return static_cast<float>(
+ static_cast<double>(m + xbits.get_biased_exponent()) * LOG_2);
+#endif // LIBC_TARGET_CPU_HAS_FMA
+
+ uint32_t mant = xbits.get_mantissa();
+ // Extract 7 leading fractional bits of the mantissa
+ int index = mant >> 16;
+ // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are
+ // all 1's.
+ m += static_cast<int>((x_u + (1 << 16)) >> 23);
+
+ // Set bits to 1.m
+ xbits.set_biased_exponent(0x7F);
+
+ float u = xbits.get_val();
+ double v = 0.0;
+#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ v = static_cast<double>(fputil::multiply_add(u, R[index], -1.0f)); // Exact.
+#else
+ v = fputil::multiply_add(static_cast<double>(u), RD[index], -1.0); // Exact
+#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
+
+ // Degree-5 polynomial approximation of log generated by Sollya with:
+ // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]);
+ constexpr double COEFFS[4] = {-0x1.000000000fe63p-1, 0x1.555556e963c16p-2,
+ -0x1.000028dedf986p-2, 0x1.966681bfda7f7p-3};
+ double v2 = v * v; // Exact
+ double p2 = fputil::multiply_add(v, COEFFS[3], COEFFS[2]);
+ double p1 = fputil::multiply_add(v, COEFFS[1], COEFFS[0]);
+ double p0 = LOG_R[index] + v;
+ double r = fputil::multiply_add(static_cast<double>(m), LOG_2,
+ fputil::polyeval(v2, p0, p1, p2));
+ return static_cast<float>(r);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
diff --git a/libc/src/__support/math/logf16.h b/libc/src/__support/math/logf16.h
new file mode 100644
index 0000000..c123eb0
--- /dev/null
+++ b/libc/src/__support/math/logf16.h
@@ -0,0 +1,180 @@
+//===-- Implementation header for logf16 ------------------------*- 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_MATH_LOGF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "expxf16_utils.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/cpu_features.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace logf16_internal {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+LIBC_INLINE_VAR constexpr size_t N_LOGF16_EXCEPTS = 5;
+#else
+LIBC_INLINE_VAR constexpr size_t N_LOGF16_EXCEPTS = 11;
+#endif
+LIBC_INLINE_VAR constexpr fputil::ExceptValues<float16, N_LOGF16_EXCEPTS>
+ LOGF16_EXCEPTS = {{
+// (input, RZ output, RU offset, RD offset, RN offset)
+#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ // x = 0x1.61cp-13, logf16(x) = -0x1.16p+3 (RZ)
+ {0x0987U, 0xc858U, 0U, 1U, 0U},
+ // x = 0x1.f2p-12, logf16(x) = -0x1.e98p+2 (RZ)
+ {0x0fc8U, 0xc7a6U, 0U, 1U, 1U},
+#endif
+ // x = 0x1.4d4p-9, logf16(x) = -0x1.7e4p+2 (RZ)
+ {0x1935U, 0xc5f9U, 0U, 1U, 0U},
+ // x = 0x1.5ep-8, logf16(x) = -0x1.4ecp+2 (RZ)
+ {0x1d78U, 0xc53bU, 0U, 1U, 0U},
+#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ // x = 0x1.fdp-1, logf16(x) = -0x1.81p-8 (RZ)
+ {0x3bf4U, 0x9e04U, 0U, 1U, 1U},
+ // x = 0x1.fep-1, logf16(x) = -0x1.008p-8 (RZ)
+ {0x3bf8U, 0x9c02U, 0U, 1U, 0U},
+#endif
+ // x = 0x1.ffp-1, logf16(x) = -0x1.004p-9 (RZ)
+ {0x3bfcU, 0x9801U, 0U, 1U, 0U},
+ // x = 0x1.ff8p-1, logf16(x) = -0x1p-10 (RZ)
+ {0x3bfeU, 0x9400U, 0U, 1U, 1U},
+#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ // x = 0x1.4c4p+1, logf16(x) = 0x1.e84p-1 (RZ)
+ {0x4131U, 0x3ba1U, 1U, 0U, 1U},
+#else
+ // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
+ {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
+ // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
+ {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
+ // x = 0x1.d5p+9, logf16(x) = 0x1.b5cp+2 (RZ)
+ {0x6354U, 0x46d7U, 1U, 0U, 1U},
+#endif
+ }};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace logf16_internal
+
+LIBC_INLINE static float16 logf16(float16 x) {
+ using namespace math::expxf16_internal;
+ using namespace math::logf16_internal;
+ using FPBits = fputil::FPBits<float16>;
+ FPBits x_bits(x);
+
+ uint16_t x_u = x_bits.uintval();
+
+ // If x <= 0, or x is 1, or x is +inf, or x is NaN.
+ if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) {
+ // log(NaN) = NaN
+ if (x_bits.is_nan()) {
+ if (x_bits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ return x;
+ }
+
+ // log(+/-0) = −inf
+ if ((x_u & 0x7fffU) == 0U) {
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits::inf(Sign::NEG).get_val();
+ }
+
+ if (x_u == 0x3c00U)
+ return FPBits::zero().get_val();
+
+ // When x < 0.
+ if (x_u > 0x8000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ // log(+inf) = +inf
+ return FPBits::inf().get_val();
+ }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ if (auto r = LOGF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ // To compute log(x), we perform the following range reduction:
+ // x = 2^m * 1.mant,
+ // log(x) = m * log(2) + log(1.mant).
+ // To compute log(1.mant), let f be the highest 6 bits including the hidden
+ // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of
+ // the mantissa, then:
+ // log(1.mant) = log(f) + log(1.mant / f)
+ // = log(f) + log(1 + d/f)
+ // since d/f is sufficiently small.
+ // We store log(f) and 1/f in the lookup tables LOGF_F and ONE_OVER_F_F
+ // respectively.
+
+ int m = -FPBits::EXP_BIAS;
+
+ // When x is subnormal, normalize it.
+ if ((x_u & FPBits::EXP_MASK) == 0U) {
+ // Can't pass an integer to fputil::cast directly.
+ constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
+ x_bits = FPBits(x_bits.get_val() * fputil::cast<float16>(NORMALIZE_EXP));
+ x_u = x_bits.uintval();
+ m -= FPBits::FRACTION_LEN;
+ }
+
+ uint16_t mant = x_bits.get_mantissa();
+ // Leading 10 - 5 = 5 bits of the mantissa.
+ int f = mant >> 5;
+ // Unbiased exponent.
+ m += x_u >> FPBits::FRACTION_LEN;
+
+ // Set bits to 1.mant instead of 2^m * 1.mant.
+ x_bits.set_biased_exponent(FPBits::EXP_BIAS);
+ float mant_f = x_bits.get_val();
+ // v = 1.mant * 1/f - 1 = d/f
+ float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f);
+
+ // Degree-3 minimax polynomial generated by Sollya with the following
+ // commands:
+ // > display = hexadecimal;
+ // > P = fpminimax(log(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
+ // > x * P;
+ float log1p_d_over_f =
+ v * fputil::polyeval(v, 0x1p+0f, -0x1.001804p-1f, 0x1.557ef6p-2f);
+ // log(1.mant) = log(f) + log(1 + d/f)
+ float log_1_mant = LOGF_F[f] + log1p_d_over_f;
+ return fputil::cast<float16>(
+ fputil::multiply_add(static_cast<float>(m), LOGF_2, log_1_mant));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGF16_H
diff --git a/libc/src/__support/math/range_reduction.h b/libc/src/__support/math/range_reduction.h
index e3f25e4..b813b2e 100644
--- a/libc/src/__support/math/range_reduction.h
+++ b/libc/src/__support/math/range_reduction.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
-#define LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/multiply_add.h"
@@ -87,4 +87,4 @@ LIBC_INLINE int64_t large_range_reduction(double x, int x_exp, double &y) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_H
diff --git a/libc/src/__support/math/range_reduction_fma.h b/libc/src/__support/math/range_reduction_fma.h
index c06a1d8..d8676d0 100644
--- a/libc/src/__support/math/range_reduction_fma.h
+++ b/libc/src/__support/math/range_reduction_fma.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
-#define LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
#include "src/__support/FPUtil/FMA.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -89,4 +89,4 @@ LIBC_INLINE int64_t large_range_reduction(double x, int x_exp, double &y) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RANGE_REDUCTION_FMA_H
diff --git a/libc/src/__support/math/sin.h b/libc/src/__support/math/sin.h
index af1eb59..3a67af0 100644
--- a/libc/src/__support/math/sin.h
+++ b/libc/src/__support/math/sin.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_SIN_H
-#define LIBC_SRC___SUPPORT_MATH_SIN_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_SIN_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SIN_H
#include "range_reduction_double_common.h"
#include "sincos_eval.h"
@@ -178,4 +178,4 @@ LIBC_INLINE static constexpr double sin(double x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_SIN_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SIN_H
diff --git a/libc/src/__support/math/sincosf_utils.h b/libc/src/__support/math/sincosf_utils.h
index ed9d9f6..62586c2 100644
--- a/libc/src/__support/math/sincosf_utils.h
+++ b/libc/src/__support/math/sincosf_utils.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
-#define LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
@@ -122,4 +122,4 @@ LIBC_INLINE void sincospif_eval(double xd, double &sin_k, double &cos_k,
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINCOSF_UTILS_H
diff --git a/libc/src/__support/math/sinf.h b/libc/src/__support/math/sinf.h
new file mode 100644
index 0000000..9290444b
--- /dev/null
+++ b/libc/src/__support/math/sinf.h
@@ -0,0 +1,194 @@
+//===-- Single-precision sin function -------------------------------------===//
+//
+// 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_SINF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINF_H
+
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
+
+#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) && \
+ defined(LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT) && \
+ defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
+
+#include "sincosf_float_eval.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float sinf(float x) {
+ return math::sincosf_float_eval::sincosf_eval</*IS_SIN*/ true>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#else // !LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
+
+#include "src/__support/math/sincosf_utils.h"
+
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+#include "src/__support/math/range_reduction_fma.h"
+#else // !LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+#include "src/__support/math/range_reduction.h"
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static float sinf(float x) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+ double xd = static_cast<double>(x);
+
+ // Range reduction:
+ // For |x| > pi/32, we perform range reduction as follows:
+ // Find k and y such that:
+ // x = (k + y) * pi/32
+ // k is an integer
+ // |y| < 0.5
+ // For small range (|x| < 2^45 when FMA instructions are available, 2^22
+ // otherwise), this is done by performing:
+ // k = round(x * 32/pi)
+ // y = x * 32/pi - k
+ // For large range, we will omit all the higher parts of 32/pi such that the
+ // least significant bits of their full products with x are larger than 63,
+ // since sin((k + y + 64*i) * pi/32) = sin(x + i * 2pi) = sin(x).
+ //
+ // When FMA instructions are not available, we store the digits of 32/pi in
+ // chunks of 28-bit precision. This will make sure that the products:
+ // x * THIRTYTWO_OVER_PI_28[i] are all exact.
+ // When FMA instructions are available, we simply store the digits of 32/pi in
+ // chunks of doubles (53-bit of precision).
+ // So when multiplying by the largest values of single precision, the
+ // resulting output should be correct up to 2^(-208 + 128) ~ 2^-80. By the
+ // worst-case analysis of range reduction, |y| >= 2^-38, so this should give
+ // us more than 40 bits of accuracy. For the worst-case estimation of range
+ // reduction, see for instances:
+ // Elementary Functions by J-M. Muller, Chapter 11,
+ // Handbook of Floating-Point Arithmetic by J-M. Muller et. al.,
+ // Chapter 10.2.
+ //
+ // Once k and y are computed, we then deduce the answer by the sine of sum
+ // formula:
+ // sin(x) = sin((k + y)*pi/32)
+ // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
+ // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed
+ // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
+ // computed using degree-7 and degree-6 minimax polynomials generated by
+ // Sollya respectively.
+
+ // |x| <= pi/16
+ if (LIBC_UNLIKELY(x_abs <= 0x3e49'0fdbU)) {
+
+ // |x| < 0x1.d12ed2p-12f
+ if (LIBC_UNLIKELY(x_abs < 0x39e8'9769U)) {
+ if (LIBC_UNLIKELY(x_abs == 0U)) {
+ // For signed zeros.
+ return x;
+ }
+ // When |x| < 2^-12, the relative error of the approximation sin(x) ~ x
+ // is:
+ // |sin(x) - x| / |sin(x)| < |x^3| / (6|x|)
+ // = x^2 / 6
+ // < 2^-25
+ // < epsilon(1)/2.
+ // So the correctly rounded values of sin(x) are:
+ // = x - sign(x)*eps(x) if rounding mode = FE_TOWARDZERO,
+ // or (rounding mode = FE_UPWARD and x is
+ // negative),
+ // = x otherwise.
+ // To simplify the rounding decision and make it more efficient, we use
+ // fma(x, -2^-25, x) instead.
+ // An exhaustive test shows that this formula work correctly for all
+ // rounding modes up to |x| < 0x1.c555dep-11f.
+ // Note: to use the formula x - 2^-25*x to decide the correct rounding, we
+ // do need fma(x, -2^-25, x) to prevent underflow caused by -2^-25*x when
+ // |x| < 2^-125. For targets without FMA instructions, we simply use
+ // double for intermediate results as it is more efficient than using an
+ // emulated version of FMA.
+#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
+ return fputil::multiply_add(x, -0x1.0p-25f, x);
+#else
+ return static_cast<float>(fputil::multiply_add(xd, -0x1.0p-25, xd));
+#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ }
+
+ // |x| < pi/16.
+ double xsq = xd * xd;
+
+ // Degree-9 polynomial approximation:
+ // sin(x) ~ x + a_3 x^3 + a_5 x^5 + a_7 x^7 + a_9 x^9
+ // = x (1 + a_3 x^2 + ... + a_9 x^8)
+ // = x * P(x^2)
+ // generated by Sollya with the following commands:
+ // > display = hexadecimal;
+ // > Q = fpminimax(sin(x)/x, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]);
+ double result =
+ fputil::polyeval(xsq, 1.0, -0x1.55555555554c6p-3, 0x1.1111111085e65p-7,
+ -0x1.a019f70fb4d4fp-13, 0x1.718d179815e74p-19);
+ return static_cast<float>(xd * result);
+ }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
+ float r = -0x1.63f4bap-2f;
+ int rounding = fputil::quick_get_round();
+ if ((rounding == FE_DOWNWARD && xbits.is_pos()) ||
+ (rounding == FE_UPWARD && xbits.is_neg()))
+ r = -0x1.63f4bcp-2f;
+ return xbits.is_neg() ? -r : r;
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ if (x_abs == 0x7f80'0000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ // Combine the results with the sine of sum formula:
+ // sin(x) = sin((k + y)*pi/32)
+ // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
+ // = sin_y * cos_k + (1 + cosm1_y) * sin_k
+ // = sin_y * cos_k + (cosm1_y * sin_k + sin_k)
+ double sin_k, cos_k, sin_y, cosm1_y;
+
+ sincosf_eval(xd, x_abs, sin_k, cos_k, sin_y, cosm1_y);
+
+ return static_cast<float>(fputil::multiply_add(
+ sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINF_H
diff --git a/libc/src/__support/math/sinf16.h b/libc/src/__support/math/sinf16.h
new file mode 100644
index 0000000..e18d0cf
--- /dev/null
+++ b/libc/src/__support/math/sinf16.h
@@ -0,0 +1,136 @@
+//===-- Half-precision sin(x) function ------------------------------------===//
+//
+// 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_SINF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "sincosf16_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace sinf16_internal {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+LIBC_INLINE_VAR constexpr size_t N_EXCEPTS = 4;
+
+LIBC_INLINE_VAR constexpr fputil::ExceptValues<float16, N_EXCEPTS>
+ SINF16_EXCEPTS{{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ {0x2b45, 0x2b43, 1, 0, 1},
+ {0x585c, 0x3ba3, 1, 0, 1},
+ {0x5cb0, 0xbbff, 0, 1, 0},
+ {0x51f5, 0xb80f, 0, 1, 0},
+ }};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace sinf16_internal
+
+LIBC_INLINE static float16 sinf16(float16 x) {
+ using namespace sinf16_internal;
+ using namespace sincosf16_internal;
+ using FPBits = fputil::FPBits<float16>;
+ FPBits xbits(x);
+
+ uint16_t x_u = xbits.uintval();
+ uint16_t x_abs = x_u & 0x7fff;
+ float xf = x;
+
+ // Range reduction:
+ // For |x| > pi/32, we perform range reduction as follows:
+ // Find k and y such that:
+ // x = (k + y) * pi/32
+ // k is an integer, |y| < 0.5
+ //
+ // This is done by performing:
+ // k = round(x * 32/pi)
+ // y = x * 32/pi - k
+ //
+ // Once k and y are computed, we then deduce the answer by the sine of sum
+ // formula:
+ // sin(x) = sin((k + y) * pi/32)
+ // = sin(k * pi/32) * cos(y * pi/32) +
+ // sin(y * pi/32) * cos(k * pi/32)
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Handle exceptional values
+ bool x_sign = x_u >> 15;
+
+ if (auto r = SINF16_EXCEPTS.lookup_odd(x_abs, x_sign);
+ LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ int rounding = fputil::quick_get_round();
+
+ // Exhaustive tests show that for |x| <= 0x1.f4p-11, 1ULP rounding errors
+ // occur. To fix this, the following apply:
+ if (LIBC_UNLIKELY(x_abs <= 0x13d0)) {
+ // sin(+/-0) = +/-0
+ if (LIBC_UNLIKELY(x_abs == 0U))
+ return x;
+
+ // When x > 0, and rounding upward, sin(x) == x.
+ // When x < 0, and rounding downward, sin(x) == x.
+ if ((rounding == FE_UPWARD && xbits.is_pos()) ||
+ (rounding == FE_DOWNWARD && xbits.is_neg()))
+ return x;
+
+ // When x < 0, and rounding upward, sin(x) == (x - 1ULP)
+ if (rounding == FE_UPWARD && xbits.is_neg()) {
+ x_u--;
+ return FPBits(x_u).get_val();
+ }
+ }
+
+ if (xbits.is_inf_or_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ if (xbits.is_inf()) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ float sin_k, cos_k, sin_y, cosm1_y;
+ sincosf16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
+
+ if (LIBC_UNLIKELY(sin_y == 0 && sin_k == 0))
+ return FPBits::zero(xbits.sign()).get_val();
+
+ // Since, cosm1_y = cos_y - 1, therefore:
+ // sin(x) = cos_k * sin_y + sin_k + (cosm1_y * sin_k)
+ return fputil::cast<float16>(fputil::multiply_add(
+ sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINF16_H
diff --git a/libc/src/__support/math/sinhf.h b/libc/src/__support/math/sinhf.h
new file mode 100644
index 0000000..e8efc29
--- /dev/null
+++ b/libc/src/__support/math/sinhf.h
@@ -0,0 +1,88 @@
+//===-- Single-precision sinh function ------------------------------------===//
+//
+// 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_SINHF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINHF_H
+
+#include "sinhfcoshf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float sinhf(float x) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+ uint32_t x_abs = xbits.abs().uintval();
+
+ // When |x| >= 90, or x is inf or nan
+ if (LIBC_UNLIKELY(x_abs >= 0x42b4'0000U || x_abs <= 0x3da0'0000U)) {
+ // |x| <= 0.078125
+ if (x_abs <= 0x3da0'0000U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // |x| = 0.0005589424981735646724700927734375
+ if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
+ if (fputil::fenv_is_round_to_nearest())
+ return x;
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ // |x| <= 2^-26
+ if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
+ return static_cast<float>(
+ LIBC_UNLIKELY(x_abs == 0) ? x : (x + 0.25 * x * x * x));
+ }
+
+ double xdbl = x;
+ double x2 = xdbl * xdbl;
+ // Sollya: fpminimax(sinh(x),[|3,5,7|],[|D...|],[-1/16-1/64;1/16+1/64],x);
+ // Sollya output: x * (0x1p0 + x^0x1p1 * (0x1.5555555556583p-3 + x^0x1p1
+ // * (0x1.111110d239f1fp-7
+ // + x^0x1p1 * 0x1.a02b5a284013cp-13)))
+ // Therefore, output of Sollya = x * pe;
+ double pe = fputil::polyeval(x2, 0.0, 0x1.5555555556583p-3,
+ 0x1.111110d239f1fp-7, 0x1.a02b5a284013cp-13);
+ return static_cast<float>(fputil::multiply_add(xdbl, pe, xdbl));
+ }
+
+ if (xbits.is_nan())
+ return x + 1.0f; // sNaN to qNaN + signal
+
+ if (xbits.is_inf())
+ return x;
+
+ int rounding = fputil::quick_get_round();
+ if (xbits.is_neg()) {
+ if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
+ return -FPBits::max_normal().get_val();
+ } else {
+ if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
+ return FPBits::max_normal().get_val();
+ }
+
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
+
+ return x + FPBits::inf(xbits.sign()).get_val();
+ }
+
+ // sinh(x) = (e^x - e^(-x)) / 2.
+ return static_cast<float>(
+ math::sinhfcoshf_internal::exp_pm_eval</*is_sinh*/ true>(x));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINHF_H
diff --git a/libc/src/__support/math/sinhf16.h b/libc/src/__support/math/sinhf16.h
new file mode 100644
index 0000000..df9b82c
--- /dev/null
+++ b/libc/src/__support/math/sinhf16.h
@@ -0,0 +1,168 @@
+//===-- Half-precision sinh(x) function -----------------------------------===//
+//
+// 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_SINHF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINHF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "expxf16_utils.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 sinhf16(float16 x) {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ constexpr fputil::ExceptValues<float16, 17> SINHF16_EXCEPTS_POS = {{
+ // x = 0x1.714p-5, sinhf16(x) = 0x1.714p-5 (RZ)
+ {0x29c5U, 0x29c5U, 1U, 0U, 1U},
+ // x = 0x1.25p-4, sinhf16(x) = 0x1.25p-4 (RZ)
+ {0x2c94U, 0x2c94U, 1U, 0U, 1U},
+ // x = 0x1.f5p-4, sinhf16(x) = 0x1.f64p-4 (RZ)
+ {0x2fd4U, 0x2fd9U, 1U, 0U, 0U},
+ // x = 0x1.b1cp-3, sinhf16(x) = 0x1.b4cp-3 (RZ)
+ {0x32c7U, 0x32d3U, 1U, 0U, 1U},
+ // x = 0x1.6e8p-2, sinhf16(x) = 0x1.764p-2 (RZ)
+ {0x35baU, 0x35d9U, 1U, 0U, 1U},
+ // x = 0x1.6b4p-1, sinhf16(x) = 0x1.8a4p-1 (RZ)
+ {0x39adU, 0x3a29U, 1U, 0U, 1U},
+ // x = 0x1.a58p-1, sinhf16(x) = 0x1.d68p-1 (RZ)
+ {0x3a96U, 0x3b5aU, 1U, 0U, 1U},
+ // x = 0x1.574p+0, sinhf16(x) = 0x1.c78p+0 (RZ)
+ {0x3d5dU, 0x3f1eU, 1U, 0U, 1U},
+ // x = 0x1.648p+1, sinhf16(x) = 0x1.024p+3 (RZ)
+ {0x4192U, 0x4809U, 1U, 0U, 0U},
+ // x = 0x1.cdcp+1, sinhf16(x) = 0x1.26cp+4 (RZ)
+ {0x4337U, 0x4c9bU, 1U, 0U, 0U},
+ // x = 0x1.d0cp+1, sinhf16(x) = 0x1.2d8p+4 (RZ)
+ {0x4343U, 0x4cb6U, 1U, 0U, 1U},
+ // x = 0x1.018p+2, sinhf16(x) = 0x1.bfp+4 (RZ)
+ {0x4406U, 0x4efcU, 1U, 0U, 0U},
+ // x = 0x1.2fcp+2, sinhf16(x) = 0x1.cc4p+5 (RZ)
+ {0x44bfU, 0x5331U, 1U, 0U, 1U},
+ // x = 0x1.4ecp+2, sinhf16(x) = 0x1.75cp+6 (RZ)
+ {0x453bU, 0x55d7U, 1U, 0U, 0U},
+ // x = 0x1.8a4p+2, sinhf16(x) = 0x1.d94p+7 (RZ)
+ {0x4629U, 0x5b65U, 1U, 0U, 1U},
+ // x = 0x1.5fp+3, sinhf16(x) = 0x1.c54p+14 (RZ)
+ {0x497cU, 0x7715U, 1U, 0U, 1U},
+ // x = 0x1.3c8p+1, sinhf16(x) = 0x1.78ap+2 (RZ)
+ {0x40f2U, 0x45e2U, 1U, 0U, 1U},
+ }};
+
+ constexpr fputil::ExceptValues<float16, 13> SINHF16_EXCEPTS_NEG = {{
+ // x = -0x1.714p-5, sinhf16(x) = -0x1.714p-5 (RZ)
+ {0xa9c5U, 0xa9c5U, 0U, 1U, 1U},
+ // x = -0x1.25p-4, sinhf16(x) = -0x1.25p-4 (RZ)
+ {0xac94U, 0xac94U, 0U, 1U, 1U},
+ // x = -0x1.f5p-4, sinhf16(x) = -0x1.f64p-4 (RZ)
+ {0xafd4U, 0xafd9U, 0U, 1U, 0U},
+ // x = -0x1.6e8p-2, sinhf16(x) = -0x1.764p-2 (RZ)
+ {0xb5baU, 0xb5d9U, 0U, 1U, 1U},
+ // x = -0x1.a58p-1, sinhf16(x) = -0x1.d68p-1 (RZ)
+ {0xba96U, 0xbb5aU, 0U, 1U, 1U},
+ // x = -0x1.cdcp+1, sinhf16(x) = -0x1.26cp+4 (RZ)
+ {0xc337U, 0xcc9bU, 0U, 1U, 0U},
+ // x = -0x1.d0cp+1, sinhf16(x) = -0x1.2d8p+4 (RZ)
+ {0xc343U, 0xccb6U, 0U, 1U, 1U},
+ // x = -0x1.018p+2, sinhf16(x) = -0x1.bfp+4 (RZ)
+ {0xc406U, 0xcefcU, 0U, 1U, 0U},
+ // x = -0x1.2fcp+2, sinhf16(x) = -0x1.cc4p+5 (RZ)
+ {0xc4bfU, 0xd331U, 0U, 1U, 1U},
+ // x = -0x1.4ecp+2, sinhf16(x) = -0x1.75cp+6 (RZ)
+ {0xc53bU, 0xd5d7U, 0U, 1U, 0U},
+ // x = -0x1.8a4p+2, sinhf16(x) = -0x1.d94p+7 (RZ)
+ {0xc629U, 0xdb65U, 0U, 1U, 1U},
+ // x = -0x1.5fp+3, sinhf16(x) = -0x1.c54p+14 (RZ)
+ {0xc97cU, 0xf715U, 0U, 1U, 1U},
+ // x = -0x1.3c8p+1, sinhf16(x) = -0x1.78ap+2 (RZ)
+ {0xc0f2U, 0xc5e2U, 0U, 1U, 1U},
+ }};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ using namespace math::expxf16_internal;
+ using FPBits = fputil::FPBits<float16>;
+ FPBits x_bits(x);
+
+ uint16_t x_u = x_bits.uintval();
+ uint16_t x_abs = x_u & 0x7fffU;
+
+ // When |x| = 0, or -2^(-14) <= x <= -2^(-9), or |x| >= asinh(2^16), or x is
+ // NaN.
+ if (LIBC_UNLIKELY(x_abs == 0U || (x_u >= 0x8400U && x_u <= 0xa400U) ||
+ x_abs >= 0x49e5U)) {
+ // sinh(NaN) = NaN
+ if (x_bits.is_nan()) {
+ if (x_bits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ return x;
+ }
+
+ // sinh(+/-0) = sinh(+/-0)
+ if (x_abs == 0U)
+ return FPBits::zero(x_bits.sign()).get_val();
+
+ // When |x| >= asinh(2^16).
+ if (x_abs >= 0x49e5U) {
+ // sinh(+/-inf) = +/-inf
+ if (x_bits.is_inf())
+ return FPBits::inf(x_bits.sign()).get_val();
+
+ int rounding_mode = fputil::quick_get_round();
+ if (rounding_mode == FE_TONEAREST ||
+ (x_bits.is_pos() && rounding_mode == FE_UPWARD) ||
+ (x_bits.is_neg() && rounding_mode == FE_DOWNWARD)) {
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
+ return FPBits::inf(x_bits.sign()).get_val();
+ }
+ return FPBits::max_normal(x_bits.sign()).get_val();
+ }
+
+ // When -2^(-14) <= x <= -2^(-9).
+ if (fputil::fenv_is_round_down())
+ return FPBits(static_cast<uint16_t>(x_u + 1)).get_val();
+ return FPBits(static_cast<uint16_t>(x_u)).get_val();
+ }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ if (x_bits.is_pos()) {
+ if (auto r = SINHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+ } else {
+ if (auto r = SINHF16_EXCEPTS_NEG.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ return eval_sinh_or_cosh</*IsSinh=*/true>(x);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINHF16_H
diff --git a/libc/src/__support/math/sinpif.h b/libc/src/__support/math/sinpif.h
new file mode 100644
index 0000000..8f15703
--- /dev/null
+++ b/libc/src/__support/math/sinpif.h
@@ -0,0 +1,123 @@
+//===-- Implementation header for sinpif ---------------------------* 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_MATH_SINPIF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SINPIF_H
+
+#include "sincosf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static float sinpif(float x) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+ double xd = static_cast<double>(x);
+
+ // Range reduction:
+ // For |x| > 1/32, we perform range reduction as follows:
+ // Find k and y such that:
+ // x = (k + y) * 1/32
+ // k is an integer
+ // |y| < 0.5
+ //
+ // This is done by performing:
+ // k = round(x * 32)
+ // y = x * 32 - k
+ //
+ // Once k and y are computed, we then deduce the answer by the sine of sum
+ // formula:
+ // sin(x * pi) = sin((k + y)*pi/32)
+ // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
+ // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed
+ // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
+ // computed using degree-7 and degree-6 minimax polynomials generated by
+ // Sollya respectively.
+
+ // |x| <= 1/16
+ if (LIBC_UNLIKELY(x_abs <= 0x3d80'0000U)) {
+
+ if (LIBC_UNLIKELY(x_abs < 0x33CD'01D7U)) {
+ if (LIBC_UNLIKELY(x_abs == 0U)) {
+ // For signed zeros.
+ return x;
+ }
+
+ // For very small values we can approximate sinpi(x) with x * pi
+ // An exhaustive test shows that this is accurate for |x| < 9.546391 ×
+ // 10-8
+ double xdpi = xd * 0x1.921fb54442d18p1;
+ return static_cast<float>(xdpi);
+ }
+
+ // |x| < 1/16.
+ double xsq = xd * xd;
+
+ // Degree-9 polynomial approximation:
+ // sinpi(x) ~ x + a_3 x^3 + a_5 x^5 + a_7 x^7 + a_9 x^9
+ // = x (1 + a_3 x^2 + ... + a_9 x^8)
+ // = x * P(x^2)
+ // generated by Sollya with the following commands:
+ // > display = hexadecimal;
+ // > Q = fpminimax(sin(pi * x)/x, [|0, 2, 4, 6, 8|], [|D...|], [0, 1/16]);
+ double result = fputil::polyeval(
+ xsq, 0x1.921fb54442d18p1, -0x1.4abbce625bbf2p2, 0x1.466bc675e116ap1,
+ -0x1.32d2c0b62d41cp-1, 0x1.501ec4497cb7dp-4);
+ return static_cast<float>(xd * result);
+ }
+
+ // Numbers greater or equal to 2^23 are always integers or NaN
+ if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
+
+ // check for NaN values
+ if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ if (x_abs == 0x7f80'0000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ return FPBits::zero(xbits.sign()).get_val();
+ }
+
+ // Combine the results with the sine of sum formula:
+ // sin(x * pi) = sin((k + y)*pi/32)
+ // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
+ // = sin_y * cos_k + (1 + cosm1_y) * sin_k
+ // = sin_y * cos_k + (cosm1_y * sin_k + sin_k)
+ double sin_k = 0, cos_k = 0, sin_y = 0, cosm1_y = 0;
+ sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
+
+ if (LIBC_UNLIKELY(sin_y == 0 && sin_k == 0))
+ return FPBits::zero(xbits.sign()).get_val();
+
+ return static_cast<float>(fputil::multiply_add(
+ sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SINPIF_H
diff --git a/libc/src/__support/math/sqrt.h b/libc/src/__support/math/sqrt.h
new file mode 100644
index 0000000..3faa62d
--- /dev/null
+++ b/libc/src/__support/math/sqrt.h
@@ -0,0 +1,24 @@
+//===-- Implementation header for sqrt --------------------------*- 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_MATH_SQRT_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SQRT_H
+
+#include "src/__support/FPUtil/sqrt.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static double sqrt(double x) { return fputil::sqrt<double>(x); }
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SQRT_H
diff --git a/libc/src/__support/math/sqrtf16.h b/libc/src/__support/math/sqrtf16.h
new file mode 100644
index 0000000..8c9e1e6
--- /dev/null
+++ b/libc/src/__support/math/sqrtf16.h
@@ -0,0 +1,31 @@
+//===-- Implementation header for sqrtf16 -----------------------*- 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_MATH_SQRTF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_SQRTF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+LIBC_INLINE static constexpr float16 sqrtf16(float16 x) {
+ return fputil::sqrt<float16>(x);
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_SQRTF16_H
diff --git a/libc/src/__support/math/tan.h b/libc/src/__support/math/tan.h
new file mode 100644
index 0000000..f7566bd
--- /dev/null
+++ b/libc/src/__support/math/tan.h
@@ -0,0 +1,305 @@
+//===-- Double-precision tan function -------------------------------------===//
+//
+// 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_TAN_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_TAN_H
+
+#include "hdr/errno_macros.h"
+#include "range_reduction_double_common.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/double_double.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
+
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+#include "range_reduction_double_fma.h"
+#else
+#include "range_reduction_double_nofma.h"
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace tan_internal {
+
+using DoubleDouble = fputil::DoubleDouble;
+using Float128 = typename fputil::DyadicFloat<128>;
+
+LIBC_INLINE static double tan_eval(const DoubleDouble &u,
+ DoubleDouble &result) {
+ // Evaluate tan(y) = tan(x - k * (pi/128))
+ // We use the degree-9 Taylor approximation:
+ // tan(y) ~ P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835
+ // Then the error is bounded by:
+ // |tan(y) - P(y)| < 2^-6 * |y|^11 < 2^-6 * 2^-66 = 2^-72.
+ // For y ~ u_hi + u_lo, fully expanding the polynomial and drop any terms
+ // < ulp(u_hi^3) gives us:
+ // P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835 = ...
+ // ~ u_hi + u_hi^3 * (1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 +
+ // + u_hi^2 * 62/2835))) +
+ // + u_lo (1 + u_hi^2 * (1 + u_hi^2 * 2/3))
+ double u_hi_sq = u.hi * u.hi; // Error < ulp(u_hi^2) < 2^(-6 - 52) = 2^-58.
+ // p1 ~ 17/315 + u_hi^2 62 / 2835.
+ double p1 =
+ fputil::multiply_add(u_hi_sq, 0x1.664f4882c10fap-6, 0x1.ba1ba1ba1ba1cp-5);
+ // p2 ~ 1/3 + u_hi^2 2 / 15.
+ double p2 =
+ fputil::multiply_add(u_hi_sq, 0x1.1111111111111p-3, 0x1.5555555555555p-2);
+ // q1 ~ 1 + u_hi^2 * 2/3.
+ double q1 = fputil::multiply_add(u_hi_sq, 0x1.5555555555555p-1, 1.0);
+ double u_hi_3 = u_hi_sq * u.hi;
+ double u_hi_4 = u_hi_sq * u_hi_sq;
+ // p3 ~ 1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 + u_hi^2 * 62/2835))
+ double p3 = fputil::multiply_add(u_hi_4, p1, p2);
+ // q2 ~ 1 + u_hi^2 * (1 + u_hi^2 * 2/3)
+ double q2 = fputil::multiply_add(u_hi_sq, q1, 1.0);
+ double tan_lo = fputil::multiply_add(u_hi_3, p3, u.lo * q2);
+ // Overall, |tan(y) - (u_hi + tan_lo)| < ulp(u_hi^3) <= 2^-71.
+ // And the relative errors is:
+ // |(tan(y) - (u_hi + tan_lo)) / tan(y) | <= 2*ulp(u_hi^2) < 2^-64
+ result = fputil::exact_add(u.hi, tan_lo);
+ return fputil::multiply_add(fputil::FPBits<double>(u_hi_3).abs().get_val(),
+ 0x1.0p-51, 0x1.0p-102);
+}
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+// Accurate evaluation of tan for small u.
+[[maybe_unused]] LIBC_INLINE static Float128 tan_eval(const Float128 &u) {
+ Float128 u_sq = fputil::quick_mul(u, u);
+
+ // tan(x) ~ x + x^3/3 + x^5 * 2/15 + x^7 * 17/315 + x^9 * 62/2835 +
+ // + x^11 * 1382/155925 + x^13 * 21844/6081075 +
+ // + x^15 * 929569/638512875 + x^17 * 6404582/10854718875
+ // Relative errors < 2^-127 for |u| < pi/256.
+ constexpr Float128 TAN_COEFFS[] = {
+ {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1
+ {Sign::POS, -129, 0xaaaaaaaa'aaaaaaaa'aaaaaaaa'aaaaaaab_u128}, // 1
+ {Sign::POS, -130, 0x88888888'88888888'88888888'88888889_u128}, // 2/15
+ {Sign::POS, -132, 0xdd0dd0dd'0dd0dd0d'd0dd0dd0'dd0dd0dd_u128}, // 17/315
+ {Sign::POS, -133, 0xb327a441'6087cf99'6b5dd24e'ec0b327a_u128}, // 62/2835
+ {Sign::POS, -134,
+ 0x91371aaf'3611e47a'da8e1cba'7d900eca_u128}, // 1382/155925
+ {Sign::POS, -136,
+ 0xeb69e870'abeefdaf'e606d2e4'd1e65fbc_u128}, // 21844/6081075
+ {Sign::POS, -137,
+ 0xbed1b229'5baf15b5'0ec9af45'a2619971_u128}, // 929569/638512875
+ {Sign::POS, -138,
+ 0x9aac1240'1b3a2291'1b2ac7e3'e4627d0a_u128}, // 6404582/10854718875
+ };
+
+ return fputil::quick_mul(
+ u, fputil::polyeval(u_sq, TAN_COEFFS[0], TAN_COEFFS[1], TAN_COEFFS[2],
+ TAN_COEFFS[3], TAN_COEFFS[4], TAN_COEFFS[5],
+ TAN_COEFFS[6], TAN_COEFFS[7], TAN_COEFFS[8]));
+}
+
+// Calculation a / b = a * (1/b) for Float128.
+// Using the initial approximation of q ~ (1/b), then apply 2 Newton-Raphson
+// iterations, before multiplying by a.
+[[maybe_unused]] Float128 newton_raphson_div(const Float128 &a, Float128 b,
+ double q) {
+ Float128 q0(q);
+ constexpr Float128 TWO(2.0);
+ b.sign = (b.sign == Sign::POS) ? Sign::NEG : Sign::POS;
+ Float128 q1 =
+ fputil::quick_mul(q0, fputil::quick_add(TWO, fputil::quick_mul(b, q0)));
+ Float128 q2 =
+ fputil::quick_mul(q1, fputil::quick_add(TWO, fputil::quick_mul(b, q1)));
+ return fputil::quick_mul(a, q2);
+}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace tan_internal
+
+LIBC_INLINE static double tan(double x) {
+ using namespace tan_internal;
+ using namespace math::range_reduction_double_internal;
+ using FPBits = typename fputil::FPBits<double>;
+ FPBits xbits(x);
+
+ uint16_t x_e = xbits.get_biased_exponent();
+
+ DoubleDouble y;
+ unsigned k;
+ LargeRangeReduction range_reduction_large{};
+
+ // |x| < 2^16
+ if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) {
+ // |x| < 2^-7
+ if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 7)) {
+ // |x| < 2^-27, |tan(x) - x| < ulp(x)/2.
+ if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 27)) {
+ // Signed zeros.
+ if (LIBC_UNLIKELY(x == 0.0))
+ return x + x; // Make sure it works with FTZ/DAZ.
+
+#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ return fputil::multiply_add(x, 0x1.0p-54, x);
+#else
+ if (LIBC_UNLIKELY(x_e < 4)) {
+ int rounding_mode = fputil::quick_get_round();
+ if ((xbits.sign() == Sign::POS && rounding_mode == FE_UPWARD) ||
+ (xbits.sign() == Sign::NEG && rounding_mode == FE_DOWNWARD))
+ return FPBits(xbits.uintval() + 1).get_val();
+ }
+ return fputil::multiply_add(x, 0x1.0p-54, x);
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+ }
+ // No range reduction needed.
+ k = 0;
+ y.lo = 0.0;
+ y.hi = x;
+ } else {
+ // Small range reduction.
+ k = range_reduction_small(x, y);
+ }
+ } else {
+ // Inf or NaN
+ if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ // tan(+-Inf) = NaN
+ if (xbits.get_mantissa() == 0) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+ return x + FPBits::quiet_nan().get_val();
+ }
+
+ // Large range reduction.
+ k = range_reduction_large.fast(x, y);
+ }
+
+ DoubleDouble tan_y;
+ [[maybe_unused]] double err = tan_eval(y, tan_y);
+
+ // Look up sin(k * pi/128) and cos(k * pi/128)
+#ifdef LIBC_MATH_HAS_SMALL_TABLES
+ // Memory saving versions. Use 65-entry table:
+ auto get_idx_dd = [](unsigned kk) -> DoubleDouble {
+ unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63);
+ DoubleDouble ans = SIN_K_PI_OVER_128[idx];
+ if (kk & 128) {
+ ans.hi = -ans.hi;
+ ans.lo = -ans.lo;
+ }
+ return ans;
+ };
+ DoubleDouble msin_k = get_idx_dd(k + 128);
+ DoubleDouble cos_k = get_idx_dd(k + 64);
+#else
+ // Fast look up version, but needs 256-entry table.
+ // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128).
+ DoubleDouble msin_k = SIN_K_PI_OVER_128[(k + 128) & 255];
+ DoubleDouble cos_k = SIN_K_PI_OVER_128[(k + 64) & 255];
+#endif // LIBC_MATH_HAS_SMALL_TABLES
+
+ // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128).
+ // So k is an integer and -pi / 256 <= y <= pi / 256.
+ // Then tan(x) = sin(x) / cos(x)
+ // = sin((k * pi/128 + y) / cos((k * pi/128 + y)
+ // = (cos(y) * sin(k*pi/128) + sin(y) * cos(k*pi/128)) /
+ // / (cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128))
+ // = (sin(k*pi/128) + tan(y) * cos(k*pi/128)) /
+ // / (cos(k*pi/128) - tan(y) * sin(k*pi/128))
+ DoubleDouble cos_k_tan_y = fputil::quick_mult(tan_y, cos_k);
+ DoubleDouble msin_k_tan_y = fputil::quick_mult(tan_y, msin_k);
+
+ // num_dd = sin(k*pi/128) + tan(y) * cos(k*pi/128)
+ DoubleDouble num_dd = fputil::exact_add<false>(cos_k_tan_y.hi, -msin_k.hi);
+ // den_dd = cos(k*pi/128) - tan(y) * sin(k*pi/128)
+ DoubleDouble den_dd = fputil::exact_add<false>(msin_k_tan_y.hi, cos_k.hi);
+ num_dd.lo += cos_k_tan_y.lo - msin_k.lo;
+ den_dd.lo += msin_k_tan_y.lo + cos_k.lo;
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ double tan_x = (num_dd.hi + num_dd.lo) / (den_dd.hi + den_dd.lo);
+ return tan_x;
+#else
+ // Accurate test and pass for correctly rounded implementation.
+
+ // Accurate double-double division
+ DoubleDouble tan_x = fputil::div(num_dd, den_dd);
+
+ // Simple error bound: |1 / den_dd| < 2^(1 + floor(-log2(den_dd)))).
+ uint64_t den_inv = (static_cast<uint64_t>(FPBits::EXP_BIAS + 1)
+ << (FPBits::FRACTION_LEN + 1)) -
+ (FPBits(den_dd.hi).uintval() & FPBits::EXP_MASK);
+
+ // For tan_x = (num_dd + err) / (den_dd + err), the error is bounded by:
+ // | tan_x - num_dd / den_dd | <= err * ( 1 + | tan_x * den_dd | ).
+ double tan_err =
+ err * fputil::multiply_add(FPBits(den_inv).get_val(),
+ FPBits(tan_x.hi).abs().get_val(), 1.0);
+
+ double err_higher = tan_x.lo + tan_err;
+ double err_lower = tan_x.lo - tan_err;
+
+ double tan_upper = tan_x.hi + err_higher;
+ double tan_lower = tan_x.hi + err_lower;
+
+ // Ziv's rounding test.
+ if (LIBC_LIKELY(tan_upper == tan_lower))
+ return tan_upper;
+
+ Float128 u_f128;
+ if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT))
+ u_f128 = range_reduction_small_f128(x);
+ else
+ u_f128 = range_reduction_large.accurate();
+
+ Float128 tan_u = tan_eval(u_f128);
+
+ auto get_sin_k = [](unsigned kk) -> Float128 {
+ unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63);
+ Float128 ans = SIN_K_PI_OVER_128_F128[idx];
+ if (kk & 128)
+ ans.sign = Sign::NEG;
+ return ans;
+ };
+
+ // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128).
+ Float128 sin_k_f128 = get_sin_k(k);
+ Float128 cos_k_f128 = get_sin_k(k + 64);
+ Float128 msin_k_f128 = get_sin_k(k + 128);
+
+ // num_f128 = sin(k*pi/128) + tan(y) * cos(k*pi/128)
+ Float128 num_f128 =
+ fputil::quick_add(sin_k_f128, fputil::quick_mul(cos_k_f128, tan_u));
+ // den_f128 = cos(k*pi/128) - tan(y) * sin(k*pi/128)
+ Float128 den_f128 =
+ fputil::quick_add(cos_k_f128, fputil::quick_mul(msin_k_f128, tan_u));
+
+ // tan(x) = (sin(k*pi/128) + tan(y) * cos(k*pi/128)) /
+ // / (cos(k*pi/128) - tan(y) * sin(k*pi/128))
+ // TODO: The initial seed 1.0/den_dd.hi for Newton-Raphson reciprocal can be
+ // reused from DoubleDouble fputil::div in the fast pass.
+ Float128 result = newton_raphson_div(num_f128, den_f128, 1.0 / den_dd.hi);
+
+ // TODO: Add assertion if Ziv's accuracy tests fail in debug mode.
+ // https://github.com/llvm/llvm-project/issues/96452.
+ return static_cast<double>(result);
+
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_TAN_H
diff --git a/libc/src/__support/math/tanf.h b/libc/src/__support/math/tanf.h
new file mode 100644
index 0000000..139de3c5
--- /dev/null
+++ b/libc/src/__support/math/tanf.h
@@ -0,0 +1,164 @@
+//===-- Single-precision tan function -------------------------------------===//
+//
+// 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_TANF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_TANF_H
+
+#include "sincosf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace tanf_internal {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+// Exceptional cases for tanf.
+LIBC_INLINE_VAR constexpr size_t N_EXCEPTS = 6;
+
+LIBC_INLINE_VAR constexpr fputil::ExceptValues<float, N_EXCEPTS> TANF_EXCEPTS{{
+ // (inputs, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x1.ada6aap27, tan(x) = 0x1.e80304p-3 (RZ)
+ {0x4d56d355, 0x3e740182, 1, 0, 0},
+ // x = 0x1.862064p33, tan(x) = -0x1.8dee56p-3 (RZ)
+ {0x50431032, 0xbe46f72b, 0, 1, 1},
+ // x = 0x1.af61dap48, tan(x) = 0x1.60d1c6p-2 (RZ)
+ {0x57d7b0ed, 0x3eb068e3, 1, 0, 1},
+ // x = 0x1.0088bcp52, tan(x) = 0x1.ca1edp0 (RZ)
+ {0x5980445e, 0x3fe50f68, 1, 0, 0},
+ // x = 0x1.f90dfcp72, tan(x) = 0x1.597f9cp-1 (RZ)
+ {0x63fc86fe, 0x3f2cbfce, 1, 0, 0},
+ // x = 0x1.a6ce12p86, tan(x) = -0x1.c5612ep-1 (RZ)
+ {0x6ad36709, 0xbf62b097, 0, 1, 0},
+}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace tanf_internal
+
+LIBC_INLINE static float tanf(float x) {
+ using namespace tanf_internal;
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+ uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU;
+
+ // |x| < pi/32
+ if (LIBC_UNLIKELY(x_abs <= 0x3dc9'0fdbU)) {
+ double xd = static_cast<double>(x);
+
+ // |x| < 0x1.0p-12f
+ if (LIBC_UNLIKELY(x_abs < 0x3980'0000U)) {
+ if (LIBC_UNLIKELY(x_abs == 0U)) {
+ // For signed zeros.
+ return x;
+ }
+ // When |x| < 2^-12, the relative error of the approximation tan(x) ~ x
+ // is:
+ // |tan(x) - x| / |tan(x)| < |x^3| / (3|x|)
+ // = x^2 / 3
+ // < 2^-25
+ // < epsilon(1)/2.
+ // So the correctly rounded values of tan(x) are:
+ // = x + sign(x)*eps(x) if rounding mode = FE_UPWARD and x is positive,
+ // or (rounding mode = FE_DOWNWARD and x is
+ // negative),
+ // = x otherwise.
+ // To simplify the rounding decision and make it more efficient, we use
+ // fma(x, 2^-25, x) instead.
+ // Note: to use the formula x + 2^-25*x to decide the correct rounding, we
+ // do need fma(x, 2^-25, x) to prevent underflow caused by 2^-25*x when
+ // |x| < 2^-125. For targets without FMA instructions, we simply use
+ // double for intermediate results as it is more efficient than using an
+ // emulated version of FMA.
+#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
+ return fputil::multiply_add(x, 0x1.0p-25f, x);
+#else
+ return static_cast<float>(fputil::multiply_add(xd, 0x1.0p-25, xd));
+#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ }
+
+ // |x| < pi/32
+ double xsq = xd * xd;
+
+ // Degree-9 minimax odd polynomial of tan(x) generated by Sollya with:
+ // > P = fpminimax(tan(x)/x, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/32]);
+ double result =
+ fputil::polyeval(xsq, 1.0, 0x1.555555553d022p-2, 0x1.111111ce442c1p-3,
+ 0x1.ba180a6bbdecdp-5, 0x1.69c0a88a0b71fp-6);
+ return static_cast<float>(xd * result);
+ }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ bool x_sign = xbits.uintval() >> 31;
+ // Check for exceptional values
+ if (LIBC_UNLIKELY(x_abs == 0x3f8a1f62U)) {
+ // |x| = 0x1.143ec4p0
+ float sign = x_sign ? -1.0f : 1.0f;
+
+ // volatile is used to prevent compiler (gcc) from optimizing the
+ // computation, making the results incorrect in different rounding modes.
+ volatile float tmp = 0x1.ddf9f4p0f;
+ tmp = fputil::multiply_add(sign, tmp, sign * 0x1.1p-24f);
+
+ return tmp;
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ // |x| > 0x1.ada6a8p+27f
+ if (LIBC_UNLIKELY(x_abs > 0x4d56'd354U)) {
+ // Inf or NaN
+ if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ if (x_abs == 0x7f80'0000U) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ }
+ return x + FPBits::quiet_nan().get_val();
+ }
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ // Other large exceptional values
+ if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign);
+ LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ }
+
+ // For |x| >= pi/32, we use the definition of tan(x) function:
+ // tan(x) = sin(x) / cos(x)
+ // The we follow the same computations of sin(x) and cos(x) as sinf, cosf,
+ // and sincosf.
+
+ double xd = static_cast<double>(x);
+ double sin_k, cos_k, sin_y, cosm1_y;
+
+ sincosf_eval(xd, x_abs, sin_k, cos_k, sin_y, cosm1_y);
+ // tan(x) = sin(x) / cos(x)
+ // = (sin_y * cos_k + cos_y * sin_k) / (cos_y * cos_k - sin_y * sin_k)
+ using fputil::multiply_add;
+ return static_cast<float>(
+ multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
+ multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_TANF_H
diff --git a/libc/src/__support/threads/fork_callbacks.cpp b/libc/src/__support/threads/fork_callbacks.cpp
index b050b171..49fb41a 100644
--- a/libc/src/__support/threads/fork_callbacks.cpp
+++ b/libc/src/__support/threads/fork_callbacks.cpp
@@ -22,7 +22,6 @@ struct ForkCallbackTriple {
ForkCallback *prepare = nullptr;
ForkCallback *parent = nullptr;
ForkCallback *child = nullptr;
- constexpr ForkCallbackTriple() = default;
};
class AtForkCallbackManager {
diff --git a/libc/src/__support/wchar/CMakeLists.txt b/libc/src/__support/wchar/CMakeLists.txt
index aed1d53..304b123 100644
--- a/libc/src/__support/wchar/CMakeLists.txt
+++ b/libc/src/__support/wchar/CMakeLists.txt
@@ -20,12 +20,10 @@ add_header_library(
.character_converter
)
-add_object_library(
+add_header_library(
character_converter
HDRS
character_converter.h
- SRCS
- character_converter.cpp
DEPENDS
libc.hdr.errno_macros
libc.hdr.types.char8_t
@@ -36,12 +34,10 @@ add_object_library(
.mbstate
)
-add_object_library(
+add_header_library(
wcrtomb
HDRS
wcrtomb.h
- SRCS
- wcrtomb.cpp
DEPENDS
libc.hdr.errno_macros
libc.hdr.types.char32_t
@@ -49,6 +45,7 @@ add_object_library(
libc.hdr.types.wchar_t
libc.src.__support.error_or
libc.src.__support.common
+ libc.src.__support.macros.null_check
.character_converter
.mbstate
)
diff --git a/libc/src/__support/wchar/character_converter.cpp b/libc/src/__support/wchar/character_converter.cpp
deleted file mode 100644
index 2667288..0000000
--- a/libc/src/__support/wchar/character_converter.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//===-- Implementation of a class for conversion --------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "hdr/errno_macros.h"
-#include "hdr/types/char32_t.h"
-#include "hdr/types/char8_t.h"
-#include "hdr/types/size_t.h"
-#include "src/__support/CPP/bit.h"
-#include "src/__support/common.h"
-#include "src/__support/error_or.h"
-#include "src/__support/math_extras.h"
-#include "src/__support/wchar/mbstate.h"
-
-#include "character_converter.h"
-
-namespace LIBC_NAMESPACE_DECL {
-namespace internal {
-
-// This is for utf-8 bytes other than the first byte
-constexpr size_t ENCODED_BITS_PER_UTF8 = 6;
-// The number of bits per utf-8 byte that actually encode character
-// Information not metadata (# of bits excluding the byte headers)
-constexpr uint32_t MASK_ENCODED_BITS =
- mask_trailing_ones<uint32_t, ENCODED_BITS_PER_UTF8>();
-// Maximum value for utf-32 for a utf-8 sequence of a given length
-constexpr char32_t MAX_VALUE_PER_UTF8_LEN[] = {0x7f, 0x7ff, 0xffff, 0x10ffff};
-constexpr int MAX_UTF8_LENGTH = 4;
-
-CharacterConverter::CharacterConverter(mbstate *mbstate) { state = mbstate; }
-
-void CharacterConverter::clear() {
- state->partial = 0;
- state->bytes_stored = 0;
- state->total_bytes = 0;
-}
-
-bool CharacterConverter::isFull() {
- return state->bytes_stored == state->total_bytes && state->total_bytes != 0;
-}
-
-bool CharacterConverter::isEmpty() { return state->bytes_stored == 0; }
-
-bool CharacterConverter::isValidState() {
- if (state->total_bytes > MAX_UTF8_LENGTH)
- return false;
-
- const char32_t max_utf32_value =
- state->total_bytes == 0 ? 0
- : MAX_VALUE_PER_UTF8_LEN[state->total_bytes - 1];
- return state->bytes_stored <= state->total_bytes &&
- state->partial <= max_utf32_value;
-}
-
-int CharacterConverter::push(char8_t utf8_byte) {
- uint8_t num_ones = static_cast<uint8_t>(cpp::countl_one(utf8_byte));
- // Checking the first byte if first push
- if (isEmpty()) {
- // UTF-8 char has 1 byte total
- if (num_ones == 0) {
- state->total_bytes = 1;
- }
- // UTF-8 char has 2 through 4 bytes total
- else if (num_ones >= 2 && num_ones <= 4) {
- /* Since the format is 110xxxxx, 1110xxxx, and 11110xxx for 2, 3, and 4,
- we will make the base mask with 7 ones and right shift it as necessary. */
- constexpr size_t SIGNIFICANT_BITS = 7;
- char8_t base_mask =
- static_cast<char8_t>(mask_trailing_ones<uint8_t, SIGNIFICANT_BITS>());
- state->total_bytes = num_ones;
- utf8_byte &= (base_mask >> num_ones);
- }
- // Invalid first byte
- else {
- // bytes_stored and total_bytes will always be 0 here
- state->partial = static_cast<char32_t>(0);
- return EILSEQ;
- }
- state->partial = static_cast<char32_t>(utf8_byte);
- state->bytes_stored++;
- return 0;
- }
- // Any subsequent push
- // Adding 6 more bits so need to left shift
- if (num_ones == 1 && !isFull()) {
- char32_t byte = utf8_byte & MASK_ENCODED_BITS;
- state->partial = state->partial << ENCODED_BITS_PER_UTF8;
- state->partial |= byte;
- state->bytes_stored++;
- return 0;
- }
-
- // Invalid byte -> reset the state
- clear();
- return EILSEQ;
-}
-
-int CharacterConverter::push(char32_t utf32) {
- // we can't be partially through a conversion when pushing a utf32 value
- if (!isEmpty())
- return -1;
-
- state->partial = utf32;
-
- // determine number of utf-8 bytes needed to represent this utf32 value
- for (uint8_t i = 0; i < MAX_UTF8_LENGTH; i++) {
- if (state->partial <= MAX_VALUE_PER_UTF8_LEN[i]) {
- state->total_bytes = i + 1;
- state->bytes_stored = i + 1;
- return 0;
- }
- }
-
- // `utf32` contains a value that is too large to actually represent a valid
- // unicode character
- clear();
- return EILSEQ;
-}
-
-ErrorOr<char32_t> CharacterConverter::pop_utf32() {
- // If pop is called too early, do not reset the state, use error to determine
- // whether enough bytes have been pushed
- if (!isFull())
- return Error(-1);
- char32_t utf32 = state->partial;
- // reset if successful pop
- clear();
- return utf32;
-}
-
-ErrorOr<char8_t> CharacterConverter::pop_utf8() {
- if (isEmpty())
- return Error(-1);
-
- constexpr char8_t FIRST_BYTE_HEADERS[] = {0, 0xC0, 0xE0, 0xF0};
- constexpr char8_t CONTINUING_BYTE_HEADER = 0x80;
-
- char32_t output;
-
- // Shift to get the next 6 bits from the utf32 encoding
- const size_t shift_amount = (state->bytes_stored - 1) * ENCODED_BITS_PER_UTF8;
- if (isFull()) {
- /*
- Choose the correct set of most significant bits to encode the length
- of the utf8 sequence. The remaining bits contain the most significant
- bits of the unicode value of the character.
- */
- output = FIRST_BYTE_HEADERS[state->total_bytes - 1] |
- (state->partial >> shift_amount);
- } else {
- // Get the next 6 bits and format it like so: 10xxxxxx
- output = CONTINUING_BYTE_HEADER |
- ((state->partial >> shift_amount) & MASK_ENCODED_BITS);
- }
-
- state->bytes_stored--;
- if (state->bytes_stored == 0)
- clear();
-
- return static_cast<char8_t>(output);
-}
-
-template <> ErrorOr<char8_t> CharacterConverter::pop() { return pop_utf8(); }
-template <> ErrorOr<char32_t> CharacterConverter::pop() { return pop_utf32(); }
-
-template <> size_t CharacterConverter::sizeAs<char8_t>() {
- return state->total_bytes;
-}
-template <> size_t CharacterConverter::sizeAs<char32_t>() { return 1; }
-
-} // namespace internal
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/wchar/character_converter.h b/libc/src/__support/wchar/character_converter.h
index 2cc28ab..e730016 100644
--- a/libc/src/__support/wchar/character_converter.h
+++ b/libc/src/__support/wchar/character_converter.h
@@ -9,12 +9,16 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CHARACTER_CONVERTER_H
#define LLVM_LIBC_SRC___SUPPORT_CHARACTER_CONVERTER_H
+#include "hdr/errno_macros.h"
#include "hdr/types/char32_t.h"
#include "hdr/types/char8_t.h"
#include "hdr/types/size_t.h"
+
+#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/common.h"
#include "src/__support/error_or.h"
+#include "src/__support/math_extras.h"
#include "src/__support/wchar/mbstate.h"
namespace LIBC_NAMESPACE_DECL {
@@ -24,12 +28,31 @@ class CharacterConverter {
private:
mbstate *state;
+ // This is for utf-8 bytes other than the first byte
+ static constexpr size_t ENCODED_BITS_PER_UTF8 = 6;
+
+ // The number of bits per utf-8 byte that actually encode character
+ // Information not metadata (# of bits excluding the byte headers)
+ static constexpr uint32_t MASK_ENCODED_BITS =
+ mask_trailing_ones<uint32_t, ENCODED_BITS_PER_UTF8>();
+
+ // Maximum value for utf-32 for a utf-8 sequence of a given length
+ static constexpr char32_t MAX_VALUE_PER_UTF8_LEN[] = {0x7f, 0x7ff, 0xffff,
+ 0x10ffff};
+ static constexpr int MAX_UTF8_LENGTH = 4;
+
public:
- CharacterConverter(mbstate *mbstate);
+ CharacterConverter(mbstate *mbstate) : state(mbstate) {}
- void clear();
- bool isFull();
- bool isEmpty();
+ void clear() {
+ state->partial = 0;
+ state->bytes_stored = 0;
+ state->total_bytes = 0;
+ }
+ bool isFull() {
+ return state->bytes_stored == state->total_bytes && state->total_bytes != 0;
+ }
+ bool isEmpty() { return state->bytes_stored == 0; }
bool isValidState();
template <typename CharType> size_t sizeAs();
@@ -42,6 +65,141 @@ public:
template <typename CharType> ErrorOr<CharType> pop();
};
+LIBC_INLINE bool CharacterConverter::isValidState() {
+ if (state->total_bytes > MAX_UTF8_LENGTH)
+ return false;
+
+ const char32_t max_utf32_value =
+ state->total_bytes == 0 ? 0
+ : MAX_VALUE_PER_UTF8_LEN[state->total_bytes - 1];
+ return state->bytes_stored <= state->total_bytes &&
+ state->partial <= max_utf32_value;
+}
+
+LIBC_INLINE int CharacterConverter::push(char8_t utf8_byte) {
+ uint8_t num_ones = static_cast<uint8_t>(cpp::countl_one(utf8_byte));
+ // Checking the first byte if first push
+ if (isEmpty()) {
+ // UTF-8 char has 1 byte total
+ if (num_ones == 0) {
+ state->total_bytes = 1;
+ }
+ // UTF-8 char has 2 through 4 bytes total
+ else if (num_ones >= 2 && num_ones <= 4) {
+ /* Since the format is 110xxxxx, 1110xxxx, and 11110xxx for 2, 3, and 4,
+ we will make the base mask with 7 ones and right shift it as necessary. */
+ constexpr size_t SIGNIFICANT_BITS = 7;
+ char8_t base_mask =
+ static_cast<char8_t>(mask_trailing_ones<uint8_t, SIGNIFICANT_BITS>());
+ state->total_bytes = num_ones;
+ utf8_byte &= (base_mask >> num_ones);
+ }
+ // Invalid first byte
+ else {
+ // bytes_stored and total_bytes will always be 0 here
+ state->partial = static_cast<char32_t>(0);
+ return EILSEQ;
+ }
+ state->partial = static_cast<char32_t>(utf8_byte);
+ state->bytes_stored++;
+ return 0;
+ }
+ // Any subsequent push
+ // Adding 6 more bits so need to left shift
+ if (num_ones == 1 && !isFull()) {
+ char32_t byte = utf8_byte & MASK_ENCODED_BITS;
+ state->partial = state->partial << ENCODED_BITS_PER_UTF8;
+ state->partial |= byte;
+ state->bytes_stored++;
+ return 0;
+ }
+
+ // Invalid byte -> reset the state
+ clear();
+ return EILSEQ;
+}
+
+LIBC_INLINE int CharacterConverter::push(char32_t utf32) {
+ // we can't be partially through a conversion when pushing a utf32 value
+ if (!isEmpty())
+ return -1;
+
+ state->partial = utf32;
+
+ // determine number of utf-8 bytes needed to represent this utf32 value
+ for (uint8_t i = 0; i < MAX_UTF8_LENGTH; i++) {
+ if (state->partial <= MAX_VALUE_PER_UTF8_LEN[i]) {
+ state->total_bytes = i + 1;
+ state->bytes_stored = i + 1;
+ return 0;
+ }
+ }
+
+ // `utf32` contains a value that is too large to actually represent a valid
+ // unicode character
+ clear();
+ return EILSEQ;
+}
+
+LIBC_INLINE ErrorOr<char32_t> CharacterConverter::pop_utf32() {
+ // If pop is called too early, do not reset the state, use error to determine
+ // whether enough bytes have been pushed
+ if (!isFull())
+ return Error(-1);
+ char32_t utf32 = state->partial;
+ // reset if successful pop
+ clear();
+ return utf32;
+}
+
+LIBC_INLINE ErrorOr<char8_t> CharacterConverter::pop_utf8() {
+ if (isEmpty())
+ return Error(-1);
+
+ constexpr char8_t FIRST_BYTE_HEADERS[] = {0, 0xC0, 0xE0, 0xF0};
+ constexpr char8_t CONTINUING_BYTE_HEADER = 0x80;
+
+ char32_t output;
+
+ // Shift to get the next 6 bits from the utf32 encoding
+ const size_t shift_amount = (state->bytes_stored - 1) * ENCODED_BITS_PER_UTF8;
+ if (isFull()) {
+ /*
+ Choose the correct set of most significant bits to encode the length
+ of the utf8 sequence. The remaining bits contain the most significant
+ bits of the unicode value of the character.
+ */
+ output = FIRST_BYTE_HEADERS[state->total_bytes - 1] |
+ (state->partial >> shift_amount);
+ } else {
+ // Get the next 6 bits and format it like so: 10xxxxxx
+ output = CONTINUING_BYTE_HEADER |
+ ((state->partial >> shift_amount) & MASK_ENCODED_BITS);
+ }
+
+ state->bytes_stored--;
+ if (state->bytes_stored == 0)
+ clear();
+
+ return static_cast<char8_t>(output);
+}
+
+template <> LIBC_INLINE ErrorOr<char8_t> CharacterConverter::pop() {
+ return pop_utf8();
+}
+
+template <> LIBC_INLINE ErrorOr<char32_t> CharacterConverter::pop() {
+ return pop_utf32();
+}
+
+template <> LIBC_INLINE size_t CharacterConverter::sizeAs<char8_t>() {
+ return state->total_bytes;
+}
+
+template <> LIBC_INLINE size_t CharacterConverter::sizeAs<char32_t>() {
+ return 1;
+}
+
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/wchar/wcrtomb.cpp b/libc/src/__support/wchar/wcrtomb.cpp
deleted file mode 100644
index fc54bbf..0000000
--- a/libc/src/__support/wchar/wcrtomb.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===-- Implementation of wcrtomb -----------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/wchar/wcrtomb.h"
-#include "src/__support/error_or.h"
-#include "src/__support/wchar/character_converter.h"
-#include "src/__support/wchar/mbstate.h"
-
-#include "hdr/errno_macros.h"
-#include "hdr/types/char32_t.h"
-#include "hdr/types/size_t.h"
-#include "hdr/types/wchar_t.h"
-#include "src/__support/common.h"
-#include "src/__support/libc_assert.h"
-
-namespace LIBC_NAMESPACE_DECL {
-namespace internal {
-
-ErrorOr<size_t> wcrtomb(char *__restrict s, wchar_t wc,
- mbstate *__restrict ps) {
- static_assert(sizeof(wchar_t) == 4);
-
- CharacterConverter cr(ps);
-
- if (!cr.isValidState())
- return Error(EINVAL);
-
- int status = cr.push(static_cast<char32_t>(wc));
- if (status != 0)
- return Error(status);
-
- size_t count = 0;
- while (!cr.isEmpty()) {
- auto utf8 = cr.pop_utf8(); // can never fail as long as the push succeeded
- LIBC_ASSERT(utf8.has_value());
-
- *s = utf8.value();
- s++;
- count++;
- }
- return count;
-}
-
-} // namespace internal
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/wchar/wcrtomb.h b/libc/src/__support/wchar/wcrtomb.h
index bcd39a9..98cf852 100644
--- a/libc/src/__support/wchar/wcrtomb.h
+++ b/libc/src/__support/wchar/wcrtomb.h
@@ -9,16 +9,47 @@
#ifndef LLVM_LIBC_SRC__SUPPORT_WCHAR_WCRTOMB_H
#define LLVM_LIBC_SRC__SUPPORT_WCHAR_WCRTOMB_H
-#include "hdr/types/size_t.h"
-#include "hdr/types/wchar_t.h"
#include "src/__support/error_or.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/__support/wchar/character_converter.h"
#include "src/__support/wchar/mbstate.h"
+#include "hdr/errno_macros.h"
+#include "hdr/types/char32_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_assert.h"
+
namespace LIBC_NAMESPACE_DECL {
namespace internal {
-ErrorOr<size_t> wcrtomb(char *__restrict s, wchar_t wc, mbstate *__restrict ps);
+LIBC_INLINE ErrorOr<size_t> wcrtomb(char *__restrict s, wchar_t wc,
+ mbstate *__restrict ps) {
+ LIBC_CRASH_ON_NULLPTR(s);
+ LIBC_CRASH_ON_NULLPTR(ps);
+ static_assert(sizeof(wchar_t) == 4);
+
+ CharacterConverter cr(ps);
+
+ if (!cr.isValidState())
+ return Error(EINVAL);
+
+ int status = cr.push(static_cast<char32_t>(wc));
+ if (status != 0)
+ return Error(status);
+
+ size_t count = 0;
+ while (!cr.isEmpty()) {
+ auto utf8 = cr.pop_utf8(); // can never fail as long as the push succeeded
+ LIBC_ASSERT(utf8.has_value());
+
+ *s = utf8.value();
+ s++;
+ count++;
+ }
+ return count;
+}
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/weak_avl.h b/libc/src/__support/weak_avl.h
new file mode 100644
index 0000000..31c7e31
--- /dev/null
+++ b/libc/src/__support/weak_avl.h
@@ -0,0 +1,595 @@
+//===-- Implementation header for weak AVL tree -----------------*- 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_WEAK_AVL_H
+#define LLVM_LIBC_SRC___SUPPORT_WEAK_AVL_H
+
+#include "hdr/stdint_proxy.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/utility/move.h"
+#include "src/__support/alloc-checker.h"
+#include "src/__support/libc_assert.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// A general self-balancing binary search tree where the node pointer can
+// be used as stable handles to the stored values.
+//
+// The self-balancing strategy is the Weak AVL (WAVL) tree, based on the
+// following foundational references:
+// 1. https://maskray.me/blog/2025-12-14-weak-avl-tree
+// 2. https://reviews.freebsd.org/D25480
+// 3. https://ics.uci.edu/~goodrich/teach/cs165/notes/WeakAVLTrees.pdf
+// 4. https://dl.acm.org/doi/10.1145/2689412 (Rank-Balanced Trees)
+//
+// WAVL trees belong to the rank-balanced binary search tree framework
+// (reference 4), alongside AVL and Red-Black trees.
+//
+// Key Properties of WAVL Trees:
+// 1. Relationship to Red-Black Trees: A WAVL tree can always be colored as a
+// Red-Black tree.
+// 2. Relationship to AVL Trees: An AVL tree meets all the requirements of a
+// WAVL tree. Insertion-only WAVL trees maintain the same structure as AVL
+// trees.
+//
+// Rank-Based Balancing:
+// In rank-balanced trees, each node is assigned a rank (conceptually similar
+// to height). The rank difference between a parent and its child is
+// strictly enforced to be either **1** or **2**.
+//
+// - **AVL Trees:** Rank is equivalent to height. The strict condition is that
+// there are no 2-2 nodes (a parent with rank difference 2 to both children).
+// - **WAVL Trees:** The no 2-2 node rule is relaxed for internal nodes during
+// the deletion fixup process, making WAVL trees less strictly balanced than
+// AVL trees but easier to maintain than Red-Black trees.
+//
+// Balancing Mechanics (Promotion/Demotion):
+// - **Null nodes** are considered to have rank -1.
+// - **External/leaf nodes** have rank 0.
+// - **Insertion:** Inserting a node may create a situation where a parent and
+// child have the same rank (difference 0). This is fixed by **promoting**
+// the rank of the parent and propagating the fix upwards using at most two
+// rotations (trinode fixup).
+// - **Deletion:** Deleting a node may result in a parent being 3 ranks higher
+// than a child (difference 3). This is fixed by **demoting** the parent's
+// rank and propagating the fix upwards.
+//
+// Implementation Detail:
+// The rank is **implicitly** maintained. We never store the full rank. Instead,
+// a 2-bit tag is used on each node to record the rank difference to each child:
+// - Bit cleared (0) -> Rank difference is **1**.
+// - Bit set (1) -> Rank difference is **2**.
+template <typename T> class WeakAVLNode {
+ // Data
+ T data;
+
+ // Parent pointer
+ WeakAVLNode *parent;
+
+ // Children pointers
+ WeakAVLNode *children[2];
+
+ // Flags
+ unsigned char left_rank_diff_2 : 1;
+ unsigned char right_rank_diff_2 : 1;
+
+ LIBC_INLINE bool is_leaf() {
+ return (children[0] == nullptr) && (children[1] == nullptr);
+ }
+
+ LIBC_INLINE void toggle_rank_diff_2(bool is_right) {
+ if (is_right)
+ right_rank_diff_2 ^= 1;
+ else
+ left_rank_diff_2 ^= 1;
+ }
+
+ LIBC_INLINE bool both_flags_set() const {
+ return left_rank_diff_2 && right_rank_diff_2;
+ }
+
+ LIBC_INLINE bool any_flag_set() const {
+ return left_rank_diff_2 || right_rank_diff_2;
+ }
+
+ LIBC_INLINE void clear_flags() {
+ left_rank_diff_2 = 0;
+ right_rank_diff_2 = 0;
+ }
+
+ LIBC_INLINE void set_both_flags() {
+ left_rank_diff_2 = 1;
+ right_rank_diff_2 = 1;
+ }
+
+ LIBC_INLINE WeakAVLNode(T data)
+ : data(cpp::move(data)), parent(nullptr), children{nullptr, nullptr},
+ left_rank_diff_2(0), right_rank_diff_2(0) {}
+
+ LIBC_INLINE static WeakAVLNode *create(T value) {
+ AllocChecker ac;
+ WeakAVLNode *res = new (ac) WeakAVLNode(value);
+ if (ac)
+ return res;
+ return nullptr;
+ }
+
+ // Unlink a node from tree. The corresponding flag is not updated. The node is
+ // not deleted and its pointers are not cleared.
+ // FixupSite is the lowest surviving node from which rank/flag invariants may
+ // be violated.
+ // Our tree requires value to stay in their node to maintain stable addresses.
+ // This complicates the unlink operation as the successor transplanting needs
+ // to update all the pointers and flags.
+ struct FixupSite {
+ WeakAVLNode *parent;
+ bool is_right;
+ };
+ LIBC_INLINE static FixupSite unlink(WeakAVLNode *&root, WeakAVLNode *node) {
+ bool has_left = node->children[0] != nullptr;
+ bool has_right = node->children[1] != nullptr;
+
+ // Case 0: no children
+ if (!has_left && !has_right) {
+ if (!node->parent) {
+ root = nullptr;
+ return {nullptr, false};
+ }
+ FixupSite site = {node->parent, node->parent->children[1] == node};
+ site.parent->children[site.is_right] = nullptr;
+ return site;
+ }
+
+ // Case 1: one child
+ if (has_left != has_right) {
+ WeakAVLNode *child = node->children[has_right];
+ if (!node->parent) {
+ root = child;
+ child->parent = nullptr;
+ return {nullptr, false};
+ }
+ FixupSite site = {node->parent, node->parent->children[1] == node};
+ site.parent->children[site.is_right] = child;
+ child->parent = site.parent;
+ return site;
+ }
+
+ // Case 2: two children: replace by successor (leftmost in right subtree)
+ WeakAVLNode *succ = node->children[1];
+ while (succ->children[0])
+ succ = succ->children[0];
+
+ WeakAVLNode *succ_parent = succ->parent;
+ // succ and node may be adjacent to each other, so we
+ // still need to check the exact direction of the successor.
+ bool succ_was_right = succ_parent->children[1] == succ;
+ WeakAVLNode *succ_rchild = succ->children[1];
+
+ // 1) Splice successor out of its old position (flags intentionally
+ // unchanged)
+ FixupSite site = {succ_parent, succ_was_right};
+ succ_parent->children[succ_was_right] = succ_rchild;
+ if (succ_rchild)
+ succ_rchild->parent = succ_parent;
+
+ // 2) Transplant successor into node's position
+ succ->parent = node->parent;
+ succ->left_rank_diff_2 = node->left_rank_diff_2;
+ succ->right_rank_diff_2 = node->right_rank_diff_2;
+
+ succ->children[0] = node->children[0];
+ succ->children[1] = node->children[1];
+ if (succ->children[0])
+ succ->children[0]->parent = succ;
+ if (succ->children[1])
+ succ->children[1]->parent = succ;
+
+ if (succ->parent) {
+ bool node_was_right = succ->parent->children[1] == node;
+ succ->parent->children[node_was_right] = succ;
+ } else {
+ root = succ;
+ }
+
+ // 3) If the physical removal was under `node`, fixup parent must be the
+ // successor (since `node` is deleted and successor now occupies that
+ // spot).
+ if (site.parent == node)
+ site.parent = succ;
+
+ return site;
+ }
+
+public:
+ using OptionalNodePtr = cpp::optional<WeakAVLNode *>;
+
+ LIBC_INLINE const WeakAVLNode *get_left() const { return children[0]; }
+ LIBC_INLINE const WeakAVLNode *get_right() const { return children[1]; }
+ LIBC_INLINE const T &get_data() const { return data; }
+ LIBC_INLINE bool has_rank_diff_2(bool is_right) const {
+ return is_right ? right_rank_diff_2 : left_rank_diff_2;
+ }
+
+ // Destroy the subtree rooted at node
+ LIBC_INLINE static void destroy(WeakAVLNode *node) {
+ if (!node)
+ return;
+ destroy(node->children[0]);
+ destroy(node->children[1]);
+ delete node;
+ }
+ // Rotate the subtree rooted at node in the given direction.
+ //
+ // Illustration for is_right = true (Left Rotation):
+ //
+ // (Node) (Pivot)
+ // / \ / \
+ // A (Pivot) => (Node) C
+ // / \ / \
+ // B C A B
+ //
+ LIBC_INLINE static WeakAVLNode *rotate(WeakAVLNode *&root, WeakAVLNode *node,
+ bool is_right) {
+ WeakAVLNode *pivot = node->children[is_right];
+ // Handover pivot's child
+ WeakAVLNode *grandchild = pivot->children[!is_right];
+ node->children[is_right] = grandchild;
+ if (grandchild)
+ grandchild->parent = node;
+ pivot->parent = node->parent;
+ // Pivot becomes the new root of the subtree
+ if (!node->parent) {
+ root = pivot;
+ } else {
+ bool node_is_right = node->parent->children[1] == node;
+ node->parent->children[node_is_right] = pivot;
+ }
+ pivot->children[!is_right] = node;
+ node->parent = pivot;
+ return pivot;
+ }
+
+ // Find data in the subtree rooted at root. If not found, returns
+ // OptionalNode. `Compare` returns integer values for ternary comparison.
+ // Unlike other interfaces, `find` does not modify the tree; hence we pass
+ // the `root` by value.
+ // It is assumed that the order returned by the comparator is consistent
+ // on each call.
+ template <typename Compare>
+ LIBC_INLINE static OptionalNodePtr find(WeakAVLNode *root, T data,
+ Compare comp) {
+ WeakAVLNode *cursor = root;
+ while (cursor != nullptr) {
+ int comp_result = comp(cursor->data, data);
+ if (comp_result == 0)
+ return cursor; // Node found
+ bool is_right = comp_result < 0;
+ cursor = cursor->children[is_right];
+ }
+ return cpp::nullopt;
+ }
+ // Insert data into the subtree rooted at root.
+ // Returns the node if insertion is successful or the node exists in
+ // the tree.
+ // Returns cpp::nullopt if memory allocation fails.
+ // `Compare` returns integer values for ternary comparison.
+ // It is assumed that the order returned by the comparator is consistent
+ // on each call.
+ template <typename Compare>
+ LIBC_INLINE static OptionalNodePtr find_or_insert(WeakAVLNode *&root, T data,
+ Compare comp) {
+ WeakAVLNode *parent = nullptr, *cursor = root;
+ bool is_right = false;
+ while (cursor != nullptr) {
+ parent = cursor;
+ int comp_result = comp(parent->data, data);
+ if (comp_result == 0)
+ return parent; // Node already exists
+ is_right = comp_result < 0;
+ cursor = cursor->children[is_right];
+ }
+ WeakAVLNode *allocated = create(cpp::move(data));
+ if (!allocated)
+ return cpp::nullopt;
+ WeakAVLNode *node = allocated;
+ node->parent = parent;
+
+ // Case 0: inserting into an empty tree
+ if (!parent) {
+ root = node; // Tree was empty
+ return node;
+ }
+
+ parent->children[is_right] = node;
+ // Rebalance process
+ // Case 1: both node and its sibling have rank-difference 1. So after the
+ // insertion, the node is at the same level as the parent. Promoting parent
+ // will fix the conflict of the trinodes but we may need to continue on
+ // parent.
+ //
+ // (GP) (GP)
+ // | Promote | x - 1
+ // | x -----> (P)
+ // 0 | / 1 / \
+ // (N) --- (P) ---- (N) \ 2
+ // \ 1 \
+ // (S) (S)
+ while (parent && !parent->any_flag_set()) {
+ parent->toggle_rank_diff_2(!is_right);
+ node = parent;
+ parent = node->parent;
+ if (parent)
+ is_right = (parent->children[1] == node);
+ }
+ // We finish if node has reaches the root -- otherwise, we end up with
+ // two more cases.
+ if (!parent)
+ return allocated;
+
+ // Case 2: parent does not need to be promoted as node is lower
+ // than the parent by 2 ranks.
+ // (P) (P)
+ // / \ / \
+ // 2 1 => 1 1
+ // / \ / \
+ // (N) (*) (N) (*)
+ if (parent->has_rank_diff_2(is_right)) {
+ parent->toggle_rank_diff_2(is_right);
+ return allocated;
+ }
+
+ // At this point, we know there is a violation but one-step fix is possible.
+ LIBC_ASSERT(!node->both_flags_set() &&
+ "there should be no 2-2 node along the insertion fixup path");
+
+ LIBC_ASSERT((node == allocated || node->any_flag_set()) &&
+ "Internal node must have a child with rank-difference 2, "
+ "otherwise it should have already been handled.");
+
+ // Case 3: node's sibling has rank-difference 2. And node has a 1-node
+ // along the same direction. We can do a single rotation to fix the
+ // trinode.
+ // (GP) (GP)
+ // 0 | X Rotate |
+ // (N) ----- (P) => (N)
+ // 1 / \ 2 \ 2 1 / \ 1
+ // (C1) \ \ (C1) (P)
+ // (C2) (S) 1 / \ 1
+ // (C2) (S)
+ if (node->has_rank_diff_2(!is_right)) {
+ WeakAVLNode *new_subroot = rotate(root, parent, is_right);
+ new_subroot->clear_flags();
+ parent->clear_flags();
+ return allocated;
+ }
+ // Case 4: node's sibling has rank-difference 2. And node has a 1-node
+ // along the opposite direction. We need a double rotation to fix the
+ // trinode.
+ // (GP) (GP)
+ // 0 | X Zig-Zag | X
+ // (N) ----- (P) => (C1)
+ // 2 / \ 1 \ 2 1 / \ 1
+ // / (C1) \ (N) (P)
+ // (C2) L / \ R (S) 1 / \ L R / \ 1
+ // (A) (B) (C2) (A)(B) (S)
+ // (mirrored)
+ // (GP) (GP)
+ // X | 0 Zig-Zag | X
+ // (P) ----- (N) => (C1)
+ // 2 / 1 / \ 2 1 / \ 1
+ // / (C1) \ (P) (N)
+ // (S) L / \ R (C2) 1 / \ L R / \ 1
+ // (A) (B) (S)(A) (B)(C2)
+
+ WeakAVLNode *subroot1 = rotate(root, node, !is_right); // First rotation
+ [[maybe_unused]] WeakAVLNode *subroot2 =
+ rotate(root, parent, is_right); // Second rotation
+ LIBC_ASSERT(subroot1 == subroot2 &&
+ "Subroots after double rotation should be the same");
+ bool subroot_left_diff_2 = subroot1->left_rank_diff_2;
+ bool subroot_right_diff_2 = subroot1->right_rank_diff_2;
+ node->clear_flags();
+ parent->clear_flags();
+ subroot1->clear_flags();
+ // Select destinations
+ WeakAVLNode *dst_left = is_right ? parent : node;
+ WeakAVLNode *dst_right = is_right ? node : parent;
+ // Masked toggles
+ if (subroot_left_diff_2)
+ dst_left->toggle_rank_diff_2(true);
+
+ if (subroot_right_diff_2)
+ dst_right->toggle_rank_diff_2(false);
+ return allocated;
+ }
+
+ // Erase the node from the tree rooted at root.
+ LIBC_INLINE static void erase(WeakAVLNode *&root, WeakAVLNode *node) {
+ // Unlink the node from the tree
+ auto [cursor, is_right] = unlink(root, node);
+ delete node;
+ WeakAVLNode *sibling = nullptr;
+ while (cursor) {
+ // Case 0. cursor previously had rank-difference 1 on the side of the
+ // deleted node. We can simply update the rank-difference and stop.
+ // Notice that this step may create 2-2 nodes, thus deviate from "strong"
+ // AVL tree.
+ //
+ // (C) (C)
+ // X / \ 1 => X / \
+ // (*) (D) (*) \ 2
+ // (D)
+ if (!cursor->has_rank_diff_2(is_right)) {
+ cursor->toggle_rank_diff_2(is_right);
+ // If we created a 2-2 leaf, we must demote it and continue.
+ // Otherwise, we are done as the internal node becomes a 2-2 node and
+ // there is no further violation upwards.
+ if (!cursor->both_flags_set() || !cursor->is_leaf())
+ return;
+ // Clear flags for demotion.
+ cursor->clear_flags();
+ }
+
+ // Case 1. cursor previously had rank-difference 2 on the side of the
+ // deleted node. Now it has rank-difference 3, which violates the
+ // weak-AVL property. We found that we have a sibling with rank-difference
+ // 2, so we can demote cursor and continue upwards.
+ //
+ // (P) (P)
+ // | X | (X + 1)
+ // (C) |
+ // / \ => (C)
+ // 2 / \ 1 / \
+ // (*) \ 3 (*) \ 2
+ // (D) (D)
+ else if (cursor->has_rank_diff_2(!is_right))
+ cursor->toggle_rank_diff_2(!is_right);
+
+ // Case 2. continue from Case 1; but the sibling has rank-difference 1.
+ // However, we found that the sibling is a 2-2 node. We demote both
+ // sibling and cursor, and continue upwards. We break for other cases if
+ // sibling cannot be demoted.
+ //
+ // (P) (P)
+ // | X | (X + 1)
+ // (C) |
+ // 1 / \ => (C)
+ // (S) \ 1 / \
+ // / \ \ 3 (S) \ 2
+ // 2 / \ 2 (D) 1 / \ 1 (D)
+ // (*) (*) (*) (*)
+ else {
+ sibling = cursor->children[!is_right];
+ LIBC_ASSERT(sibling && "rank-difference 1 sibling cannot be empty");
+ if (sibling->both_flags_set())
+ sibling->clear_flags();
+ else
+ break;
+ }
+
+ // Update cursor to move upwards
+ if (cursor->parent)
+ is_right = (cursor->parent->children[1] == cursor);
+ cursor = cursor->parent;
+ }
+
+ // Either cursor is nullptr (we reached the root), or sibling has
+ // rank-difference 1.
+ if (!cursor)
+ return;
+ LIBC_ASSERT(sibling && "rank-difference 1 sibling must exist");
+ bool sibling_is_right = !is_right; // Rename for clarity
+
+ // Case 3. continue from Case 2; but the sibling cannot be demoted.
+ // Sibling has a node T along the same direction with rank-difference 1.
+ //
+ // (P) (P)
+ // | X | X
+ // (C) (S)
+ // 1 / \ Rotate 2 / \ 1
+ // (S) \ => / (C)
+ // 1 / \ Y \ 3 (T) Y / \ 2
+ // (T) \ (D) (*) \
+ // (*) (D)
+ if (!sibling->has_rank_diff_2(sibling_is_right)) {
+ WeakAVLNode *new_subroot = rotate(root, cursor, sibling_is_right);
+ LIBC_ASSERT(new_subroot == sibling &&
+ "sibling should become the subtree root");
+ // Update flags
+ bool sibling_alter_child_has_rank_diff_2 =
+ new_subroot->has_rank_diff_2(!sibling_is_right);
+ new_subroot->clear_flags();
+ new_subroot->toggle_rank_diff_2(sibling_is_right);
+
+ // Cursor only needs to be updated if it becomes a 2-2 node
+ if (sibling_alter_child_has_rank_diff_2) {
+ // Demote a 2-2 cursor if it is a leaf
+ bool cursor_is_leaf = cursor->is_leaf();
+ if (cursor_is_leaf)
+ cursor->clear_flags();
+
+ // If cursor is now a leaf, then its parent (which should be the pivot)
+ // becomes a 2-2 node after cursor's demotion. Otherwise, cursor itself
+ // should become a 2-2 node.
+ WeakAVLNode *candidate = cursor_is_leaf ? new_subroot : cursor;
+ candidate->toggle_rank_diff_2(sibling_is_right ^ cursor_is_leaf);
+ LIBC_ASSERT(candidate->both_flags_set() &&
+ "target node should become a 2-2 node.");
+ }
+ }
+ // Case 4. continue from Case 3; but rank-difference 1 child T of sibling
+ // is on the opposite direction.
+ //
+ // (P) (P)
+ // | X | X
+ // (C) Zig-Zag (T)
+ // 1 / \ => / \
+ // (S) \ 2 / \ 2
+ // / \ 1 \ 3 (S) (C)
+ // 2 / (T) (D) 1 / Y \ / Z \ 1
+ // (*) Y / \ Z (*) (A)(B) (D)
+ // (A) (B)
+ else {
+ WeakAVLNode *target_child = rotate(root, sibling, !sibling_is_right);
+ bool subtree_left_diff_2 = target_child->left_rank_diff_2;
+ bool subtree_right_diff_2 = target_child->right_rank_diff_2;
+ [[maybe_unused]] WeakAVLNode *new_subroot =
+ rotate(root, cursor, sibling_is_right);
+ LIBC_ASSERT(new_subroot == target_child &&
+ "target_child should become the subtree root");
+ // Set flags
+ target_child->set_both_flags();
+ cursor->clear_flags();
+ sibling->clear_flags();
+ // Select destinations
+ WeakAVLNode *dst_left = sibling_is_right ? cursor : sibling;
+ WeakAVLNode *dst_right = sibling_is_right ? sibling : cursor;
+ // Masked toggles
+ if (subtree_left_diff_2)
+ dst_left->toggle_rank_diff_2(true);
+ if (subtree_right_diff_2)
+ dst_right->toggle_rank_diff_2(false);
+ }
+ }
+
+ enum struct WalkType {
+ PreOrder,
+ InOrder,
+ PostOrder,
+ Leaf,
+ };
+ template <typename Func>
+ LIBC_INLINE static void walk(WeakAVLNode *node, Func func) {
+ if (!node)
+ return;
+
+ if (node->is_leaf()) {
+ func(node, WalkType::Leaf);
+ return;
+ }
+
+ func(node, WalkType::PreOrder);
+
+ if (node->children[0])
+ walk(node->children[0], func);
+
+ func(node, WalkType::InOrder);
+
+ if (node->children[1])
+ walk(node->children[1], func);
+ func(node, WalkType::PostOrder);
+ }
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_WEAK_AVL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 6de4cf3..21c3a86 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -249,8 +249,7 @@ add_entrypoint_object(
HDRS
../dfmaf128.h
DEPENDS
- libc.src.__support.FPUtil.fma
- libc.src.__support.macros.properties.types
+ libc.src.__support.math.dfmaf128
)
add_entrypoint_object(
@@ -260,7 +259,7 @@ add_entrypoint_object(
HDRS
../dfmal.h
DEPENDS
- libc.src.__support.FPUtil.fma
+ libc.src.__support.math.dfmal
)
add_entrypoint_object(
@@ -373,16 +372,8 @@ add_entrypoint_object(
HDRS
../sinf.h
DEPENDS
- libc.src.__support.math.range_reduction
- libc.src.__support.math.sincosf_utils
+ libc.src.__support.math.sinf
libc.src.errno.errno
- libc.src.__support.FPUtil.basic_operations
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.fma
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.optimization
)
add_entrypoint_object(
@@ -392,16 +383,7 @@ add_entrypoint_object(
HDRS
../sinf16.h
DEPENDS
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.types
- libc.src.__support.math.sincosf16_utils
+ libc.src.__support.math.sinf16
COMPILE_OPTIONS
${libc_opt_high_flag}
)
@@ -433,14 +415,7 @@ add_entrypoint_object(
HDRS
../sinpif.h
DEPENDS
- libc.src.__support.math.sincosf_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.fma
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.common
- libc.src.__support.macros.optimization
+ libc.src.__support.math.sinpif
)
add_entrypoint_object(
@@ -486,16 +461,8 @@ add_entrypoint_object(
HDRS
../tan.h
DEPENDS
- libc.src.__support.math.range_reduction_double
- libc.hdr.errno_macros
+ libc.src.__support.math.tan
libc.src.errno.errno
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.macros.optimization
)
add_entrypoint_object(
@@ -505,17 +472,8 @@ add_entrypoint_object(
HDRS
../tanf.h
DEPENDS
- libc.src.__support.math.range_reduction
- libc.src.__support.math.sincosf_utils
+ libc.src.__support.math.tanf
libc.src.errno.errno
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.nearest_integer
- libc.src.__support.FPUtil.fma
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.macros.optimization
)
add_entrypoint_object(
@@ -1762,7 +1720,7 @@ add_entrypoint_object(
HDRS
../ilogb.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.ilogb
)
add_entrypoint_object(
@@ -1772,7 +1730,7 @@ add_entrypoint_object(
HDRS
../ilogbf.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.ilogbf
)
add_entrypoint_object(
@@ -1782,7 +1740,8 @@ add_entrypoint_object(
HDRS
../ilogbl.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.ilogbl
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -1802,8 +1761,7 @@ add_entrypoint_object(
HDRS
../ilogbf128.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.ilogbf128
)
add_entrypoint_object(
@@ -1827,7 +1785,7 @@ add_entrypoint_object(
HDRS
../llogb.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.llogb
)
add_entrypoint_object(
@@ -1837,7 +1795,8 @@ add_entrypoint_object(
HDRS
../llogbf.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.llogbf
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -1857,8 +1816,7 @@ add_entrypoint_object(
HDRS
../llogbf16.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.llogbf16
)
add_entrypoint_object(
@@ -1868,8 +1826,7 @@ add_entrypoint_object(
HDRS
../llogbf128.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.llogbf128
)
add_entrypoint_object(
@@ -1957,16 +1914,7 @@ add_entrypoint_object(
HDRS
../log10.h
DEPENDS
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.integer_literals
- libc.src.__support.macros.optimization
- libc.src.__support.math.common_constants
- libc.src.__support.math.log_range_reduction
+ libc.src.__support.math.log10
)
add_entrypoint_object(
@@ -2011,15 +1959,7 @@ add_entrypoint_object(
HDRS
../log1p.h
DEPENDS
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.integer_literals
- libc.src.__support.macros.optimization
- libc.src.__support.math.common_constants
+ libc.src.__support.math.log1p
)
add_entrypoint_object(
@@ -2045,16 +1985,7 @@ add_entrypoint_object(
HDRS
../log2.h
DEPENDS
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.dyadic_float
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.integer_literals
- libc.src.__support.macros.optimization
- libc.src.__support.math.common_constants
- libc.src.__support.math.log_range_reduction
+ libc.src.__support.math.log2
)
add_entrypoint_object(
@@ -2110,14 +2041,7 @@ add_entrypoint_object(
HDRS
../logf.h
DEPENDS
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.cpu_features
- libc.src.__support.math.common_constants
+ libc.src.__support.math.logf
)
add_entrypoint_object(
@@ -2127,17 +2051,7 @@ add_entrypoint_object(
HDRS
../logf16.h
DEPENDS
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.cast
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.macros.optimization
- libc.src.__support.macros.properties.cpu_features
- libc.src.__support.math.expxf16_utils
+ libc.src.__support.math.logf16
)
add_entrypoint_object(
@@ -2173,7 +2087,8 @@ add_entrypoint_object(
HDRS
../logbf.h
DEPENDS
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.logbf
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -2193,8 +2108,8 @@ add_entrypoint_object(
HDRS
../logbf16.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.logbf16
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -2204,8 +2119,8 @@ add_entrypoint_object(
HDRS
../logbf128.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.manipulation_functions
+ libc.src.__support.math.logbf128
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -3067,7 +2982,7 @@ add_entrypoint_object(
HDRS
../sqrt.h
DEPENDS
- libc.src.__support.FPUtil.sqrt
+ libc.src.__support.math.sqrt
)
@@ -3098,7 +3013,7 @@ add_entrypoint_object(
HDRS
../sqrtf16.h
DEPENDS
- libc.src.__support.FPUtil.sqrt
+ libc.src.__support.math.sqrtf16
)
add_entrypoint_object(
@@ -3269,12 +3184,8 @@ add_entrypoint_object(
HDRS
../hypotf.h
DEPENDS
- libc.src.__support.FPUtil.double_double
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.sqrt
- libc.src.__support.macros.optimization
+ libc.src.__support.math.hypotf
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -4194,10 +4105,7 @@ add_entrypoint_object(
HDRS
../sinhf.h
DEPENDS
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.optimization
- libc.src.__support.math.sinhfcoshf_utils
+ libc.src.__support.math.sinhf
)
add_entrypoint_object(
@@ -4207,14 +4115,7 @@ add_entrypoint_object(
HDRS
../sinhf16.h
DEPENDS
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.optimization
- libc.src.__support.math.expxf16_utils
+ libc.src.__support.math.sinhf16
)
add_entrypoint_object(
@@ -5136,8 +5037,7 @@ add_entrypoint_object(
HDRS
../f16fma.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.fma
+ libc.src.__support.math.f16fma
)
add_entrypoint_object(
@@ -5158,8 +5058,7 @@ add_entrypoint_object(
HDRS
../f16fmal.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.fma
+ libc.src.__support.math.f16fmal
)
add_entrypoint_object(
@@ -5202,8 +5101,8 @@ add_entrypoint_object(
HDRS
../f16sqrtl.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.sqrt
+ libc.src.__support.math.f16sqrtl
+ libc.src.errno.errno
)
add_entrypoint_object(
@@ -5224,7 +5123,7 @@ add_entrypoint_object(
HDRS
../fsqrt.h
DEPENDS
- libc.src.__support.FPUtil.generic.sqrt
+ libc.src.__support.math.fsqrt
)
add_entrypoint_object(
@@ -5234,7 +5133,7 @@ add_entrypoint_object(
HDRS
../fsqrtl.h
DEPENDS
- libc.src.__support.FPUtil.generic.sqrt
+ libc.src.__support.math.fsqrtl
)
add_entrypoint_object(
@@ -5244,8 +5143,8 @@ add_entrypoint_object(
HDRS
../fsqrtf128.h
DEPENDS
- libc.src.__support.macros.properties.types
- libc.src.__support.FPUtil.generic.sqrt
+ libc.src.__support.math.fsqrtf128
+ libc.src.errno.errno
)
add_entrypoint_object(
diff --git a/libc/src/math/generic/asin.cpp b/libc/src/math/generic/asin.cpp
index b5ba9ea..865c44d 100644
--- a/libc/src/math/generic/asin.cpp
+++ b/libc/src/math/generic/asin.cpp
@@ -11,266 +11,6 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(double, asin, (double x)) {
- using namespace asin_internal;
- using FPBits = fputil::FPBits<double>;
-
- FPBits xbits(x);
- int x_exp = xbits.get_biased_exponent();
-
- // |x| < 0.5.
- if (x_exp < FPBits::EXP_BIAS - 1) {
- // |x| < 2^-26.
- if (LIBC_UNLIKELY(x_exp < FPBits::EXP_BIAS - 26)) {
- // When |x| < 2^-26, the relative error of the approximation asin(x) ~ x
- // is:
- // |asin(x) - x| / |asin(x)| < |x^3| / (6|x|)
- // = x^2 / 6
- // < 2^-54
- // < epsilon(1)/2.
- // So the correctly rounded values of asin(x) are:
- // = x + sign(x)*eps(x) if rounding mode = FE_TOWARDZERO,
- // or (rounding mode = FE_UPWARD and x is
- // negative),
- // = x otherwise.
- // To simplify the rounding decision and make it more efficient, we use
- // fma(x, 2^-54, x) instead.
- // Note: to use the formula x + 2^-54*x to decide the correct rounding, we
- // do need fma(x, 2^-54, x) to prevent underflow caused by 2^-54*x when
- // |x| < 2^-1022. For targets without FMA instructions, when x is close to
- // denormal range, we normalize x,
-#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
- return x;
-#elif defined(LIBC_TARGET_CPU_HAS_FMA_DOUBLE)
- return fputil::multiply_add(x, 0x1.0p-54, x);
-#else
- if (xbits.abs().uintval() == 0)
- return x;
- // Get sign(x) * min_normal.
- FPBits eps_bits = FPBits::min_normal();
- eps_bits.set_sign(xbits.sign());
- double eps = eps_bits.get_val();
- double normalize_const = (x_exp == 0) ? eps : 0.0;
- double scaled_normal =
- fputil::multiply_add(x + normalize_const, 0x1.0p54, eps);
- return fputil::multiply_add(scaled_normal, 0x1.0p-54, -normalize_const);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return x * asin_eval(x * x);
-#else
- unsigned idx;
- DoubleDouble x_sq = fputil::exact_mult(x, x);
- double err = xbits.abs().get_val() * 0x1.0p-51;
- // Polynomial approximation:
- // p ~ asin(x)/x
-
- DoubleDouble p = asin_eval(x_sq, idx, err);
- // asin(x) ~ x * (ASIN_COEFFS[idx][0] + p)
- DoubleDouble r0 = fputil::exact_mult(x, p.hi);
- double r_lo = fputil::multiply_add(x, p.lo, r0.lo);
-
- // Ziv's accuracy test.
-
- double r_upper = r0.hi + (r_lo + err);
- double r_lower = r0.hi + (r_lo - err);
-
- if (LIBC_LIKELY(r_upper == r_lower))
- return r_upper;
-
- // Ziv's accuracy test failed, perform 128-bit calculation.
-
- // Recalculate mod 1/64.
- idx = static_cast<unsigned>(fputil::nearest_integer(x_sq.hi * 0x1.0p6));
-
- // Get x^2 - idx/64 exactly. When FMA is available, double-double
- // multiplication will be correct for all rounding modes. Otherwise we use
- // Float128 directly.
- Float128 x_f128(x);
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- // u = x^2 - idx/64
- Float128 u_hi(
- fputil::multiply_add(static_cast<double>(idx), -0x1.0p-6, x_sq.hi));
- Float128 u = fputil::quick_add(u_hi, Float128(x_sq.lo));
-#else
- Float128 x_sq_f128 = fputil::quick_mul(x_f128, x_f128);
- Float128 u = fputil::quick_add(
- x_sq_f128, Float128(static_cast<double>(idx) * (-0x1.0p-6)));
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- Float128 p_f128 = asin_eval(u, idx);
- Float128 r = fputil::quick_mul(x_f128, p_f128);
-
- return static_cast<double>(r);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
- // |x| >= 0.5
-
- double x_abs = xbits.abs().get_val();
-
- // Maintaining the sign:
- constexpr double SIGN[2] = {1.0, -1.0};
- double x_sign = SIGN[xbits.is_neg()];
-
- // |x| >= 1
- if (LIBC_UNLIKELY(x_exp >= FPBits::EXP_BIAS)) {
- // x = +-1, asin(x) = +- pi/2
- if (x_abs == 1.0) {
- // return +- pi/2
- return fputil::multiply_add(x_sign, PI_OVER_TWO.hi,
- x_sign * PI_OVER_TWO.lo);
- }
- // |x| > 1, return NaN.
- if (xbits.is_quiet_nan())
- return x;
-
- // Set domain error for non-NaN input.
- if (!xbits.is_nan())
- fputil::set_errno_if_required(EDOM);
-
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- // When |x| >= 0.5, we perform range reduction as follow:
- //
- // Assume further that 0.5 <= x < 1, and let:
- // y = asin(x)
- // We will use the double angle formula:
- // cos(2y) = 1 - 2 sin^2(y)
- // and the complement angle identity:
- // x = sin(y) = cos(pi/2 - y)
- // = 1 - 2 sin^2 (pi/4 - y/2)
- // So:
- // sin(pi/4 - y/2) = sqrt( (1 - x)/2 )
- // And hence:
- // pi/4 - y/2 = asin( sqrt( (1 - x)/2 ) )
- // Equivalently:
- // asin(x) = y = pi/2 - 2 * asin( sqrt( (1 - x)/2 ) )
- // Let u = (1 - x)/2, then:
- // asin(x) = pi/2 - 2 * asin( sqrt(u) )
- // Moreover, since 0.5 <= x < 1:
- // 0 < u <= 1/4, and 0 < sqrt(u) <= 0.5,
- // And hence we can reuse the same polynomial approximation of asin(x) when
- // |x| <= 0.5:
- // asin(x) ~ pi/2 - 2 * sqrt(u) * P(u),
-
- // u = (1 - |x|)/2
- double u = fputil::multiply_add(x_abs, -0.5, 0.5);
- // v_hi + v_lo ~ sqrt(u).
- // Let:
- // h = u - v_hi^2 = (sqrt(u) - v_hi) * (sqrt(u) + v_hi)
- // Then:
- // sqrt(u) = v_hi + h / (sqrt(u) + v_hi)
- // ~ v_hi + h / (2 * v_hi)
- // So we can use:
- // v_lo = h / (2 * v_hi).
- // Then,
- // asin(x) ~ pi/2 - 2*(v_hi + v_lo) * P(u)
- double v_hi = fputil::sqrt<double>(u);
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- double p = asin_eval(u);
- double r = x_sign * fputil::multiply_add(-2.0 * v_hi, p, PI_OVER_TWO.hi);
- return r;
-#else
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- double h = fputil::multiply_add(v_hi, -v_hi, u);
-#else
- DoubleDouble v_hi_sq = fputil::exact_mult(v_hi, v_hi);
- double h = (u - v_hi_sq.hi) - v_hi_sq.lo;
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- // Scale v_lo and v_hi by 2 from the formula:
- // vh = v_hi * 2
- // vl = 2*v_lo = h / v_hi.
- double vh = v_hi * 2.0;
- double vl = h / v_hi;
-
- // Polynomial approximation:
- // p ~ asin(sqrt(u))/sqrt(u)
- unsigned idx;
- double err = vh * 0x1.0p-51;
-
- DoubleDouble p = asin_eval(DoubleDouble{0.0, u}, idx, err);
-
- // Perform computations in double-double arithmetic:
- // asin(x) = pi/2 - (v_hi + v_lo) * (ASIN_COEFFS[idx][0] + p)
- DoubleDouble r0 = fputil::quick_mult(DoubleDouble{vl, vh}, p);
- DoubleDouble r = fputil::exact_add(PI_OVER_TWO.hi, -r0.hi);
-
- double r_lo = PI_OVER_TWO.lo - r0.lo + r.lo;
-
- // Ziv's accuracy test.
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- double r_upper = fputil::multiply_add(
- r.hi, x_sign, fputil::multiply_add(r_lo, x_sign, err));
- double r_lower = fputil::multiply_add(
- r.hi, x_sign, fputil::multiply_add(r_lo, x_sign, -err));
-#else
- r_lo *= x_sign;
- r.hi *= x_sign;
- double r_upper = r.hi + (r_lo + err);
- double r_lower = r.hi + (r_lo - err);
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- if (LIBC_LIKELY(r_upper == r_lower))
- return r_upper;
-
- // Ziv's accuracy test failed, we redo the computations in Float128.
- // Recalculate mod 1/64.
- idx = static_cast<unsigned>(fputil::nearest_integer(u * 0x1.0p6));
-
- // After the first step of Newton-Raphson approximating v = sqrt(u), we have
- // that:
- // sqrt(u) = v_hi + h / (sqrt(u) + v_hi)
- // v_lo = h / (2 * v_hi)
- // With error:
- // sqrt(u) - (v_hi + v_lo) = h * ( 1/(sqrt(u) + v_hi) - 1/(2*v_hi) )
- // = -h^2 / (2*v * (sqrt(u) + v)^2).
- // Since:
- // (sqrt(u) + v_hi)^2 ~ (2sqrt(u))^2 = 4u,
- // we can add another correction term to (v_hi + v_lo) that is:
- // v_ll = -h^2 / (2*v_hi * 4u)
- // = -v_lo * (h / 4u)
- // = -vl * (h / 8u),
- // making the errors:
- // sqrt(u) - (v_hi + v_lo + v_ll) = O(h^3)
- // well beyond 128-bit precision needed.
-
- // Get the rounding error of vl = 2 * v_lo ~ h / vh
- // Get full product of vh * vl
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- double vl_lo = fputil::multiply_add(-v_hi, vl, h) / v_hi;
-#else
- DoubleDouble vh_vl = fputil::exact_mult(v_hi, vl);
- double vl_lo = ((h - vh_vl.hi) - vh_vl.lo) / v_hi;
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- // vll = 2*v_ll = -vl * (h / (4u)).
- double t = h * (-0.25) / u;
- double vll = fputil::multiply_add(vl, t, vl_lo);
- // m_v = -(v_hi + v_lo + v_ll).
- Float128 m_v = fputil::quick_add(
- Float128(vh), fputil::quick_add(Float128(vl), Float128(vll)));
- m_v.sign = Sign::NEG;
-
- // Perform computations in Float128:
- // asin(x) = pi/2 - (v_hi + v_lo + vll) * P(u).
- Float128 y_f128(fputil::multiply_add(static_cast<double>(idx), -0x1.0p-6, u));
-
- Float128 p_f128 = asin_eval(y_f128, idx);
- Float128 r0_f128 = fputil::quick_mul(m_v, p_f128);
- Float128 r_f128 = fputil::quick_add(PI_OVER_TWO_F128, r0_f128);
-
- if (xbits.is_neg())
- r_f128.sign = Sign::NEG;
-
- return static_cast<double>(r_f128);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-}
+LLVM_LIBC_FUNCTION(double, asin, (double x)) { return math::asin(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/dfmaf128.cpp b/libc/src/math/generic/dfmaf128.cpp
index b6e1bdb08..b8069c6 100644
--- a/libc/src/math/generic/dfmaf128.cpp
+++ b/libc/src/math/generic/dfmaf128.cpp
@@ -6,20 +6,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC_MATH_DFMAf128_H
-#define LLVM_LIBC_SRC_MATH_DFMAf128_H
-
#include "src/math/dfmaf128.h"
-#include "src/__support/FPUtil/FMA.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/dfmaf128.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(double, dfmaf128, (float128 x, float128 y, float128 z)) {
- return fputil::fma<double>(x, y, z);
+ return math::dfmaf128(x, y, z);
}
} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_MATH_DFMAf128_H
diff --git a/libc/src/math/generic/dfmal.cpp b/libc/src/math/generic/dfmal.cpp
index 02e0ce8..a50d837 100644
--- a/libc/src/math/generic/dfmal.cpp
+++ b/libc/src/math/generic/dfmal.cpp
@@ -7,15 +7,13 @@
//===----------------------------------------------------------------------===//
#include "src/math/dfmal.h"
-#include "src/__support/FPUtil/FMA.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/dfmal.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(double, dfmal,
(long double x, long double y, long double z)) {
- return fputil::fma<double>(x, y, z);
+ return math::dfmal(x, y, z);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16fma.cpp b/libc/src/math/generic/f16fma.cpp
index 70314b5..e6673e7 100644
--- a/libc/src/math/generic/f16fma.cpp
+++ b/libc/src/math/generic/f16fma.cpp
@@ -7,14 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/f16fma.h"
-#include "src/__support/FPUtil/FMA.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/f16fma.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, f16fma, (double x, double y, double z)) {
- return fputil::fma<float16>(x, y, z);
+ return math::f16fma(x, y, z);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16fmal.cpp b/libc/src/math/generic/f16fmal.cpp
index 4f2bf92..afc2339 100644
--- a/libc/src/math/generic/f16fmal.cpp
+++ b/libc/src/math/generic/f16fmal.cpp
@@ -7,15 +7,13 @@
//===----------------------------------------------------------------------===//
#include "src/math/f16fmal.h"
-#include "src/__support/FPUtil/FMA.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/f16fmal.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, f16fmal,
(long double x, long double y, long double z)) {
- return fputil::fma<float16>(x, y, z);
+ return math::f16fmal(x, y, z);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/f16sqrtl.cpp b/libc/src/math/generic/f16sqrtl.cpp
index c6ce73d..2c81ca2 100644
--- a/libc/src/math/generic/f16sqrtl.cpp
+++ b/libc/src/math/generic/f16sqrtl.cpp
@@ -7,14 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/f16sqrtl.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/f16sqrtl.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, f16sqrtl, (long double x)) {
- return fputil::sqrt<float16>(x);
+ return math::f16sqrtl(x);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fsqrt.cpp b/libc/src/math/generic/fsqrt.cpp
index d54471f..df1d4a9a 100644
--- a/libc/src/math/generic/fsqrt.cpp
+++ b/libc/src/math/generic/fsqrt.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/fsqrt.h"
-#include "src/__support/FPUtil/generic/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/fsqrt.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, fsqrt, (double x)) { return fputil::sqrt<float>(x); }
+LLVM_LIBC_FUNCTION(float, fsqrt, (double x)) { return math::fsqrt(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fsqrtf128.cpp b/libc/src/math/generic/fsqrtf128.cpp
index f2c0495..1b2ba2f 100644
--- a/libc/src/math/generic/fsqrtf128.cpp
+++ b/libc/src/math/generic/fsqrtf128.cpp
@@ -7,14 +7,11 @@
//===----------------------------------------------------------------------===//
#include "src/math/fsqrtf128.h"
-#include "src/__support/FPUtil/generic/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-
+#include "src/__support/math/fsqrtf128.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fsqrtf128, (float128 x)) {
- return fputil::sqrt<float>(x);
+ return math::fsqrtf128(x);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/fsqrtl.cpp b/libc/src/math/generic/fsqrtl.cpp
index b896a84..d6f27b16 100644
--- a/libc/src/math/generic/fsqrtl.cpp
+++ b/libc/src/math/generic/fsqrtl.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/fsqrtl.h"
-#include "src/__support/FPUtil/generic/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/fsqrtl.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, fsqrtl, (long double x)) {
- return fputil::sqrt<float>(x);
-}
+LLVM_LIBC_FUNCTION(float, fsqrtl, (long double x)) { return math::fsqrtl(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/hypotf.cpp b/libc/src/math/generic/hypotf.cpp
index ec48f62..fa1697c 100644
--- a/libc/src/math/generic/hypotf.cpp
+++ b/libc/src/math/generic/hypotf.cpp
@@ -6,93 +6,12 @@
//
//===----------------------------------------------------------------------===//
#include "src/math/hypotf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/hypotf.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, hypotf, (float x, float y)) {
- using DoubleBits = fputil::FPBits<double>;
- using FPBits = fputil::FPBits<float>;
-
- FPBits x_abs = FPBits(x).abs();
- FPBits y_abs = FPBits(y).abs();
-
- bool x_abs_larger = x_abs.uintval() >= y_abs.uintval();
-
- FPBits a_bits = x_abs_larger ? x_abs : y_abs;
- FPBits b_bits = x_abs_larger ? y_abs : x_abs;
-
- uint32_t a_u = a_bits.uintval();
- uint32_t b_u = b_bits.uintval();
-
- // Note: replacing `a_u >= FPBits::EXP_MASK` with `a_bits.is_inf_or_nan()`
- // generates extra exponent bit masking instructions on x86-64.
- if (LIBC_UNLIKELY(a_u >= FPBits::EXP_MASK)) {
- // x or y is inf or nan
- if (a_bits.is_signaling_nan() || b_bits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- if (a_bits.is_inf() || b_bits.is_inf())
- return FPBits::inf().get_val();
- return a_bits.get_val();
- }
-
- if (LIBC_UNLIKELY(a_u - b_u >=
- static_cast<uint32_t>((FPBits::FRACTION_LEN + 2)
- << FPBits::FRACTION_LEN)))
- return x_abs.get_val() + y_abs.get_val();
-
- double ad = static_cast<double>(a_bits.get_val());
- double bd = static_cast<double>(b_bits.get_val());
-
- // These squares are exact.
- double a_sq = ad * ad;
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- double sum_sq = fputil::multiply_add(bd, bd, a_sq);
-#else
- double b_sq = bd * bd;
- double sum_sq = a_sq + b_sq;
-#endif
-
- // Take sqrt in double precision.
- DoubleBits result(fputil::sqrt<double>(sum_sq));
- uint64_t r_u = result.uintval();
-
- // If any of the sticky bits of the result are non-zero, except the LSB, then
- // the rounded result is correct.
- if (LIBC_UNLIKELY(((r_u + 1) & 0x0000'0000'0FFF'FFFE) == 0)) {
- double r_d = result.get_val();
-
- // Perform rounding correction.
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- double sum_sq_lo = fputil::multiply_add(bd, bd, a_sq - sum_sq);
- double err = sum_sq_lo - fputil::multiply_add(r_d, r_d, -sum_sq);
-#else
- fputil::DoubleDouble r_sq = fputil::exact_mult(r_d, r_d);
- double sum_sq_lo = b_sq - (sum_sq - a_sq);
- double err = (sum_sq - r_sq.hi) + (sum_sq_lo - r_sq.lo);
-#endif
-
- if (err > 0) {
- r_u |= 1;
- } else if ((err < 0) && (r_u & 1) == 0) {
- r_u -= 1;
- } else if ((r_u & 0x0000'0000'1FFF'FFFF) == 0) {
- // The rounded result is exact.
- fputil::clear_except_if_required(FE_INEXACT);
- }
- return static_cast<float>(DoubleBits(r_u).get_val());
- }
-
- return static_cast<float>(result.get_val());
+ return math::hypotf(x, y);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/ilogb.cpp b/libc/src/math/generic/ilogb.cpp
index 60f2af2..74e6166 100644
--- a/libc/src/math/generic/ilogb.cpp
+++ b/libc/src/math/generic/ilogb.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/ilogb.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/ilogb.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, ilogb, (double x)) { return fputil::intlogb<int>(x); }
+LLVM_LIBC_FUNCTION(int, ilogb, (double x)) { return math::ilogb(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/ilogbf.cpp b/libc/src/math/generic/ilogbf.cpp
index 7da2aff..0ed2cb5 100644
--- a/libc/src/math/generic/ilogbf.cpp
+++ b/libc/src/math/generic/ilogbf.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/ilogbf.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/ilogbf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, ilogbf, (float x)) { return fputil::intlogb<int>(x); }
+LLVM_LIBC_FUNCTION(int, ilogbf, (float x)) { return math::ilogbf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/ilogbf128.cpp b/libc/src/math/generic/ilogbf128.cpp
index 4abc670..2cb6032 100644
--- a/libc/src/math/generic/ilogbf128.cpp
+++ b/libc/src/math/generic/ilogbf128.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/ilogbf128.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/ilogbf128.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, ilogbf128, (float128 x)) {
- return fputil::intlogb<int>(x);
-}
+LLVM_LIBC_FUNCTION(int, ilogbf128, (float128 x)) { return math::ilogbf128(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/ilogbl.cpp b/libc/src/math/generic/ilogbl.cpp
index 12460a8..b496b53 100644
--- a/libc/src/math/generic/ilogbl.cpp
+++ b/libc/src/math/generic/ilogbl.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/ilogbl.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/ilogbl.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, ilogbl, (long double x)) {
- return fputil::intlogb<int>(x);
-}
+LLVM_LIBC_FUNCTION(int, ilogbl, (long double x)) { return math::ilogbl(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/llogb.cpp b/libc/src/math/generic/llogb.cpp
index 3850ac0..2dcffb7 100644
--- a/libc/src/math/generic/llogb.cpp
+++ b/libc/src/math/generic/llogb.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/llogb.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/llogb.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(long, llogb, (double x)) { return fputil::intlogb<long>(x); }
+LLVM_LIBC_FUNCTION(long, llogb, (double x)) { return math::llogb(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/llogbf.cpp b/libc/src/math/generic/llogbf.cpp
index fedad95..2b35e2c 100644
--- a/libc/src/math/generic/llogbf.cpp
+++ b/libc/src/math/generic/llogbf.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/llogbf.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/llogbf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(long, llogbf, (float x)) { return fputil::intlogb<long>(x); }
+LLVM_LIBC_FUNCTION(long, llogbf, (float x)) { return math::llogbf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/llogbf128.cpp b/libc/src/math/generic/llogbf128.cpp
index 9106731..6f8f9c4 100644
--- a/libc/src/math/generic/llogbf128.cpp
+++ b/libc/src/math/generic/llogbf128.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/llogbf128.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/llogbf128.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(long, llogbf128, (float128 x)) {
- return fputil::intlogb<long>(x);
-}
+LLVM_LIBC_FUNCTION(long, llogbf128, (float128 x)) { return math::llogbf128(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/llogbf16.cpp b/libc/src/math/generic/llogbf16.cpp
index c792e90..916a5b9 100644
--- a/libc/src/math/generic/llogbf16.cpp
+++ b/libc/src/math/generic/llogbf16.cpp
@@ -7,14 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/llogbf16.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/llogbf16.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(long, llogbf16, (float16 x)) {
- return fputil::intlogb<long>(x);
-}
+LLVM_LIBC_FUNCTION(long, llogbf16, (float16 x)) { return math::llogbf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/log10.cpp b/libc/src/math/generic/log10.cpp
index 60c057d..54a4b5b5 100644
--- a/libc/src/math/generic/log10.cpp
+++ b/libc/src/math/generic/log10.cpp
@@ -7,906 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/log10.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/integer_literals.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-
-#include "src/__support/math/common_constants.h"
-#include "src/__support/math/log_range_reduction.h"
+#include "src/__support/math/log10.h"
namespace LIBC_NAMESPACE_DECL {
-
-// 128-bit precision dyadic floating point numbers.
-using Float128 = typename fputil::DyadicFloat<128>;
-
-using LIBC_NAMESPACE::operator""_u128;
-
-namespace {
-
-using namespace common_constants_internal;
-using namespace math::log_range_reduction_internal;
-
-constexpr fputil::DoubleDouble LOG10_E = {0x1.95355baaafad3p-57,
- 0x1.bcb7b1526e50ep-2};
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-// A simple upper bound for the error of e_x * log(2) - log(r).
-constexpr double HI_ERR = 0x1.0p-85;
-
-// Extra errors from P is from using x^2 to reduce evaluation latency.
-constexpr double P_ERR = 0x1.0p-51;
-
-// log10(2) with 128-bit precision generated by SageMath with:
-// def format_hex(value):
-// l = hex(value)[2:]
-// n = 8
-// x = [l[i:i + n] for i in range(0, len(l), n)]
-// return "0x" + "'".join(x) + "_u128"
-// (s, m, e) = RealField(128)(2).log10().sign_exponent_mantissa();
-// print(format_hex(m));
-constexpr Float128 LOG10_2(Sign::POS, /*exponent=*/-129, /*mantissa=*/
- 0x9a209a84'fbcff798'8f8959ac'0b7c9178_u128);
-
-alignas(16) constexpr LogRR LOG10_TABLE = {
- // -log10(r) with 128-bit precision generated by SageMath with:
- //
- // for i in range(128):
- // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) );
- // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
- // print("{Sign::POS,", e, ", format_hex(m), "},");
- /* .step_1 = */ {
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -136, 0xdf3b5ebb'da7e186b'65af394f'e05eafd3_u128},
- {Sign::POS, -135, 0xe01d4057'2f029c16'a8fb8d87'b30163b5_u128},
- {Sign::POS, -134, 0xa8c1263a'c3f57eb3'6bb0170e'5bb5d630_u128},
- {Sign::POS, -134, 0xe1e841bb'c26204e5'fc2ea6eb'0ea1370e_u128},
- {Sign::POS, -133, 0x8dc2eb02'274d6ff4'dc8a199a'4bb63382_u128},
- {Sign::POS, -133, 0xaacde920'361dd054'86b57ea6'10c7db33_u128},
- {Sign::POS, -133, 0xc81618eb'15421bab'5f034a40'e6a2f09d_u128},
- {Sign::POS, -133, 0xe59c7e66'c5fedb4b'594a31b2'c5cc891c_u128},
- {Sign::POS, -133, 0xf477584f'97b654de'221efda5'8221904b_u128},
- {Sign::POS, -132, 0x892e8219'75106e09'68a0dc47'567691c9_u128},
- {Sign::POS, -132, 0x9841c66e'17dfe7da'10bc94f4'4d216b49_u128},
- {Sign::POS, -132, 0x9fd7be33'18306cc5'e303ea7e'23c9d6fb_u128},
- {Sign::POS, -132, 0xaf1cb35b'f494a8dd'ce697dba'a00d4c7d_u128},
- {Sign::POS, -132, 0xbe8380a2'fa7eba5a'9c216079'dcf0ea96_u128},
- {Sign::POS, -132, 0xc643c775'8283a271'75278940'eecfc3a9_u128},
- {Sign::POS, -132, 0xd5de75ec'27e4fe68'2d3467d2'53e2d1fc_u128},
- {Sign::POS, -132, 0xddb904e8'f1272a95'ead4055d'cdec7b22_u128},
- {Sign::POS, -132, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
- {Sign::POS, -132, 0xf57e8281'ade9d92d'38dc40c4'fe11e608_u128},
- {Sign::POS, -131, 0x82c2941b'b20bbe1f'3bcdcfe7'b23976cd_u128},
- {Sign::POS, -131, 0x86cb3663'2807cdcd'456350b0'bda452a6_u128},
- {Sign::POS, -131, 0x8eeaa306'458b760a'78185dcc'37fda01a_u128},
- {Sign::POS, -131, 0x93018395'12fc1168'307643ad'bbbde1b3_u128},
- {Sign::POS, -131, 0x9b3dd1d5'50c41443'6c449d40'9f883fe3_u128},
- {Sign::POS, -131, 0x9f6356aa'03c34389'8ea7b30c'8b4ad886_u128},
- {Sign::POS, -131, 0xa7bd56cd'de5d76a2'961c6e69'0d8879b4_u128},
- {Sign::POS, -131, 0xabf1ea3e'1d7bd7cf'042643ce'd81ec14a_u128},
- {Sign::POS, -131, 0xb02b9af7'4c2f879e'4742fb3d'0b5cdd19_u128},
- {Sign::POS, -131, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
- {Sign::POS, -131, 0xbcf7dabd'87c01afc'8d3fc634'85e7ff13_u128},
- {Sign::POS, -131, 0xc1467f69'4d10a581'f3edc493'75fbc5a5_u128},
- {Sign::POS, -131, 0xc9f3ef07'e1f3fc5e'5fcd7d0c'e937375f_u128},
- {Sign::POS, -131, 0xce52d50b'94fa253a'58252dad'a9f06111_u128},
- {Sign::POS, -131, 0xd2b74192'fae43777'62f01e5f'f43708ab_u128},
- {Sign::POS, -131, 0xd72142a8'4ca85abd'481d9b31'31f52639_u128},
- {Sign::POS, -131, 0xdb90e68b'8abf14af'b305ced1'419fe924_u128},
- {Sign::POS, -131, 0xe48150cf'32888b9c'849266a8'5513dc6d_u128},
- {Sign::POS, -131, 0xe90234c6'5a15e533'080ecf32'66b4dcf4_u128},
- {Sign::POS, -131, 0xed88f6bb'355fa196'e1e0dda0'b3d375a4_u128},
- {Sign::POS, -131, 0xf215a60b'6557943f'ce3537a3'a211b25b_u128},
- {Sign::POS, -131, 0xf6a85251'3757dfbd'5dab6830'7fedefcd_u128},
- {Sign::POS, -131, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
- {Sign::POS, -130, 0x8242724a'155219f3'18aa3021'71017dcb_u128},
- {Sign::POS, -130, 0x849812d0'ccbb5cbd'abc7e698'502d43c0_u128},
- {Sign::POS, -130, 0x86f0dab1'ab5822b6'c339089a'51663370_u128},
- {Sign::POS, -130, 0x894cd27d'9f182c63'26f70b34'ce5cf201_u128},
- {Sign::POS, -130, 0x8bac02e8'ac3e09ac'676f20a8'7ab433df_u128},
- {Sign::POS, -130, 0x8e0e74ca'ae062e24'6db4169c'c4b83bc3_u128},
- {Sign::POS, -130, 0x90743120'1c7f651a'cd3fdb2f'ad0d1fd6_u128},
- {Sign::POS, -130, 0x92dd410a'd7bfe103'49d03e16'3250d1d4_u128},
- {Sign::POS, -130, 0x9549add2'f8a3c7e0'9ec7dc02'd5e723b9_u128},
- {Sign::POS, -130, 0x97b980e7'a743d71c'34698d03'a5442573_u128},
- {Sign::POS, -130, 0x9a2cc3df'f7548556'0522904d'1e47f3de_u128},
- {Sign::POS, -130, 0x9ca3807b'ca9fe93f'791a7264'6c87b976_u128},
- {Sign::POS, -130, 0x9f1dc0a4'b9cea286'3826f190'd655d736_u128},
- {Sign::POS, -130, 0xa19b8e6f'03b60e45'544ab3e4'8199b299_u128},
- {Sign::POS, -130, 0xa41cf41a'83643487'be775fa8'2961114e_u128},
- {Sign::POS, -130, 0xa6a1fc13'ad241953'45798e50'19e6c082_u128},
- {Sign::POS, -130, 0xa92ab0f4'92b772bd'91fb1ed0'cdc4d1fb_u128},
- {Sign::POS, -130, 0xabb71d85'ef05380d'818b8b9c'bbd17b72_u128},
- {Sign::POS, -130, 0xae474cc0'397f0d4f'a50c2fea'60c5b3b2_u128},
- {Sign::POS, -130, 0xb0db49cc'c1823c8e'58ea3498'0ad8b720_u128},
- {Sign::POS, -130, 0xb3732006'd1fbbba5'4b5f7194'1be508a4_u128},
- {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
- {Sign::POS, -130, 0xb60edafc'dd99ad1d'9e405fb8'bcb1ff1e_u128},
- {Sign::POS, -130, 0xb8ae8671'b3d7dd6c'f7e2ab36'f09e9014_u128},
- {Sign::POS, -130, 0xbb522e5d'bf37f63b'c6696396'40c305bb_u128},
- {Sign::POS, -130, 0xbdf9def0'4cf980ff'a3dc9e46'4e98764b_u128},
- {Sign::POS, -130, 0xc0a5a490'dea95b5e'ffd3256b'59fa9c59_u128},
- {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
- {Sign::POS, -130, 0xc3558be0'85e3f4bc'b0a2d486'72a051a5_u128},
- {Sign::POS, -130, 0xc609a1bb'4aa98f59'acb2ca5d'4ca1c10e_u128},
- {Sign::POS, -130, 0xc8c1f339'9ca7d33b'43690b9e'3cde0d02_u128},
- {Sign::POS, -130, 0xcb7e8db1'cfe04827'18b1fd60'383f7e5a_u128},
- {Sign::POS, -130, 0xce3f7eb9'a517c969'0248757e'5f45af3d_u128},
- {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
- {Sign::POS, -130, 0xd104d427'de7fbcc4'7c4acd60'5be48bc1_u128},
- {Sign::POS, -130, 0xd3ce9c15'e10ec927'58ff6362'9a92652d_u128},
- {Sign::POS, -130, 0xd69ce4e1'6303fcdd'6b49be3b'd8c89f10_u128},
- {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
- {Sign::POS, -130, 0xd96fbd2e'2814c9cc'e6dd603a'881e9060_u128},
- {Sign::POS, -130, 0xdc4733e7'cbcbfc8c'89e281c9'8c1d705c_u128},
- {Sign::POS, -130, 0xdf235843'9aa5dd12'dc0db7cf'0cce9f32_u128},
- {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
- {Sign::POS, -130, 0xe20439c2'7a7c01b8'fdf1c5b8'46db9deb_u128},
- {Sign::POS, -130, 0xe4e9e832'e2da0c05'3dd7eab4'8869c402_u128},
- {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
- {Sign::POS, -130, 0xe7d473b2'e5db8f2a'4e8fcc90'0b41daef_u128},
- {Sign::POS, -130, 0xeac3ecb2'4a3ac7b4'7593e1a9'e917359a_u128},
- {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
- {Sign::POS, -130, 0xedb863f4'b73f982d'e7741396'b49e1ce5_u128},
- {Sign::POS, -130, 0xf0b1ea93'f34675a7'c8ba4f8f'47b85a5c_u128},
- {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
- {Sign::POS, -130, 0xf3b09202'359f9787'7007c127'6821b705_u128},
- {Sign::POS, -130, 0xf6b46c0c'8c8fdea1'7ee19afe'6db7e324_u128},
- {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
- {Sign::POS, -130, 0xf9bd8add'584687f0'edf54f37'f6d40420_u128},
- {Sign::POS, -130, 0xfccc00fe'dba4e6fb'efe52ccf'03e7dee1_u128},
- {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
- {Sign::POS, -130, 0xffdfe15d'e3c01bac'1be2585c'279c50a5_u128},
- {Sign::POS, -129, 0x817c9fa6'43880404'e0b571f5'c91b0446_u128},
- {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
- {Sign::POS, -129, 0x830c1742'7ea55eca'7178594b'ef2def59_u128},
- {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
- {Sign::POS, -129, 0x849e6196'487c1d1c'9a741bb1'71158d2a_u128},
- {Sign::POS, -129, 0x863388eb'55ebd295'1a618264'446cb495_u128},
- {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
- {Sign::POS, -129, 0x87cb97c3'ff9eac18'71dbdbbe'c51d7657_u128},
- {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
- {Sign::POS, -129, 0x896698dc'e4cff76c'abe0b522'230f7d14_u128},
- {Sign::POS, -129, 0x8b04972e'9d4d3011'd28e8ada'fea703b4_u128},
- {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
- {Sign::POS, -129, 0x8ca59def'7b5cefc5'208422d8'3be34b27_u128},
- {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
- {Sign::POS, -129, 0x8e49b895'5e3ffb8a'c385cf49'402af0e4_u128},
- {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
- {Sign::POS, -129, 0x8ff0f2d7'960a075c'da982a61'4e12c6dd_u128},
- {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
- {Sign::POS, -129, 0x919b58b0'd999bbc8'038401fc'1c1b5c2c_u128},
- {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
- {Sign::POS, -129, 0x9348f661'4f821394'a9b55d3f'16da746a_u128},
- {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
- {Sign::POS, -129, 0x94f9d870'aac256a5'088d2d14'73d4f7f5_u128},
- {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
- {Sign::POS, -129, 0x96ae0bb0'5c35d5bd'7c1e117d'ea19e9e6_u128},
- {Sign::POS, -129, 0x98659d3d'd9b12532'336db063'0f536fb9_u128},
- {Sign::POS, 0, 0_u128},
- },
- // -log10(r) for the second step, generated by SageMath with:
- //
- // for i in range(-2^6, 2^7 + 1):
- // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) );
- // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
- // print("{Sign::POS," if s == -1 else "{Sign::NEG,", e, ",
- // format_hex(m), "},");
- /* .step_2 = */
- {
- {Sign::NEG, -137, 0xdeca7290'13cd7c31'7f1ce002'fa34131b_u128},
- {Sign::NEG, -137, 0xdb5475b4'4946d986'639afa08'5dd8b4c7_u128},
- {Sign::NEG, -137, 0xd7de6b0e'10cab7d2'05512632'fe9a58cb_u128},
- {Sign::NEG, -137, 0xd468529c'fc6fb395'b5380a99'53117d07_u128},
- {Sign::NEG, -137, 0xd0f22c60'9e474741'70af2d7d'53be1f31_u128},
- {Sign::NEG, -137, 0xcd7bf858'885dcae2'0ccd499c'49b74cc2_u128},
- {Sign::NEG, -137, 0xca05b684'4cba73cf'5b51ddc3'987ebfb8_u128},
- {Sign::NEG, -137, 0xc68f66e3'7d5f545a'49375f51'89b3782b_u128},
- {Sign::NEG, -137, 0xc3190975'ac495b7a'f6e57738'865c712f_u128},
- {Sign::NEG, -137, 0xbfa29e3a'6b70547e'ca02b10a'8c712acd_u128},
- {Sign::NEG, -137, 0xbc2c2531'4cc6e6b6'78e50382'10208151_u128},
- {Sign::NEG, -137, 0xb8b59e59'e23a9524'0fa099ec'd71ee0ea_u128},
- {Sign::NEG, -137, 0xb53f09b3'bdb3be28'eeb445cc'b8fb09ed_u128},
- {Sign::NEG, -137, 0xb1c8673e'71159b33'c352fff1'8a1c02fb_u128},
- {Sign::NEG, -137, 0xae51b6f9'8e3e406e'7949e03e'cf9b390b_u128},
- {Sign::NEG, -137, 0xaadaf8e4'a7069c6c'2681f33f'30aadedc_u128},
- {Sign::NEG, -137, 0xa7642cff'4d4277d6'f01d5496'eea213b3_u128},
- {Sign::NEG, -137, 0xa3ed5349'12c0751d'e92ef555'ff1de975_u128},
- {Sign::NEG, -137, 0xa0766bc1'894a1022'eb0c7519'b3e7c1e0_u128},
- {Sign::NEG, -137, 0x9c21b6e9'1e7f03a3'f60d204f'f0fe5296_u128},
- {Sign::NEG, -137, 0x98aab049'1050bea8'125c19a4'f057c18b_u128},
- {Sign::NEG, -137, 0x95339bd6'4cd953e7'7e9383ce'1bdf9575_u128},
- {Sign::NEG, -137, 0x91bc7990'65cc57d6'bf274f4d'8f770253_u128},
- {Sign::NEG, -137, 0x8e454976'ecd836ad'656bd9b7'58fe44ba_u128},
- {Sign::NEG, -137, 0x8ace0b89'73a63413'bfdd2c7f'388fc014_u128},
- {Sign::NEG, -137, 0x8756bfc7'8bda6ad0'83fbf6ed'936c493a_u128},
- {Sign::NEG, -137, 0x83df6630'c713cc76'71bfa9a1'8bec01cc_u128},
- {Sign::NEG, -137, 0x8067fec4'b6ec2111'f09d19f5'6dbfef72_u128},
- {Sign::NEG, -138, 0xf9e11305'd9f00dad'4c422713'b1642228_u128},
- {Sign::NEG, -138, 0xf2f20cd5'f58de39a'0c3c7c56'99b7a0a4_u128},
- {Sign::NEG, -138, 0xec02eaf8'e3c656ff'b8db7c69'e3fa0797_u128},
- {Sign::NEG, -138, 0xe513ad6d'c7a3a553'a083eb05'506ff7ed_u128},
- {Sign::NEG, -138, 0xde245433'c425b5c5'c21595e7'45f1fa15_u128},
- {Sign::NEG, -138, 0xd734df49'fc42189b'b9d5bcdb'fe719389_u128},
- {Sign::NEG, -138, 0xd0454eaf'92e4068b'a17a1e85'e93461f4_u128},
- {Sign::NEG, -138, 0xc955a263'aaec6016'e3537584'da333fda_u128},
- {Sign::NEG, -138, 0xc265da65'6731ace5'00963177'f24682c2_u128},
- {Sign::NEG, -138, 0xbb75f6b3'ea801b1e'4ac03734'7bcfc50e_u128},
- {Sign::NEG, -138, 0xb485f74e'57997ec6'901a736a'4364cdfd_u128},
- {Sign::NEG, -138, 0xad95dc33'd1355117'bb550acc'3b9d7247_u128},
- {Sign::NEG, -138, 0xa6a5a563'7a00afdc'663cf2b2'7e8f1ffb_u128},
- {Sign::NEG, -138, 0x9fb552dc'749e5cca'5f89bd08'feb39952_u128},
- {Sign::NEG, -138, 0x98c4e49d'e3a6bcdd'23c2623c'73f494db_u128},
- {Sign::NEG, -138, 0x91d45aa6'e9a7d7b0'4937d3b5'485af61e_u128},
- {Sign::NEG, -138, 0x8ae3b4f6'a92556d9'df14214e'7a6d8111_u128},
- {Sign::NEG, -138, 0x83f2f38c'44988544'bf7cfc14'999fb4bc_u128},
- {Sign::NEG, -139, 0xfa042ccd'bce09d15'a990c0ee'569a8d51_u128},
- {Sign::NEG, -139, 0xec223b0b'32227c9e'a38463e9'd941e1c2_u128},
- {Sign::NEG, -139, 0xde4011cf'2daaff31'ba032453'0edaa03f_u128},
- {Sign::NEG, -139, 0xd05db117'f419b857'5e997a02'dad7ace7_u128},
- {Sign::NEG, -139, 0xc27b18e3'c9f977c7'4a14676d'4d0f817e_u128},
- {Sign::NEG, -139, 0xb4984930'f3c0481c'857c002e'e7a1e473_u128},
- {Sign::NEG, -139, 0xa6b541fd'b5cf6d89'5923b2eb'72d8012a_u128},
- {Sign::NEG, -139, 0x98d20348'5473648b'21cde8f8'5ca1f9fd_u128},
- {Sign::NEG, -139, 0x8aee8d0f'13e3e09e'0be08e08'b1d212d4_u128},
- {Sign::NEG, -140, 0xfa15bea0'708795e1'69502399'8e6bd7b0_u128},
- {Sign::NEG, -140, 0xde4df414'0b42822f'634cea67'50617a92_u128},
- {Sign::NEG, -140, 0xc285ba75'7feb2781'fbd7e970'aef9dbb8_u128},
- {Sign::NEG, -140, 0xa6bd11c1'564a8ace'9aedc1c1'ba7d0695_u128},
- {Sign::NEG, -140, 0x8af3f9f4'1600120a'8d306ba2'07233c44_u128},
- {Sign::NEG, -141, 0xde54e614'8d030322'856a0a3a'00fcf3c1_u128},
- {Sign::NEG, -141, 0xa6c0fa00'de35f314'b3a2c140'7cf6d38d_u128},
- {Sign::NEG, -142, 0xde585f4c'5bbbcd3d'd791cf6a'70c3a504_u128},
- {Sign::NEG, -143, 0xde5a1bf6'27b1f68f'10a633f2'c4a8ea22_u128},
- {Sign::NEG, 0, 0_u128},
- {Sign::POS, -143, 0xde5d9565'8a729eab'ed4a68e5'e6e83ddf_u128},
- {Sign::POS, -142, 0xde5f522b'21e3e25a'3281f187'2cdbee94_u128},
- {Sign::POS, -141, 0xa6c8cb3b'7e5bbbfd'f1466eda'a96e356e_u128},
- {Sign::POS, -141, 0xde62cbd2'1e895473'8a607fd6'95dfc3d9_u128},
- {Sign::POS, -140, 0x8afed570'32bebc7c'c36b8713'ceefe2de_u128},
- {Sign::POS, -140, 0xa6ccb436'a3c72fa4'5c2e76c9'53e3e3e6_u128},
- {Sign::POS, -140, 0xc29b023f'dcb2dccf'8e4950fa'5c943bbf_u128},
- {Sign::POS, -140, 0xde69bf8f'58005dfc'20fa8a73'c585f634_u128},
- {Sign::POS, -140, 0xfa38ec28'905810a3'0aa106d9'b0a9717a_u128},
- {Sign::POS, -139, 0x8b044407'80460c2a'85d70e03'2de41aec_u128},
- {Sign::POS, -139, 0x98ec49a3'11cc30ab'beee21cb'b82a9a78_u128},
- {Sign::POS, -139, 0xa6d486e8'ba5151a0'abd7b0fd'd8efe6f6_u128},
- {Sign::POS, -139, 0xb4bcfbda'377d31cc'3221c56e'2c1aa912_u128},
- {Sign::POS, -139, 0xc2a5a879'470c7c37'57b795a3'6d9c5f19_u128},
- {Sign::POS, -139, 0xd08e8cc7'a6d0c580'131ec142'c053ac3b_u128},
- {Sign::POS, -139, 0xde77a8c7'14b08d28'35e3298f'4bb2aa0a_u128},
- {Sign::POS, -139, 0xec60fc79'4ea73ee4'7133dafd'fc44f160_u128},
- {Sign::POS, -139, 0xfa4a87e0'12c533eb'74b37d23'121c59d5_u128},
- {Sign::POS, -138, 0x841a257e'8f97da22'93bf5f42'07da8a4c_u128},
- {Sign::POS, -138, 0x8b0f22e9'19107c0c'fdb5990e'c6057f4e_u128},
- {Sign::POS, -138, 0x92043c30'84f41481'2d408a58'b1b202fe_u128},
- {Sign::POS, -138, 0x98f97155'b274b1ab'1759381b'61dfbf01_u128},
- {Sign::POS, -138, 0x9feec259'80cedbbe'41e90a05'4df4b9f1_u128},
- {Sign::POS, -138, 0xa6e42f3c'cf49959d'a1e66c62'03725d50_u128},
- {Sign::POS, -138, 0xadd9b800'7d365d83'8693d36a'b45bd7ce_u128},
- {Sign::POS, -138, 0xb4cf5ca5'69f12da9'91e25bb4'0ad3f098_u128},
- {Sign::POS, -138, 0xbbc51d2c'74e07cf0'bdf94392'c4cc7f6c_u128},
- {Sign::POS, -138, 0xc2baf996'7d753f89'6fe37973'354a82f9_u128},
- {Sign::POS, -138, 0xc9b0f1e4'632ae79b'97647b42'67bfd801_u128},
- {Sign::POS, -138, 0xd0a70617'058765ee'dbf5c32a'454f7bdf_u128},
- {Sign::POS, -138, 0xd79d362f'441b2a92'd6edfe04'c37ba916_u128},
- {Sign::POS, -138, 0xde93822d'fe812587'5ad3480c'cfbe9890_u128},
- {Sign::POS, -138, 0xe589ea14'145ec764'c7d9ac76'5be7e325_u128},
- {Sign::POS, -138, 0xec806de2'65640204'6d8f24b9'a3ca011b_u128},
- {Sign::POS, -138, 0xf3770d99'd14b4928'f9b65480'7dcdd5b2_u128},
- {Sign::POS, -138, 0xfa6dc93b'37d99326'f4513f47'45663028_u128},
- {Sign::POS, -137, 0x80b25063'bc6f2cc6'a46e9a72'd80da75f_u128},
- {Sign::POS, -137, 0x842dca1f'ba19cce6'ee60992b'51ffac4b_u128},
- {Sign::POS, -137, 0x87a951d2'04deeaf3'1977fa1c'786886b3_u128},
- {Sign::POS, -137, 0x8b24e77b'0cb60a84'0e5f7c52'cdf119d5_u128},
- {Sign::POS, -137, 0x8ea08b1b'419bf221'3bf9d70d'a1021a10_u128},
- {Sign::POS, -137, 0x921c3cb3'1392ab94'fd0406b0'7523b8e6_u128},
- {Sign::POS, -137, 0x9597fc42'f2a18441'0453ee32'c020f2a8_u128},
- {Sign::POS, -137, 0x9913c9cb'4ed50d72'cfb3ec22'066bf7f6_u128},
- {Sign::POS, -137, 0x9c8fa54c'983f1cb8'215c025b'd493ecf9_u128},
- {Sign::POS, -137, 0x9f2c9319'2e68232b'39c116b7'ee3a83ec_u128},
- {Sign::POS, -137, 0xa2a8870f'24ac5f66'f41f4b3e'de2782f0_u128},
- {Sign::POS, -137, 0xa62488ff'3c735799'61196927'723eb75c_u128},
- {Sign::POS, -137, 0xa9a098e9'e5e2a432'0e615e83'6cb1edab_u128},
- {Sign::POS, -137, 0xad1cb6cf'91252372'6981331c'5fc71cfc_u128},
- {Sign::POS, -137, 0xb098e2b0'ae6af9c2'5f6a4faa'054f11fa_u128},
- {Sign::POS, -137, 0xb4151c8d'ade99205'02a68bc6'81a74c28_u128},
- {Sign::POS, -137, 0xb7916466'ffdb9ded'382ba24d'90566403_u128},
- {Sign::POS, -137, 0xbb0dba3d'14811652'6ad1abe5'1dd22e00_u128},
- {Sign::POS, -137, 0xbe8a1e10'5c1f3b85'456d3f7f'59b13960_u128},
- {Sign::POS, -137, 0xc2068fe1'470095a4'738dd8b7'd66e9058_u128},
- {Sign::POS, -137, 0xc5830fb0'4574f4f1'68e123fe'd7ff11c6_u128},
- {Sign::POS, -137, 0xc8ff9d7d'c7d17225'2f3bd097'80c3aa11_u128},
- {Sign::POS, -137, 0xcc7c394a'3e706ec5'3b48887f'1ce36935_u128},
- {Sign::POS, -137, 0xcff8e316'19b19578'47ddae65'5ecc4633_u128},
- {Sign::POS, -137, 0xd3759ae1'c9f9da5b'37fa81ee'f4819c88_u128},
- {Sign::POS, -137, 0xd6f260ad'bfb37b55'ff6c4a8d'747c65ed_u128},
- {Sign::POS, -137, 0xda6f347a'6b4e0070'921c2949'3a33318c_u128},
- {Sign::POS, -137, 0xddec1648'3d3e3c27'da0631eb'65e731d8_u128},
- {Sign::POS, -137, 0xe1690617'a5fe4bc2'b3da6c07'd110babc_u128},
- {Sign::POS, -137, 0xe4e603e9'160d97a6'f2485c78'68b8835a_u128},
- {Sign::POS, -137, 0xe8630fbc'fdf0d3ae'67f5b7ed'01344055_u128},
- {Sign::POS, -137, 0xebe02993'ce31ff7b'f820df44'5b1d0622_u128},
- {Sign::POS, -137, 0xef5d516d'f76066d0'adefc674'b7eca5cd_u128},
- {Sign::POS, -137, 0xf2da874b'ea10a1e0'da6be6dc'057d3235_u128},
- {Sign::POS, -137, 0xf657cb2e'16dc95a9'392bdde1'52ab5ff5_u128},
- {Sign::POS, -137, 0xf9d51d14'ee637444'1bab58e2'ec99cf73_u128},
- {Sign::POS, -137, 0xfd527d00'e149bd3e'9b51ef7e'3388d692_u128},
- {Sign::POS, -136, 0x8067f579'301c9ef6'e914c6a7'f3f22fa2_u128},
- {Sign::POS, -136, 0x8226b374'edf088e2'0d22862e'b2081c94_u128},
- {Sign::POS, -136, 0x83e57873'e27ad153'29ebd0b4'76cd8fd8_u128},
- {Sign::POS, -136, 0x85a44476'461854a0'98feddc2'806d01ed_u128},
- {Sign::POS, -136, 0x8763177c'512896af'471bfc26'1a401854_u128},
- {Sign::POS, -136, 0x88b23a5b'61430a16'b6f89c19'b4cd1acd_u128},
- {Sign::POS, -136, 0x8a7119a8'5909ebe9'b39aaf34'163fb099_u128},
- {Sign::POS, -136, 0x8c2ffff9'9357e887'1665f0f8'21541c36_u128},
- {Sign::POS, -136, 0x8deeed4f'489679a6'a5051754'e049c1cb_u128},
- {Sign::POS, -136, 0x8fade1a9'b131c159'8c5a9a1c'57b2e986_u128},
- {Sign::POS, -136, 0x916cdd09'05988a35'1d844843'8a26a9ae_u128},
- {Sign::POS, -136, 0x932bdf6d'7e3c477d'8e3a0913'ecd2fd02_u128},
- {Sign::POS, -136, 0x94eae8d7'53911550'bc881a45'f47f1d36_u128},
- {Sign::POS, -136, 0x96a9f946'be0db8d0'f5e51c05'499b06d0_u128},
- {Sign::POS, -136, 0x986910bb'f62ba04f'c1a43be8'1a243fde_u128},
- {Sign::POS, -136, 0x9a282f37'3466e378'aec3cfeb'e971beb7_u128},
- {Sign::POS, -136, 0x9be754b8'b13e437c'2518b293'28614989_u128},
- {Sign::POS, -136, 0x9da68140'a5332b3a'39d6b147'cbe803a4_u128},
- {Sign::POS, -136, 0x9f65b4cf'48c9af6d'87765e30'04ae428d_u128},
- {Sign::POS, -136, 0xa124ef64'd4888ed6'08f896ab'28245bac_u128},
- {Sign::POS, -136, 0xa2e43101'80f93263'f8880fb5'ca630c87_u128},
- {Sign::POS, -136, 0xa4a379a5'86a7ad62'b179397c'f82e935c_u128},
- {Sign::POS, -136, 0xa662c951'1e22bda3'95a8cb71'7197ad81_u128},
- {Sign::POS, -136, 0xa8222004'7ffbcba8'f6394a34'b7f9a4a4_u128},
- {Sign::POS, -136, 0xa9e17dbf'e4c6ead0'ffafd8c2'b57884e8_u128},
- {Sign::POS, -136, 0xaba0e283'851ad980'a970a643'b8a6ac2b_u128},
- {Sign::POS, -136, 0xad604e4f'9991014e'a89b49fb'749d47e0_u128},
- {Sign::POS, -136, 0xaf1fc124'5ac5772e'66475ed2'ac983305_u128},
- {Sign::POS, -136, 0xb06f5be1'bf1918e7'b4fd6209'364bb36f_u128},
- {Sign::POS, -136, 0xb22edb06'36da31d6'8b5ce79b'0965962a_u128},
- {Sign::POS, -136, 0xb3ee6133'f7149769'6724232b'07396427_u128},
- {Sign::POS, -136, 0xb5adee6b'386e62ae'2f02b14d'cad8a49c_u128},
- {Sign::POS, -136, 0xb76d82ac'339058db'bd6443a8'1f792e07_u128},
- {Sign::POS, -136, 0xb92d1df7'2125eb7c'ea1cd962'5749939a_u128},
- {Sign::POS, -136, 0xbaecc04c'39dd389b'97775e31'42198913_u128},
- {Sign::POS, -136, 0xbcac69ab'b6670aeb'c2a701b8'09a2bc39_u128},
- {Sign::POS, -136, 0xbe6c1a15'cf76d9f6'979b990f'39e662e3_u128},
- {Sign::POS, -136, 0xc02bd18a'bdc2ca45'88395c46'3ddd82b2_u128},
- {Sign::POS, -136, 0xc1eb900a'ba03ad8d'66f451bd'9ba5ed05_u128},
- {Sign::POS, -136, 0xc3ab5595'fcf502d9'84cfb941'3f6437a6_u128},
- {Sign::POS, -136, 0xc56b222c'bf54f6b6'd2c1c8d3'2943ca42_u128},
- {Sign::POS, -136, 0xc72af5cf'39e4635f'067c0d1f'd95192e6_u128},
- {Sign::POS, -136, 0xc8ead07d'a566d0e3'c298bf9e'db6441f2_u128},
- {Sign::POS, -136, 0xcaaab238'3aa27559'c22d646a'ddde3910_u128},
- {Sign::POS, -136, 0xcc6a9aff'32603504'07c301e5'c7d1ca40_u128},
- {Sign::POS, -136, 0xce2a8ad2'c56ba27f'0fb44446'4df02505_u128},
- {Sign::POS, -136, 0xcfea81b3'2c92feec'05f1df35'91ae898f_u128},
- {Sign::POS, -136, 0xd13a7f7c'07506f7d'b43caf8e'7b891066_u128},
- {Sign::POS, -136, 0xd2fa82b3'6a610c4f'597fb13f'0d0fdf19_u128},
- {Sign::POS, -136, 0xd4ba8cf8'3dd2a06b'3c21f1c6'0a60b0d6_u128},
- {Sign::POS, -136, 0xd67a9e4a'ba7d7ce5'2b745590'9a0428a4_u128},
- {Sign::POS, -136, 0xd83ab6ab'193ca223'1438b605'73d2da10_u128},
- {Sign::POS, -136, 0xd9fad619'92edc008'49f86400'c5ab2b11_u128},
- {Sign::POS, -136, 0xdbbafc96'60713620'd3c313d1'48a23c35_u128},
- {Sign::POS, -136, 0xdd7b2a21'baaa13cc'bc568523'55e0f0d5_u128},
- },
- // -log10(r) for the third step, generated by SageMath with:
- //
- // for i in range(-80, 81):
- // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
- // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
- // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, "," ,
- // format_hex(m), "},");
- /* .step_3 = */
- {
- {Sign::NEG, -143, 0x8af8b9b3'22ba8c7d'54d7e498'98ca0093_u128},
- {Sign::NEG, -143, 0x893c0652'9deffc3d'c321bbf1'6665f29c_u128},
- {Sign::NEG, -143, 0x877f52e4'33ac7ec4'8246df71'40c3e4ae_u128},
- {Sign::NEG, -143, 0x85c29f67'e3ef35bc'1deaa9e8'5780e4c1_u128},
- {Sign::NEG, -143, 0x8405ebdd'aeb742cf'0cd8a512'1a9162d0_u128},
- {Sign::NEG, -143, 0x82493845'9403c7a7'b10486fa'4644308d_u128},
- {Sign::NEG, -143, 0x808c849f'93d3e5f0'578a2f61'eedd4be8_u128},
- {Sign::NEG, -144, 0xfd9fa1d7'5c4d7ea6'715b4a49'1790e8a7_u128},
- {Sign::NEG, -144, 0xfa263a53'c5f6eaf4'efb6273a'04c71573_u128},
- {Sign::NEG, -144, 0xf6acd2b4'64a25420'474d9015'60c17807_u128},
- {Sign::NEG, -144, 0xf3336af9'384dfd7c'6b9a5dec'eb80ec57_u128},
- {Sign::NEG, -144, 0xefba0322'40f82a5d'2665a32f'7cc64f79_u128},
- {Sign::NEG, -144, 0xec409b2f'7e9f1e16'17c8a673'16659363_u128},
- {Sign::NEG, -144, 0xe8c73320'f1411bfa'b62cdd3e'f5c8673d_u128},
- {Sign::NEG, -144, 0xe54dcaf6'98dc675e'4e4be6d5'a4a07422_u128},
- {Sign::NEG, -144, 0xe1d462b0'756f4394'032f86ff'08c92e22_u128},
- {Sign::NEG, -144, 0xde5afa4e'86f7f3ee'ce31a0d2'7359396f_u128},
- {Sign::NEG, -144, 0xdae191d0'cd74bbc1'7efc3180'aee36373_u128},
- {Sign::NEG, -144, 0xd7682937'48e3de5e'bb894b1e'0ce72fc4_u128},
- {Sign::NEG, -144, 0xd3eec081'f9439f19'00230f6c'7270f8be_u128},
- {Sign::NEG, -144, 0xd07557b0'de924142'9f63aaa5'63e9a399_u128},
- {Sign::NEG, -144, 0xccfbeec3'f8ce082d'c2354e44'1015e7eb_u128},
- {Sign::NEG, -144, 0xc98285bb'47f5372c'67d22bcf'5a452a4c_u128},
- {Sign::NEG, -144, 0xc6091c96'cc061190'65c46fa3'e3afea18_u128},
- {Sign::NEG, -144, 0xc28fb356'84fedaab'67e63bbe'1405c20d_u128},
- {Sign::NEG, -144, 0xbf1649fa'72ddd5ce'f061a284'212afbad_u128},
- {Sign::NEG, -144, 0xbb9ce082'95a1464c'57b0a190'1625b539_u128},
- {Sign::NEG, -144, 0xb82376ee'ed476f74'cc9d1c79'd93a9a1e_u128},
- {Sign::NEG, -144, 0xb4aa0d3f'79ce9499'5440d7a1'31392da8_u128},
- {Sign::NEG, -144, 0xb130a374'3b34f90a'ca0572f7'c9f7a7de_u128},
- {Sign::NEG, -144, 0xadb7398d'3178e019'dfa464cb'37fe6455_u128},
- {Sign::NEG, -144, 0xaa3dcf8a'5c988d17'1d26f48e'fb62e2e0_u128},
- {Sign::NEG, -144, 0xa6c4656b'bc924352'e0e635a6'81d259e2_u128},
- {Sign::NEG, -144, 0xa34afb31'5164461d'5f8b022f'27cbda35_u128},
- {Sign::NEG, -144, 0x9fd190db'1b0cd8c6'a40df5ca'390a0465_u128},
- {Sign::NEG, -144, 0x9c582669'198a3e9e'8fb76866'f01c4f2d_u128},
- {Sign::NEG, -144, 0x98debbdb'4cdabaf4'da1f690c'752fdeff_u128},
- {Sign::NEG, -144, 0x95655131'b4fc9119'112db8a3'dc07ee78_u128},
- {Sign::NEG, -144, 0x91ebe66c'51ee045a'9919c4c2'2125c79e_u128},
- {Sign::NEG, -144, 0x8e727b8b'23ad5808'ac6aa272'26204db3_u128},
- {Sign::NEG, -144, 0x8af9108e'2a38cf72'5bf708fe'ad2b1780_u128},
- {Sign::NEG, -144, 0x877fa575'658eade6'8ee54cbc'53cd19ed_u128},
- {Sign::NEG, -144, 0x84063a40'd5ad36b4'02ab59d3'8cc6e2c5_u128},
- {Sign::NEG, -144, 0x808ccef0'7a92ad29'4b0eaf0a'99286378_u128},
- {Sign::NEG, -145, 0xfa26c708'a87aa929'a448b11f'012c975c_u128},
- {Sign::NEG, -145, 0xf333eff8'c556e089'b0a1d584'117de73b_u128},
- {Sign::NEG, -145, 0xec4118b1'4bb6870e'e890f9fb'57fdabb6_u128},
- {Sign::NEG, -145, 0xe54e4132'3b962355'261d48c7'1e693130_u128},
- {Sign::NEG, -145, 0xde5b697b'94f23bf7'efecdd48'ed894c32_u128},
- {Sign::NEG, -145, 0xd768918d'57c75792'7944b995'7598a88a_u128},
- {Sign::NEG, -145, 0xd075b967'8411fcbf'a208bc08'75093645_u128},
- {Sign::NEG, -145, 0xc982e10a'19ceb219'f6bb94d8'9da8b432_u128},
- {Sign::NEG, -145, 0xc2900875'18f9fe3b'b07ebbab'782457b0_u128},
- {Sign::NEG, -145, 0xbb9d2fa8'819067be'b5126529'45eb9165_u128},
- {Sign::NEG, -145, 0xb4aa56a4'538e753c'96d57890'e171eea5_u128},
- {Sign::NEG, -145, 0xadb77d68'8ef0ad4e'94c5854b'9cd01726_u128},
- {Sign::NEG, -145, 0xa6c4a3f5'33b3968d'9a7eb881'1ec3e6bb_u128},
- {Sign::NEG, -145, 0x9fd1ca4a'41d3b792'403bd2ab'3e0fa2d7_u128},
- {Sign::NEG, -145, 0x98def067'b94d96f4'cad61d29'db384b6b_u128},
- {Sign::NEG, -145, 0x91ec164d'9a1dbb4d'2bc55fd6'b8a306ec_u128},
- {Sign::NEG, -145, 0x8af93bfb'e440ab33'011fd699'5111a927_u128},
- {Sign::NEG, -145, 0x84066172'97b2ed3d'959a26fa'ac7e5494_u128},
- {Sign::NEG, -146, 0xfa270d63'68e21007'c10eab72'66ac6bc0_u128},
- {Sign::NEG, -146, 0xec415772'74ef0439'0bb178b9'0026b2b2_u128},
- {Sign::NEG, -146, 0xde5ba112'5385c43b'ac3bfd92'5e6b33e1_u128},
- {Sign::NEG, -146, 0xd075ea43'049f5d3b'9d0a01a9'5b355319_u128},
- {Sign::NEG, -146, 0xc2903304'8834dc64'31b3b7b2'0a6a6496_u128},
- {Sign::NEG, -146, 0xb4aa7b56'de3f4ee0'170da891'504620f4_u128},
- {Sign::NEG, -146, 0xa6c4c33a'06b7c1d9'53289e84'744549cb_u128},
- {Sign::NEG, -146, 0x98df0aae'01974279'45519048'b0ce7e7f_u128},
- {Sign::NEG, -146, 0x8af951b2'ced6dde8'a6118c42'bf99407e_u128},
- {Sign::NEG, -147, 0xfa273090'dcdf429f'0e5b474c'c5a64cf6_u128},
- {Sign::NEG, -147, 0xde5bbcdd'c0b533aa'a74dab3b'd6067bc7_u128},
- {Sign::NEG, -147, 0xc290484c'4921a941'9f73f4e3'7357341b_u128},
- {Sign::NEG, -147, 0xa6c4d2dc'7616bdb0'31bf5d5f'815220e7_u128},
- {Sign::NEG, -147, 0x8af95c8e'47868b41'4b987ca5'fca242d7_u128},
- {Sign::NEG, -148, 0xde5bcac3'7ac6587d'19be3fab'd93832c5_u128},
- {Sign::NEG, -148, 0xa6c4daad'af3d75e0'8fd43f0c'9ce444d3_u128},
- {Sign::NEG, -149, 0xde5bd1b6'58ad4676'061cd853'e796bc2c_u128},
- {Sign::NEG, -150, 0xde5bd52f'c7d8545f'87d6afab'fba0644f_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -150, 0xde5bdc22'a69d9e19'a9bf3200'1043629d_u128},
- {Sign::POS, -149, 0xde5bdf9c'1637d9ef'8014f0f3'60272d82_u128},
- {Sign::POS, -148, 0xa6c4ea50'24795bd2'fe94a02f'c639c0e3_u128},
- {Sign::POS, -148, 0xde5be68e'f5db7f99'bee710a5'ace7c8d4_u128},
- {Sign::POS, -147, 0x8af97245'3faf11e8'1a778d81'00437e4f_u128},
- {Sign::POS, -147, 0xa6c4f221'608e89fe'97d773f8'992f7051_u128},
- {Sign::POS, -147, 0xc29072db'dd9a0dd5'0c9ee584'1a3afa95_u128},
- {Sign::POS, -147, 0xde5bf474'b6df8331'7b644b13'993cf4ef_u128},
- {Sign::POS, -147, 0xfa2776eb'ec6ccfdb'3448f66e'2bd7a0ca_u128},
- {Sign::POS, -146, 0x8af97d20'bf27eccd'6a7ca5f1'a87a1a3c_u128},
- {Sign::POS, -146, 0x98df3f3a'b64b431d'245675fe'3061108f_u128},
- {Sign::POS, -146, 0xa6c501c3'dba75dc2'64136e97'019d0a3b_u128},
- {Sign::POS, -146, 0xb4aac4bc'2f432fa3'6cdadac4'd6925bd4_u128},
- {Sign::POS, -146, 0xc2908823'b125aba7'2899e237'91d29632_u128},
- {Sign::POS, -146, 0xd0764bfa'6155c4b5'28039e1f'0323a4c1_u128},
- {Sign::POS, -146, 0xde5c1040'3fda6db5'a2912e03'afc8cc28_u128},
- {Sign::POS, -146, 0xec41d4f5'4cba9991'7681cc9f'9e0d89f9_u128},
- {Sign::POS, -146, 0xfa279a19'87fd3b32'28dae4b7'241255e1_u128},
- {Sign::POS, -145, 0x8406afd6'78d4a2c0'f2b412f8'dceda28e_u128},
- {Sign::POS, -145, 0x8af992d7'c4e2d5b5'bf5dccd9'67504857_u128},
- {Sign::POS, -145, 0x91ec7610'a82cafed'3716dbf9'50b07f85_u128},
- {Sign::POS, -145, 0x98df5981'22b5aadd'69eebe0b'8e5b18e1_u128},
- {Sign::POS, -145, 0x9fd23d29'34813ffc'bb583ce6'5af56beb_u128},
- {Sign::POS, -145, 0xa6c52108'dd92e8c1'e22978ef'a7a962a0_u128},
- {Sign::POS, -145, 0xadb80520'1dee1ea3'e89bf389'8ef27836_u128},
- {Sign::POS, -145, 0xb4aae96e'f5965b1a'2c4c997e'c90bab0b_u128},
- {Sign::POS, -145, 0xbb9dcdf5'648f179c'5e3bcd6f'21fe6224_u128},
- {Sign::POS, -145, 0xc290b2b3'6adbcda2'82cd723b'f1524680_u128},
- {Sign::POS, -145, 0xc98397a9'087ff6a4'f1c8f574'935e109b_u128},
- {Sign::POS, -145, 0xd0767cd6'3d7f0c1c'565959c2'e4394a59_u128},
- {Sign::POS, -145, 0xd769623b'09dc8781'af0d4157'bc4f05be_u128},
- {Sign::POS, -145, 0xde5c47d7'6d9be24e'4dd6f857'6e9188b8_u128},
- {Sign::POS, -145, 0xe54f2dab'68c095fb'd80c7f46'484eee3d_u128},
- {Sign::POS, -145, 0xec4213b6'fb4e1c04'46679575'12a6bd26_u128},
- {Sign::POS, -145, 0xf334f9fa'2547ede1'e505c36d'95a074fa_u128},
- {Sign::POS, -145, 0xfa27e074'e6b1850f'5368655f'1ce3110b_u128},
- {Sign::POS, -144, 0x808d6393'9fc72d83'c23a5ac5'7f06c112_u128},
- {Sign::POS, -144, 0x8406d708'97f0f4a2'df39eb58'90580f93_u128},
- {Sign::POS, -144, 0x87804a99'5bd7d4a2'cd896f3e'43f38669_u128},
- {Sign::POS, -144, 0x8af9be45'eb7d8a41'83b16ff7'eecace8c_u128},
- {Sign::POS, -144, 0x8e73320e'46e3d23d'21ec7ae8'ffa1531d_u128},
- {Sign::POS, -144, 0x91eca5f2'6e0c6953'f227268d'464ae907_u128},
- {Sign::POS, -144, 0x956619f2'60f90c44'680017af'3bbaf2d3_u128},
- {Sign::POS, -144, 0x98df8e0e'1fab77cd'20c8069e'4ae400de_u128},
- {Sign::POS, -144, 0x9c590245'aa2568ac'e381c465'1a67ee13_u128},
- {Sign::POS, -144, 0x9fd27699'00689ba2'a0e23fff'd718794e_u128},
- {Sign::POS, -144, 0xa34beb08'2276cd6d'73508b92'7f485b97_u128},
- {Sign::POS, -144, 0xa6c55f93'1051bacc'9ee5e19f'2eecdb55_u128},
- {Sign::POS, -144, 0xaa3ed439'c9fb207f'916daa3c'6c8fdc9d_u128},
- {Sign::POS, -144, 0xadb848fc'4f74bb45'e265804b'77126ed3_u128},
- {Sign::POS, -144, 0xb131bdda'a0c047df'52fd36ae'943fd7b4_u128},
- {Sign::POS, -144, 0xb4ab32d4'bddf830b'ce16dd7f'60311bf6_u128},
- {Sign::POS, -144, 0xb824a7ea'a6d4298b'6846c745'1d8105ac_u128},
- {Sign::POS, -144, 0xbb9e1d1c'5b9ff81e'5fd38e2b'0650a884_u128},
- {Sign::POS, -144, 0xbf179269'dc44ab85'1cb61936'9e1c641f_u128},
- {Sign::POS, -144, 0xc29107d3'28c40080'3099a17e'0461648c_u128},
- {Sign::POS, -144, 0xc60a7d58'411fb3d0'56dbb75e'4813a12b_u128},
- {Sign::POS, -144, 0xc983f2f9'25598236'748c47b1'bbe45a07_u128},
- {Sign::POS, -144, 0xccfd68b5'd5732873'986da106'4b5913e1_u128},
- {Sign::POS, -144, 0xd076de8e'516e6348'faf478d3'd0b31300_u128},
- {Sign::POS, -144, 0xd3f05482'994cef77'fe47f0b2'6ba754ff_u128},
- {Sign::POS, -144, 0xd769ca92'ad1089c2'2e419b90'd8e709b7_u128},
- {Sign::POS, -144, 0xdae340be'8cbaeee9'406d82ea'ca788b6f_u128},
- {Sign::POS, -144, 0xde5cb706'384ddbaf'140a2bff'40e0d670_u128},
- {Sign::POS, -144, 0xe1d62d69'afcb0cd5'b2089d06'e51d8034_u128},
- {Sign::POS, -144, 0xe54fa3e8'f3343f1f'4d0c626a'636f2e4f_u128},
- {Sign::POS, -144, 0xe8c91a84'028b2f4e'416b93f8'c6f48d30_u128},
- {Sign::POS, -144, 0xec42913a'ddd19a25'152eda1d'd615c6f5_u128},
- {Sign::POS, -144, 0xefbc080d'85093c66'78117318'6fc07a66_u128},
- {Sign::POS, -144, 0xf3357efb'f833d2d5'43813830'e974324d_u128},
- {Sign::POS, -144, 0xf6aef606'37531a34'7a9ea2ef'6e1f5d41_u128},
- {Sign::POS, -144, 0xfa286d2c'4268cf47'4a3cd252'5dccc623_u128},
- {Sign::POS, -144, 0xfda1e46e'1976aed1'08e19004'ae218d5d_u128},
- {Sign::POS, -143, 0x808dade5'de3f3aca'9b62aaca'25d5d18a_u128},
- {Sign::POS, -143, 0x824a69a2'95c0f02b'bee9a8d4'3e00613c_u128},
- {Sign::POS, -143, 0x8407256d'334155ed'd8d4b69c'2056f729_u128},
- {Sign::POS, -143, 0x85c3e145'b6c14a72'e7cc2860'5d7bb77e_u128},
- {Sign::POS, -143, 0x87809d2c'2041ac1c'ff51b4bd'c834a8f1_u128},
- {Sign::POS, -143, 0x893d5920'6fc3594e'47c0774a'a81c3561_u128},
- {Sign::POS, -143, 0x8afa1522'a5473068'fe4cf331'ecb9eb62_u128},
- },
- // -log10(r) for the fourth step, generated by SageMath with:
- //
- // for i in range(-65, 65):
- // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) );
- // s, m, e = RealField(128)(r).log10().sign_mantissa_exponent();
- // print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",",
- // format_hex(m), "},");
- /* .step_4 = */
- {
- {Sign::NEG, -151, 0xe1d54641'22cf95a4'e471a82b'bedbe0ae_u128},
- {Sign::NEG, -151, 0xde5bd6ec'7f7bc110'af6e93be'8e4c1764_u128},
- {Sign::NEG, -151, 0xdae26797'a490f80e'e44848f0'a5779499_u128},
- {Sign::NEG, -151, 0xd768f842'920f3a98'90205533'f4e70566_u128},
- {Sign::NEG, -151, 0xd3ef88ed'47f688a6'c01844ac'e3729e48_u128},
- {Sign::NEG, -151, 0xd0761997'c646e232'8151a232'4e41c7c4_u128},
- {Sign::NEG, -151, 0xccfcaa42'0d004734'e0edf74d'88cacafd_u128},
- {Sign::NEG, -151, 0xc9833aec'1c22b7a6'ec0ecc3a'5cd27e58_u128},
- {Sign::NEG, -151, 0xc609cb95'f3ae3381'afd5a7e7'0a6bf214_u128},
- {Sign::NEG, -151, 0xc2905c3f'93a2babe'39640ff4'47f81ceb_u128},
- {Sign::NEG, -151, 0xbf16ece8'fc004d55'95db88b5'422588b1_u128},
- {Sign::NEG, -151, 0xbb9d7d92'2cc6eb40'd25d952f'9beffeec_u128},
- {Sign::NEG, -151, 0xb8240e3b'25f69478'fc0bb71b'6ea03578_u128},
- {Sign::NEG, -151, 0xb4aa9ee3'e78f48f7'20076ee3'49cb7b20_u128},
- {Sign::NEG, -151, 0xb1312f8c'719108b4'4b723ba4'3353643d_u128},
- {Sign::NEG, -151, 0xadb7c034'c3fbd3a9'8b6d9b2d'a7657754_u128},
- {Sign::NEG, -151, 0xaa3e50dc'decfa9cf'ed1b0a01'987ad9b4_u128},
- {Sign::NEG, -151, 0xa6c4e184'c20c8b20'7d9c0354'6f57fc11_u128},
- {Sign::NEG, -151, 0xa34b722c'6db27794'4a12010d'0b0c4727_u128},
- {Sign::NEG, -151, 0x9fd202d3'e1c16f24'5f9e7bc4'c0f1c851_u128},
- {Sign::NEG, -151, 0x9c58937b'1e3971c9'cb62eac7'5cacde29_u128},
- {Sign::NEG, -151, 0x98df2422'231a7f7d'9a80c413'202be52a_u128},
- {Sign::NEG, -151, 0x9565b4c8'f0649838'da197c58'c3a6e445_u128},
- {Sign::NEG, -151, 0x91ec456f'8617bbf4'974e86fb'759f3988_u128},
- {Sign::NEG, -151, 0x8e72d615'e433eaa9'df415610'dadf46b3_u128},
- {Sign::NEG, -151, 0x8af966bc'0ab92451'bf135a61'0e7a1ddc_u128},
- {Sign::NEG, -151, 0x877ff761'f9a768e5'43e60366'a1cb2e09_u128},
- {Sign::NEG, -151, 0x84068807'b0feb85d'7adabf4e'9c75efce_u128},
- {Sign::NEG, -151, 0x808d18ad'30bf12b3'7112faf8'7c6591ee_u128},
- {Sign::NEG, -152, 0xfa2752a4'f1d0efc0'676043ec'6b994be5_u128},
- {Sign::NEG, -152, 0xf33473ef'12f5cfb9'9fa73d18'6649999d_u128},
- {Sign::NEG, -152, 0xec419538'c4ecc544'a53db362'aa5cc6f0_u128},
- {Sign::NEG, -152, 0xe54eb682'07b5d053'9266761d'e5e05f13_u128},
- {Sign::NEG, -152, 0xde5bd7ca'db50f0d8'81645201'b36e17ba_u128},
- {Sign::NEG, -152, 0xd768f913'3fbe26c5'8c7a112a'9a2b2a52_u128},
- {Sign::NEG, -152, 0xd0761a5b'34fd720c'cdea7b1a'0dc7ad42_u128},
- {Sign::NEG, -152, 0xc9833ba2'bb0ed2a0'5ff854b6'6e7ded1f_u128},
- {Sign::NEG, -152, 0xc2905ce9'd1f24872'5ce6604b'0911c5ed_u128},
- {Sign::NEG, -152, 0xbb9d7e30'79a7d374'def75d88'16cffc59_u128},
- {Sign::NEG, -152, 0xb4aa9f76'b22f739a'006e0982'bd8d96ef_u128},
- {Sign::NEG, -152, 0xadb7c0bc'7b8928d3'db8d1eb5'0fa7375c_u128},
- {Sign::NEG, -152, 0xa6c4e201'd5b4f314'8a9754fe'0c0073a7_u128},
- {Sign::NEG, -152, 0x9fd20346'c0b2d24e'27cf61a1'9e032f69_u128},
- {Sign::NEG, -152, 0x98df248b'3c82c672'cd77f748'9d9ef50b_u128},
- {Sign::NEG, -152, 0x91ec45cf'4924cf74'95d3c600'cf484f03_u128},
- {Sign::NEG, -152, 0x8af96712'e698ed45'9b257b3c'e3f82109_u128},
- {Sign::NEG, -152, 0x84068856'14df1fd7'f7afc1d4'792b015a_u128},
- {Sign::NEG, -153, 0xfa275331'a7eece3b'8b6a8408'31c123d8_u128},
- {Sign::NEG, -153, 0xec4195b6'47c38612'3ef142da'7335b35a_u128},
- {Sign::NEG, -153, 0xde5bd83a'093c6718'3e79062c'7cbb3b7d_u128},
- {Sign::NEG, -153, 0xd0761abc'ec597131'be870ed4'ed5b755b_u128},
- {Sign::NEG, -153, 0xc2905d3e'f11aa442'f3a09874'3d20fb64_u128},
- {Sign::NEG, -153, 0xb4aa9fc0'17800030'124ad974'bd15fbca_u128},
- {Sign::NEG, -153, 0xa6c4e240'5f8984dd'4f0b030a'9742eb00_u128},
- {Sign::NEG, -153, 0x98df24bf'c937322e'de664133'cead362d_u128},
- {Sign::NEG, -153, 0x8af9673e'54890808'f4e1bab8'3f55f5a1_u128},
- {Sign::NEG, -154, 0xfa275378'02fe0c9f'8e052253'3c713e98_u128},
- {Sign::NEG, -154, 0xde5bd871'a03259cf'129bc1c6'f293726e_u128},
- {Sign::NEG, -154, 0xc2905d69'80aef768'e0918216'6eeb17eb_u128},
- {Sign::NEG, -154, 0xa6c4e25f'a473e535'60f08720'313daa3f_u128},
- {Sign::NEG, -154, 0x8af96754'0b8122fc'fcc2ea56'6b3af38b_u128},
- {Sign::NEG, -155, 0xde5bd88d'6bad6110'3a25757e'00f4e3a0_u128},
- {Sign::NEG, -155, 0xa6c4e26f'46e91b3e'55d3f9e7'0cf177b8_u128},
- {Sign::NEG, -156, 0xde5bd89b'516ae82a'3d4aac85'125398d0_u128},
- {Sign::NEG, -157, 0xde5bd8a2'4449ac95'9ab5a849'a06f400d_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -157, 0xde5bd8b0'2a073729'0d3cc88f'd4ef34c2_u128},
- {Sign::POS, -156, 0xde5bd8b7'1ce5fd51'225916c2'b3f33c90_u128},
- {Sign::POS, -155, 0xa6c4e28e'8bd3930a'17847f98'acf08d54_u128},
- {Sign::POS, -155, 0xde5bd8c5'02a38b5e'04439783'0931fddd_u128},
- {Sign::POS, -154, 0x8af9677f'79717409'c2ab3859'13176984_u128},
- {Sign::POS, -154, 0xa6c4e29e'2e48d4cc'e454dec8'2bde52e5_u128},
- {Sign::POS, -154, 0xc2905dbe'9fd7e82f'fe1522b0'470d7d7f_u128},
- {Sign::POS, -154, 0xde5bd8e0'ce1eae6a'a6e2721f'2afc3cce_u128},
- {Sign::POS, -154, 0xfa275404'b91d27b4'75b3458e'ec3c106c_u128},
- {Sign::POS, -153, 0x8af96795'3069aa22'80bf0ff2'f6cd9f93_u128},
- {Sign::POS, -153, 0x98df2528'e2a09a29'f09cc73b'7013b906_u128},
- {Sign::POS, -153, 0xa6c4e2bd'7333640c'55ee1480'619827c4_u128},
- {Sign::POS, -153, 0xb4aaa052'e22207e5'7c2e48d7'72250b3c_u128},
- {Sign::POS, -153, 0xc2905de9'2f6c85d1'2ed8ba8c'6fa81c98_u128},
- {Sign::POS, -153, 0xd0761b80'5b12ddeb'3968c521'4f33fc4f_u128},
- {Sign::POS, -153, 0xde5bd918'6515104f'6759c94e'2d017fad_u128},
- {Sign::POS, -153, 0xec4196b1'4d731d19'84272d01'4c70fe58_u128},
- {Sign::POS, -153, 0xfa27544b'142d0465'5b4c5b5f'180b9fe1_u128},
- {Sign::POS, -152, 0x840688f2'dca16327'5c226261'10c254a4_u128},
- {Sign::POS, -152, 0x8af967c0'9e5a3178'b345ef5d'90dd6545_u128},
- {Sign::POS, -152, 0x91ec468e'cf40ed34'98ce9208'7c5cb614_u128},
- {Sign::POS, -152, 0x98df255d'6f559668'f27a0a60'56dcfe57_u128},
- {Sign::POS, -152, 0x9fd2042c'7e982d23'a6061afe'b7929f24_u128},
- {Sign::POS, -152, 0xa6c4e2fb'fd08b172'99308918'494a4a20_u128},
- {Sign::POS, -152, 0xadb7c1cb'eaa72363'b1b71c7c'ca69a844_u128},
- {Sign::POS, -152, 0xb4aaa09c'47738304'd5579f97'0cf000a9_u128},
- {Sign::POS, -152, 0xbb9d7f6d'136dd063'e9cfdf6c'f676df42_u128},
- {Sign::POS, -152, 0xc2905e3e'4e960b8e'd4ddab9f'8032bbab_u128},
- {Sign::POS, -152, 0xc9833d0f'f8ec3493'7c3ed66a'b6f39fe9_u128},
- {Sign::POS, -152, 0xd0761be2'12704b7f'c5b134a5'bb25cf2e_u128},
- {Sign::POS, -152, 0xd768fab4'9b225061'96f29dc2'c0d26ca0_u128},
- {Sign::POS, -152, 0xde5bd987'93024346'd5c0ebcf'0fa0221e_u128},
- {Sign::POS, -152, 0xe54eb85a'fa10243d'67d9fb73'02d3c705_u128},
- {Sign::POS, -152, 0xec41972e'd04bf353'32fbabf2'095106f1_u128},
- {Sign::POS, -152, 0xf3347603'15b5b096'1ce3df2a'a59b0889_u128},
- {Sign::POS, -152, 0xfa2754d7'ca4d5c14'0b507996'6dd5143e_u128},
- {Sign::POS, -151, 0x808d19d6'77097aed'71ffb125'05e19d89_u128},
- {Sign::POS, -151, 0x84068941'40833efc'4657417a'9e657eae_u128},
- {Sign::POS, -151, 0x877ff8ac'4193fa3d'758de3f1'68f9f8c9_u128},
- {Sign::POS, -151, 0x8af96817'7a3bacb7'f2828ffc'57f43581_u128},
- {Sign::POS, -151, 0x8e72d782'ea7a5672'b0143e5b'e77b1053_u128},
- {Sign::POS, -151, 0x91ec46ee'924ff774'a121e91e'1d8769ef_u128},
- {Sign::POS, -151, 0x9565b65a'71bc8fc4'b88a8b9e'89e47b9c_u128},
- {Sign::POS, -151, 0x98df25c6'88c01f69'e92d2286'46302a9c_u128},
- {Sign::POS, -151, 0x9c589532'd75aa66b'25e8abcb'f5db5b8c_u128},
- {Sign::POS, -151, 0x9fd2049f'5d8c24cf'619c26b3'c62a45c8_u128},
- {Sign::POS, -151, 0xa34b740c'1b549a9d'8f2693cf'6e34c6cc_u128},
- {Sign::POS, -151, 0xa6c4e379'10b407dc'a166f4fe'2ee6b59a_u128},
- {Sign::POS, -151, 0xaa3e52e6'3daa6c93'8b3c4d6c'd3003616_u128},
- {Sign::POS, -151, 0xadb7c253'a237c8c9'3f85a195'af160c71_u128},
- {Sign::POS, -151, 0xb13131c1'3e5c1c84'b121f740'a191f084_u128},
- {Sign::POS, -151, 0xb4aaa12f'121767cc'd2f05583'12b2e136_u128},
- {Sign::POS, -151, 0xb824109d'1d69aaa8'97cfc4bf'f48d77de_u128},
- {Sign::POS, -151, 0xbb9d800b'6052e51e'f29f4ea7'c30c3ba5_u128},
- {Sign::POS, -151, 0xbf16ef79'dad31736'd63dfe38'83eff4e9_u128},
- {Sign::POS, -151, 0xc2905ee8'8cea40f7'358adfbd'c6d0009f_u128},
- {Sign::POS, -151, 0xc609ce57'76986267'036500d0'a51aa3b6_u128},
- {Sign::POS, -151, 0xc9833dc6'97dd7b8d'32ab7057'c2155e78_u128},
- {Sign::POS, -151, 0xccfcad35'f0b98c70'b63d3e87'4add3ff0_u128},
- {Sign::POS, -151, 0xd0761ca5'812c9518'80f97ce0'f6673948_u128},
- {Sign::POS, -151, 0xd3ef8c15'4936958b'85bf3e34'0580712d_u128},
- {Sign::POS, -151, 0xd768fb85'48d78dd0'b76d969d'42ce9734_u128},
- {Sign::POS, -151, 0xdae26af5'800f7def'08e39b87'02d0373a_u128},
- {Sign::POS, -151, 0xde5bda65'eede65ed'6d0063a9'23dd0cc6_u128},
- }};
-
-// > P = fpminimax(log10(1 + x)/x, 3, [|128...|], [-0x1.0002143p-29 , 0x1p-29]);
-// > P;
-// > dirtyinfnorm(log10(1 + x)/x - P, [-0x1.0002143p-29 , 0x1p-29]);
-// 0x1.64fb8...p-123
-constexpr Float128 BIG_COEFFS[4]{
- {Sign::NEG, -131, 0xde5bd8a9'373f89a7'6903c4ce'1582517d_u128},
- {Sign::POS, -130, 0x943d3b1b'7a1af679'b8a21791'624e2e8a_u128},
- {Sign::NEG, -130, 0xde5bd8a9'37287195'355baaaf'abc25990_u128},
- {Sign::POS, -129, 0xde5bd8a9'37287195'355baaaf'ad33dbd9_u128},
-};
-
-// Reuse the output of the fast pass range reduction.
-// -2^-8 <= m_x < 2^-7
-double log10_accurate(int e_x, int index, double m_x) {
-
- Float128 e_x_f128(static_cast<float>(e_x));
- Float128 sum = fputil::quick_mul(LOG10_2, e_x_f128);
- sum = fputil::quick_add(sum, LOG10_TABLE.step_1[index]);
-
- Float128 v_f128 = log_range_reduction(m_x, LOG10_TABLE, sum);
-
- // Polynomial approximation
- Float128 p = fputil::quick_mul(v_f128, BIG_COEFFS[0]);
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[1]));
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[2]));
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[3]));
-
- Float128 r = fputil::quick_add(sum, p);
-
- return static_cast<double>(r);
-}
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-} // namespace
-
-LLVM_LIBC_FUNCTION(double, log10, (double x)) {
- using namespace common_constants_internal;
- using FPBits_t = typename fputil::FPBits<double>;
-
- FPBits_t xbits(x);
- uint64_t x_u = xbits.uintval();
-
- int x_e = -FPBits_t::EXP_BIAS;
-
- if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
- // log10(1.0) = +0.0
- return 0.0;
- }
-
- if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
- xbits.uintval() > FPBits_t::max_normal().uintval())) {
- if (x == 0.0) {
- // return -Inf and raise FE_DIVBYZERO.
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits_t::inf(Sign::NEG).get_val();
- }
- if (xbits.is_neg() && !xbits.is_nan()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
- if (xbits.is_inf_or_nan()) {
- return x;
- }
- // Normalize denormal inputs.
- xbits = FPBits_t(x * 0x1.0p52);
- x_e -= 52;
- x_u = xbits.uintval();
- }
-
- // log10(x) = log10(2^x_e * x_m)
- // = x_e * log10(2) + log10(x_m)
-
- // Range reduction for log10(x_m):
- // For each x_m, we would like to find r such that:
- // -2^-8 <= r * x_m - 1 < 2^-7
- int shifted = static_cast<int>(x_u >> 45);
- int index = shifted & 0x7F;
- double r = RD[index];
-
- // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
- // all 1's.
- x_e += static_cast<int>((x_u + (1ULL << 45)) >> 52);
- double e_x = static_cast<double>(x_e);
-
- // hi is exact
- double hi = fputil::multiply_add(e_x, LOG_2_HI, LOG_R_DD[index].hi);
- // lo errors ~ e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo) + rounding err
- // <= 2 * (e_x * LSB(LOG_2_LO) + LSB(LOG_R[index].lo))
- double lo = fputil::multiply_add(e_x, LOG_2_LO, LOG_R_DD[index].lo);
-
- // Set m = 1.mantissa.
- uint64_t x_m = (x_u & 0x000F'FFFF'FFFF'FFFFULL) | 0x3FF0'0000'0000'0000ULL;
- double m = FPBits_t(x_m).get_val();
-
- double u, u_sq;
- fputil::DoubleDouble r1;
-
- // Perform exact range reduction
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- u = fputil::multiply_add(r, m, -1.0); // exact
-#else
- uint64_t c_m = x_m & 0x3FFF'E000'0000'0000ULL;
- double c = FPBits_t(c_m).get_val();
- u = fputil::multiply_add(r, m - c, CD[index]); // exact
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- // Error of u_sq = ulp(u^2);
- u_sq = u * u;
- // Degree-7 minimax polynomial
- double p0 = fputil::multiply_add(u, LOG_COEFFS[1], LOG_COEFFS[0]);
- double p1 = fputil::multiply_add(u, LOG_COEFFS[3], LOG_COEFFS[2]);
- double p2 = fputil::multiply_add(u, LOG_COEFFS[5], LOG_COEFFS[4]);
- double p = fputil::polyeval(u_sq, lo, p0, p1, p2);
-
- // Exact sum:
- // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
- r1 = fputil::exact_add(hi, u);
- r1.lo += p;
-
- // Quick double-double multiplication:
- // r2.hi + r2.lo ~ r1 * log10(e),
- // with error bounded by:
- // 4*ulp( ulp(r2.hi) )
- fputil::DoubleDouble r2 = fputil::quick_mult(r1, LOG10_E);
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return r2.hi + r2.lo;
-#else
- // Technicallly error of r1.lo is bounded by:
- // |hi|*ulp(log(2)_lo) + C*ulp(u^2)
- // To simplify the error computation a bit, we replace |hi|*ulp(log(2)_lo)
- // with the upper bound: 2^11 * ulp(log(2)_lo) = 2^-85.
- // Total error is bounded by ~ C * ulp(u^2) + 2^-85.
- double err = fputil::multiply_add(u_sq, P_ERR, HI_ERR);
-
- // Lower bound from the result
- double left = r2.hi + (r2.lo - err);
- // Upper bound from the result
- double right = r2.hi + (r2.lo + err);
-
- // Ziv's test if fast pass is accurate enough.
- if (left == right)
- return left;
-
- // Exact cases:
- if (LIBC_UNLIKELY((x_u & 0x3FFFFF) == 0)) {
- switch (x_u) {
- case 0x4024000000000000: // x = 10.0
- return 1.0;
- case 0x4059000000000000: // x = 10^2
- return 2.0;
- case 0x408f400000000000: // x = 10^3
- return 3.0;
- case 0x40c3880000000000: // x = 10^4
- return 4.0;
- case 0x40f86a0000000000: // x = 10^5
- return 5.0;
- case 0x412e848000000000: // x = 10^6
- return 6.0;
- case 0x416312d000000000: // x = 10^7
- return 7.0;
- case 0x4197d78400000000: // x = 10^8
- return 8.0;
- case 0x41cdcd6500000000: // x = 10^9
- return 9.0;
- case 0x4202a05f20000000: // x = 10^10
- return 10.0;
- case 0x42374876e8000000: // x = 10^11
- return 11.0;
- case 0x426d1a94a2000000: // x = 10^12
- return 12.0;
- case 0x42a2309ce5400000: // x = 10^13
- return 13.0;
- }
- } else {
- switch (x_u) {
- case 0x42d6bcc41e900000: // x = 10^14
- return 14.0;
- case 0x430c6bf526340000: // x = 10^15
- return 15.0;
- case 0x4341c37937e08000: // x = 10^16
- return 16.0;
- case 0x4376345785d8a000: // x = 10^17
- return 17.0;
- case 0x43abc16d674ec800: // x = 10^18
- return 18.0;
- case 0x43e158e460913d00: // x = 10^19
- return 19.0;
- case 0x4415af1d78b58c40: // x = 10^20
- return 20.0;
- case 0x444b1ae4d6e2ef50: // x = 10^21
- return 21.0;
- case 0x4480f0cf064dd592: // x = 10^22
- return 22.0;
- }
- }
-
- return log10_accurate(x_e, index, u);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-}
+LLVM_LIBC_FUNCTION(double, log10, (double x)) { return math::log10(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp
index ddac3c2..f4179a6 100644
--- a/libc/src/math/generic/log1p.cpp
+++ b/libc/src/math/generic/log1p.cpp
@@ -7,1057 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/log1p.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/integer_literals.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-
-#include "src/__support/math/common_constants.h"
+#include "src/__support/math/log1p.h"
namespace LIBC_NAMESPACE_DECL {
-
-// 128-bit precision dyadic floating point numbers.
-using Float128 = typename fputil::DyadicFloat<128>;
-
-using LIBC_NAMESPACE::operator""_u128;
-
-namespace {
-
-using namespace common_constants_internal;
-
-// R1[i] = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7) )
-constexpr double R1[129] = {
- 0x1p0, 0x1.fcp-1, 0x1.f8p-1, 0x1.f4p-1, 0x1.fp-1, 0x1.ecp-1, 0x1.eap-1,
- 0x1.e6p-1, 0x1.e2p-1, 0x1.dep-1, 0x1.dap-1, 0x1.d8p-1, 0x1.d4p-1, 0x1.dp-1,
- 0x1.cep-1, 0x1.cap-1, 0x1.c8p-1, 0x1.c4p-1, 0x1.cp-1, 0x1.bep-1, 0x1.bap-1,
- 0x1.b8p-1, 0x1.b4p-1, 0x1.b2p-1, 0x1.bp-1, 0x1.acp-1, 0x1.aap-1, 0x1.a6p-1,
- 0x1.a4p-1, 0x1.a2p-1, 0x1.9ep-1, 0x1.9cp-1, 0x1.9ap-1, 0x1.98p-1, 0x1.94p-1,
- 0x1.92p-1, 0x1.9p-1, 0x1.8ep-1, 0x1.8ap-1, 0x1.88p-1, 0x1.86p-1, 0x1.84p-1,
- 0x1.82p-1, 0x1.8p-1, 0x1.7ep-1, 0x1.7ap-1, 0x1.78p-1, 0x1.76p-1, 0x1.74p-1,
- 0x1.72p-1, 0x1.7p-1, 0x1.6ep-1, 0x1.6cp-1, 0x1.6ap-1, 0x1.68p-1, 0x1.66p-1,
- 0x1.64p-1, 0x1.62p-1, 0x1.6p-1, 0x1.5ep-1, 0x1.5cp-1, 0x1.5ap-1, 0x1.58p-1,
- 0x1.58p-1, 0x1.56p-1, 0x1.54p-1, 0x1.52p-1, 0x1.5p-1, 0x1.4ep-1, 0x1.4cp-1,
- 0x1.4ap-1, 0x1.4ap-1, 0x1.48p-1, 0x1.46p-1, 0x1.44p-1, 0x1.42p-1, 0x1.42p-1,
- 0x1.4p-1, 0x1.3ep-1, 0x1.3cp-1, 0x1.3cp-1, 0x1.3ap-1, 0x1.38p-1, 0x1.36p-1,
- 0x1.36p-1, 0x1.34p-1, 0x1.32p-1, 0x1.3p-1, 0x1.3p-1, 0x1.2ep-1, 0x1.2cp-1,
- 0x1.2cp-1, 0x1.2ap-1, 0x1.28p-1, 0x1.28p-1, 0x1.26p-1, 0x1.24p-1, 0x1.24p-1,
- 0x1.22p-1, 0x1.2p-1, 0x1.2p-1, 0x1.1ep-1, 0x1.1cp-1, 0x1.1cp-1, 0x1.1ap-1,
- 0x1.1ap-1, 0x1.18p-1, 0x1.16p-1, 0x1.16p-1, 0x1.14p-1, 0x1.14p-1, 0x1.12p-1,
- 0x1.12p-1, 0x1.1p-1, 0x1.0ep-1, 0x1.0ep-1, 0x1.0cp-1, 0x1.0cp-1, 0x1.0ap-1,
- 0x1.0ap-1, 0x1.08p-1, 0x1.08p-1, 0x1.06p-1, 0x1.06p-1, 0x1.04p-1, 0x1.04p-1,
- 0x1.02p-1, 0x1.02p-1, 0x1p-1,
-};
-
-// Extra constants for exact range reduction when FMA instructions are not
-// available:
-// r * c - 1 for r = 2^-8 * nearestint( 2^8 / (1 + i * 2^-7))
-// and c = 1 + i * 2^-7
-// with i = 0..128.
-[[maybe_unused]] constexpr double RCM1[129] = {
- 0.0, -0x1p-14, -0x1p-12, -0x1.2p-11, -0x1p-10, -0x1.9p-10,
- 0x1.fp-10, 0x1.28p-10, 0x1p-12, -0x1.9p-11, -0x1.fp-10, 0x1.2p-10,
- -0x1p-12, -0x1.cp-10, 0x1.1p-10, -0x1.5p-11, 0x1p-9, 0x1p-14,
- -0x1p-9, 0x1.ap-12, -0x1.ep-10, 0x1.8p-12, -0x1.1p-9, -0x1p-15,
- 0x1p-9, -0x1.ap-11, 0x1.1p-10, -0x1.f8p-10, -0x1p-12, 0x1.68p-10,
- -0x1.fp-10, -0x1.cp-12, 0x1p-10, 0x1.3p-9, -0x1.6p-10, -0x1.4p-13,
- 0x1p-10, 0x1.0cp-9, -0x1.08p-9, -0x1.2p-10, -0x1p-12, 0x1.2p-11,
- 0x1.5p-10, 0x1p-9, 0x1.5p-9, -0x1.1cp-9, -0x1.cp-10, -0x1.58p-10,
- -0x1p-10, -0x1.7p-11, -0x1p-11, -0x1.6p-12, -0x1p-12, -0x1.cp-13,
- -0x1p-12, -0x1.6p-12, -0x1p-11, -0x1.7p-11, -0x1p-10, -0x1.58p-10,
- -0x1.cp-10, -0x1.1cp-9, -0x1.6p-9, 0x1.5p-9, 0x1p-9, 0x1.5p-10,
- 0x1.2p-11, -0x1p-12, -0x1.2p-10, -0x1.08p-9, -0x1.88p-9, 0x1.0cp-9,
- 0x1p-10, -0x1.4p-13, -0x1.6p-10, -0x1.54p-9, 0x1.3p-9, 0x1p-10,
- -0x1.cp-12, -0x1.fp-10, 0x1.8p-9, 0x1.68p-10, -0x1p-12, -0x1.f8p-10,
- 0x1.7p-9, 0x1.1p-10, -0x1.ap-11, -0x1.6p-9, 0x1p-9, -0x1p-15,
- -0x1.1p-9, 0x1.48p-9, 0x1.8p-12, -0x1.ep-10, 0x1.6p-9, 0x1.ap-12,
- -0x1p-9, 0x1.48p-9, 0x1p-14, -0x1.4p-9, 0x1p-9, -0x1.5p-11,
- -0x1.bp-9, 0x1.1p-10, -0x1.cp-10, 0x1.54p-9, -0x1p-12, -0x1.9cp-9,
- 0x1.2p-10, -0x1.fp-10, 0x1.3p-9, -0x1.9p-11, 0x1.cp-9, 0x1p-12,
- -0x1.88p-9, 0x1.28p-10, -0x1.2p-9, 0x1.fp-10, -0x1.9p-10, 0x1.4cp-9,
- -0x1p-10, 0x1.9p-9, -0x1.2p-11, 0x1.c4p-9, -0x1p-12, 0x1.e8p-9,
- -0x1p-14, 0x1.fcp-9, 0.0,
-};
-
-// Generated by Sollya with:
-// for i from 0 to 128 do {
-// r = 2^-8 * nearestint( 2^8 / (1 + i*2^-7) );
-// b = nearestint(log(r)*2^43) * 2^-43;
-// c = round(log(r) - b, D, RN);
-// print("{", -c, ",", -b, "},");
-// };
-// We replace LOG_R1_DD[128] with log(1.0) == 0.0
-alignas(16) constexpr fputil::DoubleDouble LOG_R1_DD[129] = {
- {0.0, 0.0},
- {-0x1.0c76b999d2be8p-46, 0x1.010157589p-7},
- {-0x1.3dc5b06e2f7d2p-45, 0x1.0205658938p-6},
- {-0x1.aa0ba325a0c34p-45, 0x1.8492528c9p-6},
- {0x1.111c05cf1d753p-47, 0x1.0415d89e74p-5},
- {-0x1.c167375bdfd28p-45, 0x1.466aed42ep-5},
- {-0x1.29efbec19afa2p-47, 0x1.67c94f2d4cp-5},
- {0x1.0fc1a353bb42ep-45, 0x1.aaef2d0fbp-5},
- {-0x1.e113e4fc93b7bp-47, 0x1.eea31c006cp-5},
- {-0x1.5325d560d9e9bp-45, 0x1.1973bd1466p-4},
- {0x1.cc85ea5db4ed7p-45, 0x1.3bdf5a7d1ep-4},
- {-0x1.53a2582f4e1efp-48, 0x1.4d3115d208p-4},
- {0x1.c1e8da99ded32p-49, 0x1.700d30aeacp-4},
- {0x1.3115c3abd47dap-45, 0x1.9335e5d594p-4},
- {-0x1.e42b6b94407c8p-47, 0x1.a4e7640b1cp-4},
- {0x1.646d1c65aacd3p-45, 0x1.c885801bc4p-4},
- {0x1.a89401fa71733p-46, 0x1.da72763844p-4},
- {-0x1.534d64fa10afdp-45, 0x1.fe89139dbep-4},
- {0x1.1ef78ce2d07f2p-45, 0x1.1178e8227ep-3},
- {0x1.ca78e44389934p-45, 0x1.1aa2b7e23fp-3},
- {0x1.39d6ccb81b4a1p-47, 0x1.2d1610c868p-3},
- {0x1.62fa8234b7289p-51, 0x1.365fcb0159p-3},
- {0x1.5837954fdb678p-45, 0x1.4913d8333bp-3},
- {0x1.633e8e5697dc7p-45, 0x1.527e5e4a1bp-3},
- {-0x1.27023eb68981cp-46, 0x1.5bf406b544p-3},
- {-0x1.5118de59c21e1p-45, 0x1.6f0128b757p-3},
- {-0x1.c661070914305p-46, 0x1.7898d85445p-3},
- {-0x1.73d54aae92cd1p-47, 0x1.8beafeb39p-3},
- {0x1.7f22858a0ff6fp-47, 0x1.95a5adcf7p-3},
- {0x1.9904d6865817ap-45, 0x1.9f6c407089p-3},
- {-0x1.c358d4eace1aap-47, 0x1.b31d8575bdp-3},
- {-0x1.d4bc4595412b6p-45, 0x1.bd087383bep-3},
- {-0x1.1ec72c5962bd2p-48, 0x1.c6ffbc6f01p-3},
- {-0x1.84a7e75b6f6e4p-47, 0x1.d1037f2656p-3},
- {0x1.212276041f43p-51, 0x1.e530effe71p-3},
- {-0x1.a211565bb8e11p-51, 0x1.ef5ade4ddp-3},
- {0x1.bcbecca0cdf3p-46, 0x1.f991c6cb3bp-3},
- {-0x1.6f08c1485e94ap-46, 0x1.01eae5626c8p-2},
- {0x1.7188b163ceae9p-45, 0x1.0c42d67616p-2},
- {-0x1.c210e63a5f01cp-45, 0x1.1178e8227e8p-2},
- {0x1.b9acdf7a51681p-45, 0x1.16b5ccbacf8p-2},
- {0x1.ca6ed5147bdb7p-45, 0x1.1bf99635a68p-2},
- {0x1.a87deba46baeap-47, 0x1.214456d0eb8p-2},
- {0x1.c93c1df5bb3b6p-45, 0x1.269621134d8p-2},
- {0x1.a9cfa4a5004f4p-45, 0x1.2bef07cdc9p-2},
- {0x1.16ecdb0f177c8p-46, 0x1.36b6776be1p-2},
- {0x1.83b54b606bd5cp-46, 0x1.3c25277333p-2},
- {0x1.8e436ec90e09dp-47, 0x1.419b423d5e8p-2},
- {-0x1.f27ce0967d675p-45, 0x1.4718dc271c8p-2},
- {-0x1.e20891b0ad8a4p-45, 0x1.4c9e09e173p-2},
- {0x1.ebe708164c759p-45, 0x1.522ae0738ap-2},
- {0x1.fadedee5d40efp-46, 0x1.57bf753c8dp-2},
- {-0x1.a0b2a08a465dcp-47, 0x1.5d5bddf596p-2},
- {-0x1.db623e731aep-45, 0x1.630030b3abp-2},
- {0x1.0a0d32756ebap-45, 0x1.68ac83e9c68p-2},
- {0x1.721657c222d87p-46, 0x1.6e60ee6af18p-2},
- {0x1.d8b0949dc60b3p-45, 0x1.741d876c678p-2},
- {0x1.9ec7d2efd1778p-45, 0x1.79e26687cf8p-2},
- {-0x1.72090c812566ap-45, 0x1.7fafa3bd818p-2},
- {0x1.fd56f3333778ap-45, 0x1.85855776dc8p-2},
- {-0x1.05ae1e5e7047p-45, 0x1.8b639a88b3p-2},
- {-0x1.766b52ee6307dp-46, 0x1.914a8635bf8p-2},
- {-0x1.52313a502d9fp-46, 0x1.973a3431358p-2},
- {-0x1.52313a502d9fp-46, 0x1.973a3431358p-2},
- {-0x1.6279e10d0c0bp-45, 0x1.9d32bea15fp-2},
- {0x1.3c6457f9d79f5p-45, 0x1.a33440224f8p-2},
- {0x1.e36f2bea77a5dp-46, 0x1.a93ed3c8ad8p-2},
- {-0x1.17cc552774458p-45, 0x1.af5295248dp-2},
- {0x1.095252d841995p-46, 0x1.b56fa044628p-2},
- {0x1.7d85bf40a666dp-45, 0x1.bb9611b80ep-2},
- {0x1.cec807fe8e18p-45, 0x1.c1c60693fap-2},
- {0x1.cec807fe8e18p-45, 0x1.c1c60693fap-2},
- {-0x1.9b6ddc15249aep-45, 0x1.c7ff9c74558p-2},
- {-0x1.797c33ec7a6bp-47, 0x1.ce42f180648p-2},
- {0x1.35bafe9a767a8p-45, 0x1.d490246def8p-2},
- {-0x1.ea42d60dc616ap-46, 0x1.dae75484c98p-2},
- {-0x1.ea42d60dc616ap-46, 0x1.dae75484c98p-2},
- {-0x1.326b207322938p-46, 0x1.e148a1a2728p-2},
- {-0x1.465505372bd08p-45, 0x1.e7b42c3ddbp-2},
- {0x1.f27f45a470251p-45, 0x1.ee2a156b41p-2},
- {0x1.f27f45a470251p-45, 0x1.ee2a156b41p-2},
- {0x1.2cde56f014a8bp-46, 0x1.f4aa7ee0318p-2},
- {0x1.085fa3c164935p-47, 0x1.fb358af7a48p-2},
- {-0x1.53ba3b1727b1cp-47, 0x1.00e5ae5b208p-1},
- {-0x1.53ba3b1727b1cp-47, 0x1.00e5ae5b208p-1},
- {-0x1.4c45fe79539ep-47, 0x1.04360be7604p-1},
- {0x1.6812241edf5fdp-45, 0x1.078bf0533c4p-1},
- {0x1.f486b887e7e27p-46, 0x1.0ae76e2d054p-1},
- {0x1.f486b887e7e27p-46, 0x1.0ae76e2d054p-1},
- {0x1.c299807801742p-46, 0x1.0e4898611ccp-1},
- {-0x1.58647bb9ddcb2p-45, 0x1.11af823c75cp-1},
- {-0x1.58647bb9ddcb2p-45, 0x1.11af823c75cp-1},
- {-0x1.edd97a293ae49p-45, 0x1.151c3f6f298p-1},
- {0x1.4cc4ef8ab465p-46, 0x1.188ee40f23cp-1},
- {0x1.4cc4ef8ab465p-46, 0x1.188ee40f23cp-1},
- {0x1.cacdeed70e667p-51, 0x1.1c07849ae6p-1},
- {-0x1.a7242c9fe81d3p-45, 0x1.1f8635fc618p-1},
- {-0x1.a7242c9fe81d3p-45, 0x1.1f8635fc618p-1},
- {0x1.2fc066e48667bp-46, 0x1.230b0d8bebcp-1},
- {-0x1.b61f10522625p-47, 0x1.269621134dcp-1},
- {-0x1.b61f10522625p-47, 0x1.269621134dcp-1},
- {0x1.06d2be797882dp-45, 0x1.2a2786d0ecp-1},
- {-0x1.7a6e507b9dc11p-46, 0x1.2dbf557b0ep-1},
- {-0x1.7a6e507b9dc11p-46, 0x1.2dbf557b0ep-1},
- {-0x1.74e93c5a0ed9cp-45, 0x1.315da443408p-1},
- {-0x1.74e93c5a0ed9cp-45, 0x1.315da443408p-1},
- {0x1.0b83f9527e6acp-46, 0x1.35028ad9d8cp-1},
- {-0x1.18b7abb5569a4p-45, 0x1.38ae2171978p-1},
- {-0x1.18b7abb5569a4p-45, 0x1.38ae2171978p-1},
- {-0x1.2b7367cfe13c2p-47, 0x1.3c6080c36cp-1},
- {-0x1.2b7367cfe13c2p-47, 0x1.3c6080c36cp-1},
- {-0x1.6ce7930f0c74cp-45, 0x1.4019c2125ccp-1},
- {-0x1.6ce7930f0c74cp-45, 0x1.4019c2125ccp-1},
- {-0x1.d984f481051f7p-48, 0x1.43d9ff2f924p-1},
- {-0x1.2cb6af94d60aap-45, 0x1.47a1527e8a4p-1},
- {-0x1.2cb6af94d60aap-45, 0x1.47a1527e8a4p-1},
- {0x1.f7115ed4c541cp-49, 0x1.4b6fd6f970cp-1},
- {0x1.f7115ed4c541cp-49, 0x1.4b6fd6f970cp-1},
- {-0x1.e6c516d93b8fbp-45, 0x1.4f45a835a5p-1},
- {-0x1.e6c516d93b8fbp-45, 0x1.4f45a835a5p-1},
- {0x1.5ccc45d257531p-47, 0x1.5322e268678p-1},
- {0x1.5ccc45d257531p-47, 0x1.5322e268678p-1},
- {0x1.9980bff3303ddp-47, 0x1.5707a26bb8cp-1},
- {0x1.9980bff3303ddp-47, 0x1.5707a26bb8cp-1},
- {0x1.dfa63ac10c9fbp-45, 0x1.5af405c3648p-1},
- {0x1.dfa63ac10c9fbp-45, 0x1.5af405c3648p-1},
- {0x1.202380cda46bep-45, 0x1.5ee82aa2418p-1},
- {0x1.202380cda46bep-45, 0x1.5ee82aa2418p-1},
- {0.0, 0.0},
-};
-
-// Degree-7 minimax polynomial log(1 + v) ~ v - v^2 / 2 + ...
-// generated by Sollya with:
-// > P = fpminimax(log(1 + x)/x, 6, [|1, 1, D...|],
-// [-0x1.69000000000edp-8, 0x1.7f00000000081p-8]);
-constexpr double P_COEFFS[6] = {-0x1p-1,
- 0x1.5555555555166p-2,
- -0x1.fffffffdb7746p-3,
- 0x1.99999a8718a6p-3,
- -0x1.555874ce8ce22p-3,
- 0x1.24335555ddbe5p-3};
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-// Extra errors from P is from using x^2 to reduce evaluation latency and
-// directional rounding.
-constexpr double P_ERR = 0x1.0p-49;
-
-// log(2) with 128-bit precision generated by SageMath with:
-// def format_hex(value):
-// l = hex(value)[2:]
-// n = 8
-// x = [l[i:i + n] for i in range(0, len(l), n)]
-// return "0x" + "'".join(x) + "_u128"
-// (s, m, e) = RealField(128)(2).log().sign_mantissa_exponent();
-// print(format_hex(m));
-constexpr Float128 LOG_2(Sign::POS, /*exponent=*/-128, /*mantissa=*/
- 0xb17217f7'd1cf79ab'c9e3b398'03f2f6af_u128);
-
-// -log(r1) with 128-bit precision generated by SageMath with:
-//
-// for i in range(129):
-// r = 2^-8 * round( 2^8 / (1 + i*2^(-7)) );
-// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
-// print("{Sign::POS,", e, ", format_hex(m), "},");
-constexpr Float128 LOG_R1[129] = {
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -134, 0x8080abac'46f38946'662d417c'ed007a46_u128},
- {Sign::POS, -133, 0x8102b2c4'9ac23a4f'91d082dc'e3ddcd38_u128},
- {Sign::POS, -133, 0xc2492946'4655f45c'da5f3cc0'b3251dbd_u128},
- {Sign::POS, -132, 0x820aec4f'3a222380'b9e3aea6'c444ef07_u128},
- {Sign::POS, -132, 0xa33576a1'6f1f4c64'521016bd'904dc968_u128},
- {Sign::POS, -132, 0xb3e4a796'a5dac208'27cca0bc'c06c2f92_u128},
- {Sign::POS, -132, 0xd5779687'd887e0d1'a9dda170'56e45ed5_u128},
- {Sign::POS, -132, 0xf7518e00'35c3dd83'606d8909'3278a939_u128},
- {Sign::POS, -131, 0x8cb9de8a'32ab368a'a7c98595'30a45153_u128},
- {Sign::POS, -131, 0x9defad3e'8f73217a'976d3b5b'45f6ca0b_u128},
- {Sign::POS, -131, 0xa6988ae9'03f562ed'3e858f08'597b3a69_u128},
- {Sign::POS, -131, 0xb8069857'560707a3'6a677b4c'8bec22e1_u128},
- {Sign::POS, -131, 0xc99af2ea'ca4c4570'eaf51f66'692844ba_u128},
- {Sign::POS, -131, 0xd273b205'8de1bd49'46bbf837'b4d320c6_u128},
- {Sign::POS, -131, 0xe442c00d'e2591b47'196ab34c'e0bccd12_u128},
- {Sign::POS, -131, 0xed393b1c'22351280'3f4e2e66'0317d55f_u128},
- {Sign::POS, -131, 0xff4489ce'deab2ca6'c17bd40d'8d9291ec_u128},
- {Sign::POS, -130, 0x88bc7411'3f23def1'9c5a0fe3'96f40f1e_u128},
- {Sign::POS, -130, 0x8d515bf1'1fb94f1c'88713268'840cbcc0_u128},
- {Sign::POS, -130, 0x968b0864'3409ceb6'65c0da50'6a088484_u128},
- {Sign::POS, -130, 0x9b2fe580'ac80b17d'411a5b94'4aca8708_u128},
- {Sign::POS, -130, 0xa489ec19'9dab06f2'a9fb6cf0'ecb411b7_u128},
- {Sign::POS, -130, 0xa93f2f25'0dac67d1'cad2fb8d'48054ae0_u128},
- {Sign::POS, -130, 0xadfa035a'a1ed8fdc'149767e4'10316d2c_u128},
- {Sign::POS, -130, 0xb780945b'ab55dce4'34c7bc3d'32750fde_u128},
- {Sign::POS, -130, 0xbc4c6c2a'226399ef'8f6ebcfb'2016a439_u128},
- {Sign::POS, -130, 0xc5f57f59'c7f46155'aa8b6997'a402bf30_u128},
- {Sign::POS, -130, 0xcad2d6e7'b80bf914'2c507fb7'a3d0bf6a_u128},
- {Sign::POS, -130, 0xcfb62038'44b3209a'd0cb02f3'3f79c16c_u128},
- {Sign::POS, -130, 0xd98ec2ba'de71e539'58a98f2a'd65bee9b_u128},
- {Sign::POS, -130, 0xde8439c1'dec56877'4d57da94'5b5d0aaa_u128},
- {Sign::POS, -130, 0xe37fde37'807b84e3'4e9a750b'6b68781d_u128},
- {Sign::POS, -130, 0xe881bf93'2af3dac0'c524848e'3443e040_u128},
- {Sign::POS, -130, 0xf29877ff'38809091'3b020fa1'820c9492_u128},
- {Sign::POS, -130, 0xf7ad6f26'e7ff2ef7'54d2238f'75f969b1_u128},
- {Sign::POS, -130, 0xfcc8e365'9d9bcbec'ca0cdf30'1431b60f_u128},
- {Sign::POS, -129, 0x80f572b1'363487b9'f5bd0b5b'3479d5f4_u128},
- {Sign::POS, -129, 0x86216b3b'0b17188b'163ceae8'8f720f1e_u128},
- {Sign::POS, -129, 0x88bc7411'3f23def1'9c5a0fe3'96f40f1e_u128},
- {Sign::POS, -129, 0x8b5ae65d'67db9acd'f7a51681'26a58b9a_u128},
- {Sign::POS, -129, 0x8dfccb1a'd35ca6ed'5147bdb6'ddcaf59c_u128},
- {Sign::POS, -129, 0x90a22b68'75c6a1f7'ae91aeba'609c8877_u128},
- {Sign::POS, -129, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
- {Sign::POS, -129, 0x95f783e6'e49a9cfa'4a5004f3'ef063313_u128},
- {Sign::POS, -129, 0x9b5b3bb5'f088b766'd878bbe3'd392be25_u128},
- {Sign::POS, -129, 0x9e1293b9'998c1daa'5b035eae'273a855f_u128},
- {Sign::POS, -129, 0xa0cda11e'af46390d'bb243827'3918db7e_u128},
- {Sign::POS, -129, 0xa38c6e13'8e20d831'f698298a'dddd7f32_u128},
- {Sign::POS, -129, 0xa64f04f0'b961df76'e4f5275c'2d15c21f_u128},
- {Sign::POS, -129, 0xa9157039'c51ebe70'8164c759'686a2209_u128},
- {Sign::POS, -129, 0xabdfba9e'468fd6f6'f72ea077'49ce6bd3_u128},
- {Sign::POS, -129, 0xaeadeefa'caf97d35'7dd6e688'ebb13b03_u128},
- {Sign::POS, -129, 0xb1801859'd56249dc'18ce51ff'f99479cd_u128},
- {Sign::POS, -129, 0xb45641f4'e350a0d3'2756eba0'0bc33978_u128},
- {Sign::POS, -129, 0xb7307735'78cb90b2'be1116c3'466beb6d_u128},
- {Sign::POS, -129, 0xba0ec3b6'33dd8b09'49dc60b2'b059a60b_u128},
- {Sign::POS, -129, 0xbcf13343'e7d9ec7d'2efd1778'1bb3afec_u128},
- {Sign::POS, -129, 0xbfd7d1de'c0a8df6f'37eda996'244bccb0_u128},
- {Sign::POS, -129, 0xc2c2abbb'6e5fd56f'33337789'd592e296_u128},
- {Sign::POS, -129, 0xc5b1cd44'596fa51e'1a18fb8f'9f9ef280_u128},
- {Sign::POS, -129, 0xc8a5431a'dfb44ca5'688ce7c1'a75e341a_u128},
- {Sign::POS, -129, 0xcb9d1a18'9ab56e76'2d7e9307'c70c0668_u128},
- {Sign::POS, -129, 0xcb9d1a18'9ab56e76'2d7e9307'c70c0668_u128},
- {Sign::POS, -129, 0xce995f50'af69d861'ef2f3f4f'861ad6a9_u128},
- {Sign::POS, -129, 0xd19a2011'27d3c645'7f9d79f5'1dcc7301_u128},
- {Sign::POS, -129, 0xd49f69e4'56cf1b79'5f53bd2e'406e66e7_u128},
- {Sign::POS, -129, 0xd7a94a92'466e833a'ad88bba7'd0cee8e0_u128},
- {Sign::POS, -129, 0xdab7d022'31484a92'96c20cca'6efe2ac5_u128},
- {Sign::POS, -129, 0xddcb08dc'0717d85b'f40a666c'87842843_u128},
- {Sign::POS, -129, 0xe0e30349'fd1cec80'7fe8e180'2aba24d6_u128},
- {Sign::POS, -129, 0xe0e30349'fd1cec80'7fe8e180'2aba24d6_u128},
- {Sign::POS, -129, 0xe3ffce3a'2aa64922'3eadb651'b49ac53a_u128},
- {Sign::POS, -129, 0xe72178c0'323a1a0f'304e1653'e71d9973_u128},
- {Sign::POS, -129, 0xea481236'f7d35baf'e9a767a8'0d6d97e8_u128},
- {Sign::POS, -129, 0xed73aa42'64b0ade9'4f91cf4b'33e42998_u128},
- {Sign::POS, -129, 0xed73aa42'64b0ade9'4f91cf4b'33e42998_u128},
- {Sign::POS, -129, 0xf0a450d1'39366ca6'fc66eb64'08ff6433_u128},
- {Sign::POS, -129, 0xf3da161e'ed6b9aaf'ac8d42f7'8d3e65d3_u128},
- {Sign::POS, -129, 0xf7150ab5'a09f27f4'5a470250'd40ebe90_u128},
- {Sign::POS, -129, 0xf7150ab5'a09f27f4'5a470250'd40ebe90_u128},
- {Sign::POS, -129, 0xfa553f70'18c966f2'b780a545'a1b54dcf_u128},
- {Sign::POS, -129, 0xfd9ac57b'd244217e'8f05924d'258c14c5_u128},
- {Sign::POS, -128, 0x8072d72d'903d588b'89d1b09c'70c4010a_u128},
- {Sign::POS, -128, 0x8072d72d'903d588b'89d1b09c'70c4010a_u128},
- {Sign::POS, -128, 0x821b05f3'b01d6774'030d58c3'f7e2ea1f_u128},
- {Sign::POS, -128, 0x83c5f829'9e2b4091'20f6fafe'8fbb68b9_u128},
- {Sign::POS, -128, 0x8573b716'82a7d21a'e21f9f89'c1ab80b2_u128},
- {Sign::POS, -128, 0x8573b716'82a7d21a'e21f9f89'c1ab80b2_u128},
- {Sign::POS, -128, 0x87244c30'8e670a66'01e005d0'6dbfa8f8_u128},
- {Sign::POS, -128, 0x88d7c11e'3ad53cdc'223111a7'07b6de2c_u128},
- {Sign::POS, -128, 0x88d7c11e'3ad53cdc'223111a7'07b6de2c_u128},
- {Sign::POS, -128, 0x8a8e1fb7'94b09134'2eb628db'a173c82d_u128},
- {Sign::POS, -128, 0x8c477207'91e53313'be2ad194'15fe25a5_u128},
- {Sign::POS, -128, 0x8c477207'91e53313'be2ad194'15fe25a5_u128},
- {Sign::POS, -128, 0x8e03c24d'73003959'bddae1cc'ce247838_u128},
- {Sign::POS, -128, 0x8fc31afe'30b2c6de'9b00bf16'7e95da67_u128},
- {Sign::POS, -128, 0x8fc31afe'30b2c6de'9b00bf16'7e95da67_u128},
- {Sign::POS, -128, 0x918586c5'f5e4bf01'9b92199e'd1a4bab1_u128},
- {Sign::POS, -128, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
- {Sign::POS, -128, 0x934b1089'a6dc93c1'df5bb3b6'0554e152_u128},
- {Sign::POS, -128, 0x9513c368'76083695'f3cbc416'a2418012_u128},
- {Sign::POS, -128, 0x96dfaabd'86fa1646'be1188fb'c94e2f15_u128},
- {Sign::POS, -128, 0x96dfaabd'86fa1646'be1188fb'c94e2f15_u128},
- {Sign::POS, -128, 0x98aed221'a03458b6'1d2f8932'1647b358_u128},
- {Sign::POS, -128, 0x98aed221'a03458b6'1d2f8932'1647b358_u128},
- {Sign::POS, -128, 0x9a81456c'ec642e0f'e549f9aa'ea3cb5e1_u128},
- {Sign::POS, -128, 0x9c5710b8'cbb73a42'a2554b2d'd4619e63_u128},
- {Sign::POS, -128, 0x9c5710b8'cbb73a42'a2554b2d'd4619e63_u128},
- {Sign::POS, -128, 0x9e304061'b5fda919'30603d87'b6df81ad_u128},
- {Sign::POS, -128, 0x9e304061'b5fda919'30603d87'b6df81ad_u128},
- {Sign::POS, -128, 0xa00ce109'2e5498c3'67879c5a'30cd1242_u128},
- {Sign::POS, -128, 0xa00ce109'2e5498c3'67879c5a'30cd1242_u128},
- {Sign::POS, -128, 0xa1ecff97'c91e267b'0b7efae0'8e597e16_u128},
- {Sign::POS, -128, 0xa3d0a93f'45169a4a'83594fab'088c0d65_u128},
- {Sign::POS, -128, 0xa3d0a93f'45169a4a'83594fab'088c0d65_u128},
- {Sign::POS, -128, 0xa5b7eb7c'b860fb88'af6a62a0'dec6e073_u128},
- {Sign::POS, -128, 0xa5b7eb7c'b860fb88'af6a62a0'dec6e073_u128},
- {Sign::POS, -128, 0xa7a2d41a'd270c9d7'49362382'a768847a_u128},
- {Sign::POS, -128, 0xa7a2d41a'd270c9d7'49362382'a768847a_u128},
- {Sign::POS, -128, 0xa9917134'33c2b998'8ba4aea6'14d05701_u128},
- {Sign::POS, -128, 0xa9917134'33c2b998'8ba4aea6'14d05701_u128},
- {Sign::POS, -128, 0xab83d135'dc633301'7fe6607b'a902ef3c_u128},
- {Sign::POS, -128, 0xab83d135'dc633301'7fe6607b'a902ef3c_u128},
- {Sign::POS, -128, 0xad7a02e1'b24efd31'd60864fd'949b4bd3_u128},
- {Sign::POS, -128, 0xad7a02e1'b24efd31'd60864fd'949b4bd3_u128},
- {Sign::POS, -128, 0xaf741551'20c9011c'066d235e'e63073dd_u128},
- {Sign::POS, -128, 0xaf741551'20c9011c'066d235e'e63073dd_u128},
- {Sign::POS, 0, 0_u128},
-};
-
-// Logarithm range reduction - Step 2:
-// s(k) = 2^-18 round( 2^18 / (1 + k*2^-14) ) - 1 for k = -91 .. 96
-// Output range:
-// [-0x1.1037c00000040271p-15 , 0x1.108480000008096cp-15]
-constexpr double S2[198] = {
- 0x1.6ep-8, 0x1.6ap-8, 0x1.66p-8, 0x1.62p-8, 0x1.5dcp-8,
- 0x1.59cp-8, 0x1.55cp-8, 0x1.51cp-8, 0x1.4dcp-8, 0x1.49cp-8,
- 0x1.458p-8, 0x1.418p-8, 0x1.3d8p-8, 0x1.398p-8, 0x1.358p-8,
- 0x1.318p-8, 0x1.2d8p-8, 0x1.294p-8, 0x1.254p-8, 0x1.214p-8,
- 0x1.1d4p-8, 0x1.194p-8, 0x1.154p-8, 0x1.114p-8, 0x1.0dp-8,
- 0x1.09p-8, 0x1.05p-8, 0x1.01p-8, 0x1.fap-9, 0x1.f2p-9,
- 0x1.eap-9, 0x1.e2p-9, 0x1.d98p-9, 0x1.d18p-9, 0x1.c98p-9,
- 0x1.c18p-9, 0x1.b98p-9, 0x1.b18p-9, 0x1.a98p-9, 0x1.a18p-9,
- 0x1.998p-9, 0x1.91p-9, 0x1.89p-9, 0x1.81p-9, 0x1.79p-9,
- 0x1.71p-9, 0x1.69p-9, 0x1.61p-9, 0x1.59p-9, 0x1.51p-9,
- 0x1.49p-9, 0x1.41p-9, 0x1.388p-9, 0x1.308p-9, 0x1.288p-9,
- 0x1.208p-9, 0x1.188p-9, 0x1.108p-9, 0x1.088p-9, 0x1.008p-9,
- 0x1.f1p-10, 0x1.e1p-10, 0x1.d1p-10, 0x1.c1p-10, 0x1.b1p-10,
- 0x1.a1p-10, 0x1.91p-10, 0x1.81p-10, 0x1.71p-10, 0x1.6p-10,
- 0x1.5p-10, 0x1.4p-10, 0x1.3p-10, 0x1.2p-10, 0x1.1p-10,
- 0x1p-10, 0x1.ep-11, 0x1.cp-11, 0x1.ap-11, 0x1.8p-11,
- 0x1.6p-11, 0x1.4p-11, 0x1.2p-11, 0x1p-11, 0x1.cp-12,
- 0x1.8p-12, 0x1.4p-12, 0x1p-12, 0x1.8p-13, 0x1p-13,
- 0x1p-14, 0.0, -0x1p-14, -0x1p-13, -0x1.8p-13,
- -0x1p-12, -0x1.4p-12, -0x1.8p-12, -0x1.cp-12, -0x1p-11,
- -0x1.2p-11, -0x1.4p-11, -0x1.6p-11, -0x1.8p-11, -0x1.ap-11,
- -0x1.cp-11, -0x1.ep-11, -0x1p-10, -0x1.1p-10, -0x1.2p-10,
- -0x1.3p-10, -0x1.4p-10, -0x1.5p-10, -0x1.6p-10, -0x1.6fp-10,
- -0x1.7fp-10, -0x1.8fp-10, -0x1.9fp-10, -0x1.afp-10, -0x1.bfp-10,
- -0x1.cfp-10, -0x1.dfp-10, -0x1.efp-10, -0x1.ffp-10, -0x1.078p-9,
- -0x1.0f8p-9, -0x1.178p-9, -0x1.1f8p-9, -0x1.278p-9, -0x1.2f8p-9,
- -0x1.378p-9, -0x1.3fp-9, -0x1.47p-9, -0x1.4fp-9, -0x1.57p-9,
- -0x1.5fp-9, -0x1.67p-9, -0x1.6fp-9, -0x1.77p-9, -0x1.7fp-9,
- -0x1.87p-9, -0x1.8fp-9, -0x1.968p-9, -0x1.9e8p-9, -0x1.a68p-9,
- -0x1.ae8p-9, -0x1.b68p-9, -0x1.be8p-9, -0x1.c68p-9, -0x1.ce8p-9,
- -0x1.d68p-9, -0x1.dep-9, -0x1.e6p-9, -0x1.eep-9, -0x1.f6p-9,
- -0x1.fep-9, -0x1.03p-8, -0x1.07p-8, -0x1.0bp-8, -0x1.0fp-8,
- -0x1.12cp-8, -0x1.16cp-8, -0x1.1acp-8, -0x1.1ecp-8, -0x1.22cp-8,
- -0x1.26cp-8, -0x1.2acp-8, -0x1.2e8p-8, -0x1.328p-8, -0x1.368p-8,
- -0x1.3a8p-8, -0x1.3e8p-8, -0x1.428p-8, -0x1.464p-8, -0x1.4a4p-8,
- -0x1.4e4p-8, -0x1.524p-8, -0x1.564p-8, -0x1.5a4p-8, -0x1.5ep-8,
- -0x1.62p-8, -0x1.66p-8, -0x1.6ap-8, -0x1.6ep-8, -0x1.72p-8,
- -0x1.75cp-8, -0x1.79cp-8, -0x1.7dcp-8,
-};
-
-// -log(r) for the second step, generated by SageMath with:
-//
-// for i in range(-91, 97):
-// r = 2^-18 * round( 2^18 / (1 + i*2^(-14)) );
-// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
-// print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",
-// format_hex(m), "},");
-constexpr Float128 LOG_R2[198] = {
- {Sign::NEG, -135, 0xb67dab2a'1a5742a4'a0e061c5'f7431c5e_u128},
- {Sign::NEG, -135, 0xb4807f24'af682939'5d5bfe7b'969ed6ec_u128},
- {Sign::NEG, -135, 0xb2834b35'b4d54d5f'4d08702d'dfabc23f_u128},
- {Sign::NEG, -135, 0xb0860f5c'eba9be95'd4d36650'8b9953df_u128},
- {Sign::NEG, -135, 0xae68f71a'a09e8847'ac18a289'f8f214a9_u128},
- {Sign::NEG, -135, 0xac6baaee'd676e8f1'd5b42054'abb88c45_u128},
- {Sign::NEG, -135, 0xaa6e56d8'7cd632d6'09809d58'ee484964_u128},
- {Sign::NEG, -135, 0xa870fad7'54bb8791'b9e6fc7c'72f06d73_u128},
- {Sign::NEG, -135, 0xa67396eb'1f231892'6f78d6d0'105c00e2_u128},
- {Sign::NEG, -135, 0xa4762b13'9d0626e7'028f7126'29209148_u128},
- {Sign::NEG, -135, 0xa258dfd1'0aedaa67'c98d898e'f172df02_u128},
- {Sign::NEG, -135, 0xa05b63a3'73e60a83'fcc37c3c'3062bfa1_u128},
- {Sign::NEG, -135, 0x9e5ddf89'cf42f501'3eb450db'05763c36_u128},
- {Sign::NEG, -135, 0x9c605383'ddf1b88c'7146a86f'd458b775_u128},
- {Sign::NEG, -135, 0x9a62bf91'60dcb286'c20a0c92'81474436_u128},
- {Sign::NEG, -135, 0x986523b2'18eb4ed6'cdc57316'ec4aebc3_u128},
- {Sign::NEG, -135, 0x96677fe5'c70207b9'c060dad7'4cef4273_u128},
- {Sign::NEG, -135, 0x9449f92d'2ff44633'ed8def1a'3e433499_u128},
- {Sign::NEG, -135, 0x924c4507'3220b5e0'3ce7a1f8'5c27b4fc_u128},
- {Sign::NEG, -135, 0x904e88f3'68fea63f'f2ca8934'49f7f2cb_u128},
- {Sign::NEG, -135, 0x8e50c4f1'956699ed'8d77d9fa'bd2853cf_u128},
- {Sign::NEG, -135, 0x8c52f901'782e20ec'93e828d7'5b58ded4_u128},
- {Sign::NEG, -135, 0x8a552522'd227d87a'9f9605b0'53c5acf0_u128},
- {Sign::NEG, -135, 0x88574955'64236ae0'62a14939'3bca7241_u128},
- {Sign::NEG, -135, 0x86398719'b66bac7c'aea6b56c'e89203d4_u128},
- {Sign::NEG, -135, 0x843b9aef'044e4dcc'0242bd86'd00609b2_u128},
- {Sign::NEG, -135, 0x823da6d4'c89c6927'daabf927'74bac84e_u128},
- {Sign::NEG, -135, 0x803faaca'c419abf2'a1c6f3fc'242ef8d0_u128},
- {Sign::NEG, -136, 0xfc834da1'6f0d9f57'a225ebc0'2e6d9dd4_u128},
- {Sign::NEG, -136, 0xf88735cc'c7433381'c33f6ad3'40ae18a9_u128},
- {Sign::NEG, -136, 0xf48b0e17'1249b6bc'70b2a4d3'8a242244_u128},
- {Sign::NEG, -136, 0xf08ed67f'd190e280'1d548190'48b811b0_u128},
- {Sign::NEG, -136, 0xec52ca07'ed95f236'9c21b650'afe9ede0_u128},
- {Sign::NEG, -136, 0xe85671ad'ecd28aac'935519c9'6d30e463_u128},
- {Sign::NEG, -136, 0xe45a0970'dc912ca7'ba88f6f2'e2672cfe_u128},
- {Sign::NEG, -136, 0xe05d9150'3e298bc8'0b1a8b84'657ae069_u128},
- {Sign::NEG, -136, 0xdc61094b'92ed70ef'ea3bff8d'197b20a1_u128},
- {Sign::NEG, -136, 0xd8647162'5c28b9e5'cdbb931d'6fecc249_u128},
- {Sign::NEG, -136, 0xd467c994'1b2158f5'd971d560'd5f00820_u128},
- {Sign::NEG, -136, 0xd06b11e0'51175493'75563561'244c090b_u128},
- {Sign::NEG, -136, 0xcc6e4a46'7f44c6fa'dc393c9a'3f3b380f_u128},
- {Sign::NEG, -136, 0xc831a4c6'f6fa709d'e6abe6e9'e4ee2096_u128},
- {Sign::NEG, -136, 0xc434bc61'24a0f16e'3ce3c822'8583a66e_u128},
- {Sign::NEG, -136, 0xc037c413'c61bfd93'b96a79f5'c5a4963a_u128},
- {Sign::NEG, -136, 0xbc3abbde'5c8d9bde'aaef2733'7008679f_u128},
- {Sign::NEG, -136, 0xb83da3c0'6911e509'a49a3fca'ddc8bc5a_u128},
- {Sign::NEG, -136, 0xb4407bb9'6cbf035a'e0254feb'785362fa_u128},
- {Sign::NEG, -136, 0xb04343c8'e8a53245'9893a4e2'5ab9dc95_u128},
- {Sign::NEG, -136, 0xac45fbee'5dcebe0b'5d8b0f40'a3708915_u128},
- {Sign::NEG, -136, 0xa848a429'4d40035d'5f4c11c2'c7a58c69_u128},
- {Sign::NEG, -136, 0xa44b3c79'37f76efd'b348cc5d'f706ffba_u128},
- {Sign::NEG, -136, 0xa04dc4dd'9eed7d60'9159f2c5'5a18befd_u128},
- {Sign::NEG, -136, 0x9c106456'3058bef3'bdfdee41'fe6a5a02_u128},
- {Sign::NEG, -136, 0x9812cbe3'46475a24'4580ddf8'9853254d_u128},
- {Sign::NEG, -136, 0x94152383'53489ffb'ac75e10d'61fc3ee8_u128},
- {Sign::NEG, -136, 0x90176b35'd83ce8e2'cad9b30b'29736155_u128},
- {Sign::NEG, -136, 0x8c19a2fa'55fe9b14'6f881deb'98fc45f3_u128},
- {Sign::NEG, -136, 0x881bcad0'4d622a3e'70a04b63'b7248c96_u128},
- {Sign::NEG, -136, 0x841de2b7'3f361722'b4823fb4'8035eddd_u128},
- {Sign::NEG, -136, 0x801feaae'ac42ef38'3364ccb5'b13cd47f_u128},
- {Sign::NEG, -137, 0xf843c56c'2a969897'e306977b'049f0ad5_u128},
- {Sign::NEG, -137, 0xf0479599'f617a843'e3c4d9e9'619bc045_u128},
- {Sign::NEG, -137, 0xe84b45e5'bc76702c'4356d525'b5e6432d_u128},
- {Sign::NEG, -137, 0xe04ed64e'7f14697a'7839dcd7'989339ab_u128},
- {Sign::NEG, -137, 0xd85246d3'3f47230b'4e21f045'ecb76f23_u128},
- {Sign::NEG, -137, 0xd0559772'fe5840b0'902e248d'd4ba9b28_u128},
- {Sign::NEG, -137, 0xc858c82c'bd857a72'a4444906'7ef92e01_u128},
- {Sign::NEG, -137, 0xc05bd8ff'7e009bd2'17926207'cc22e4e6_u128},
- {Sign::NEG, -137, 0xb85ec9ea'40ef8309'1c349622'f3fa5d82_u128},
- {Sign::NEG, -137, 0xafe1c6ec'e1a058dd'97fa2fd0'c9dc723e_u128},
- {Sign::NEG, -137, 0xa7e47606'048b1a65'983e8089'7cf1e60f_u128},
- {Sign::NEG, -137, 0x9fe70534'1d236102'7199cd06'ae5d39b3_u128},
- {Sign::NEG, -137, 0x97e97476'2c5e8f58'43cd18a7'2a051a96_u128},
- {Sign::NEG, -137, 0x8febc3cb'332616ff'7b6d1248'c3e1fd40_u128},
- {Sign::NEG, -137, 0x87edf332'325777c5'f5572a88'14c703af_u128},
- {Sign::NEG, -138, 0xffe00554'55887de0'26828c92'649a3a39_u128},
- {Sign::NEG, -138, 0xefe3e464'3a640cf3'82c550bd'1216d82a_u128},
- {Sign::NEG, -138, 0xdfe78392'14b4e8ae'da6959f7'f0e01bf0_u128},
- {Sign::NEG, -138, 0xcfeae2db'e5d6736d'da93e2fa'85a8f214_u128},
- {Sign::NEG, -138, 0xbfee023f'af0c2480'b47505bf'a5a03b06_u128},
- {Sign::NEG, -138, 0xaff0e1bb'718186ad'b1475a51'80a43520_u128},
- {Sign::NEG, -138, 0x9ff3814d'2e4a36b2'a8740b91'c95df537_u128},
- {Sign::NEG, -138, 0x8ff5e0f2'e661e1c6'57d895d3'5921b59c_u128},
- {Sign::NEG, -139, 0xfff00155'35588833'3c56c598'c659c2a3_u128},
- {Sign::NEG, -139, 0xdff3c0e4'97ea4eb1'2ef8ec33'ed9d782a_u128},
- {Sign::NEG, -139, 0xbff7008f'f5e0c257'379eba7e'6465ff63_u128},
- {Sign::NEG, -139, 0x9ff9c053'5073a370'3f972b78'3fcab757_u128},
- {Sign::NEG, -140, 0xfff80055'51558885'de026e27'1ee0549d_u128},
- {Sign::NEG, -140, 0xbffb8023'febc0c25'eceb47ea'01f6c632_u128},
- {Sign::NEG, -141, 0xfffc0015'54d55888'7333c578'57e1ed52_u128},
- {Sign::NEG, -142, 0xfffe0005'55455588'87dde026'fa704374_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -141, 0x80010002'aab2aac4'44999abe'2fe2cc65_u128},
- {Sign::POS, -140, 0x8002000a'aaeaac44'4eef3815'81464ccb_u128},
- {Sign::POS, -140, 0xc0048024'01440c26'dfeb4850'85f6f454_u128},
- {Sign::POS, -139, 0x8004002a'acaac445'99abe3be'3a1c6e93_u128},
- {Sign::POS, -139, 0xa0064053'5a37a37a'6bc1e20e'ac8448b4_u128},
- {Sign::POS, -139, 0xc0090090'0a20c275'979eedc0'64c242fd_u128},
- {Sign::POS, -139, 0xe00c40e4'bd6e4efd'c72446cc'1bf728bd_u128},
- {Sign::POS, -138, 0x800800aa'baac446e'f381b821'bbb569e5_u128},
- {Sign::POS, -138, 0x900a20f3'19a3e273'569b26aa'a485ea5c_u128},
- {Sign::POS, -138, 0xa00c814d'7c6a37f8'2dcf56c8'3c80b028_u128},
- {Sign::POS, -138, 0xb00f21bb'e3e388ee'5f697682'84463b9b_u128},
- {Sign::POS, -138, 0xc0120240'510c284c'b48ea6c0'5e2773a1_u128},
- {Sign::POS, -138, 0xd01522dc'c4f87991'14d9d761'96d8043a_u128},
- {Sign::POS, -138, 0xe0188393'40d4f241'e016a611'a4415d72_u128},
- {Sign::POS, -138, 0xf01c2465'c5e61b6f'661e135f'49a47c40_u128},
- {Sign::POS, -137, 0x801002ab'2ac4499a'be6bf0fa'435e8383_u128},
- {Sign::POS, -137, 0x88121333'7898871e'9a31ba0c'bc030353_u128},
- {Sign::POS, -137, 0x901443cc'cd362c9f'54b57dfe'0c4c840f_u128},
- {Sign::POS, -137, 0x98169478'296fad41'7ad1e9c3'15328f7e_u128},
- {Sign::POS, -137, 0xa0190536'8e2389b3'1f3f686c'f3d6be22_u128},
- {Sign::POS, -137, 0xa81b9608'fc3c50ec'f105b66e'c4703ede_u128},
- {Sign::POS, -137, 0xb01e46f0'74b0a0f3'610848c6'8df4d233_u128},
- {Sign::POS, -137, 0xb7a0e9ed'7613acb0'2e0efddf'33a20464_u128},
- {Sign::POS, -137, 0xbfa3d900'8e042ffb'c2cdb3c7'50f127b4_u128},
- {Sign::POS, -137, 0xc7a6e82b'a36a7073'bd953378'6d3f4c49_u128},
- {Sign::POS, -137, 0xcfaa176f'b76c8eb1'82e237c9'a4d450e3_u128},
- {Sign::POS, -137, 0xd7ad66cd'cb3cbe14'c00b46a4'd0e3dfd0_u128},
- {Sign::POS, -137, 0xdfb0d646'e0194584'ea999c0d'f8546710_u128},
- {Sign::POS, -137, 0xe7b465db'f74c8032'cec6c2a9'ad974f4f_u128},
- {Sign::POS, -137, 0xefb8158e'122cde5a'2d2045da'1570a07c_u128},
- {Sign::POS, -137, 0xf7bbe55e'321ce603'6752e9b2'381e3edc_u128},
- {Sign::POS, -137, 0xffbfd54d'588b33c5'3c1ed527'28e00e40_u128},
- {Sign::POS, -136, 0x83e1f2ae'43793dc3'493b0d87'3fb9a340_u128},
- {Sign::POS, -136, 0x87e40ac6'5f6cc4a0'29e38750'c9d26893_u128},
- {Sign::POS, -136, 0x8be632ef'80e9a0df'aab9e832'7258ac3f_u128},
- {Sign::POS, -136, 0x8fe86b2a'28bf51b3'28bc403d'8a5f3c63_u128},
- {Sign::POS, -136, 0x93eab376'd7c36377'f720c1c9'7227fcdc_u128},
- {Sign::POS, -136, 0x97ed0bd6'0ed17018'6ad9a3e3'd11b66c1_u128},
- {Sign::POS, -136, 0x9bef7448'4ecb1f6c'edb27b79'c90b4019_u128},
- {Sign::POS, -136, 0x9fb1c4cd'27012e19'a092a0d7'ab21722a_u128},
- {Sign::POS, -136, 0xa3b44c65'b71c2d85'535d52f0'939a4d02_u128},
- {Sign::POS, -136, 0xa7b6e412'cadcb3dc'90a57e11'edc1864e_u128},
- {Sign::POS, -136, 0xabb98bd4'e33c4381'68e9c901'60031159_u128},
- {Sign::POS, -136, 0xafbc43ac'813a6ea3'bf60594f'929adeb8_u128},
- {Sign::POS, -136, 0xb3bf0b9a'25dcd7a2'8a421588'86775205_u128},
- {Sign::POS, -136, 0xb7c1e39e'522f316d'1ab45417'663dee9e_u128},
- {Sign::POS, -136, 0xbbc4cbb9'87433fe4'6c51ae3c'e1aea68a_u128},
- {Sign::POS, -136, 0xbfc7c3ec'4630d83c'7c52ae8b'40ebabb7_u128},
- {Sign::POS, -136, 0xc3cacc37'1015e15d'a857126f'7cfaaa67_u128},
- {Sign::POS, -136, 0xc7cde49a'66165446'14d05662'cd29464a_u128},
- {Sign::POS, -136, 0xcb90da16'44d29bb7'8379db06'ef3cd6bb_u128},
- {Sign::POS, -136, 0xcf9411aa'99ddb7de'9025f4c6'7dd38bb6_u128},
- {Sign::POS, -136, 0xd3975958'f681086d'd6f8a61c'892032ee_u128},
- {Sign::POS, -136, 0xd79ab121'dbf8714c'9a2f20b4'e2332d47_u128},
- {Sign::POS, -136, 0xdb9e1905'cb85ea59'3c767d61'f51d375b_u128},
- {Sign::POS, -136, 0xdfa19105'46717fca'd4b2bd65'bb25493c_u128},
- {Sign::POS, -136, 0xe3a51920'ce095292'c96c1254'a30ef91f_u128},
- {Sign::POS, -136, 0xe7a8b158'e3a198be'73e324ce'0946b214_u128},
- {Sign::POS, -136, 0xebac59ae'08949dd8'cacd125a'12bac62c_u128},
- {Sign::POS, -136, 0xef6fd620'b2b7a503'cafdc272'27b71eaa_u128},
- {Sign::POS, -136, 0xf3739daf'959aaafc'688d4282'f6026aa3_u128},
- {Sign::POS, -136, 0xf777755d'03f4e0b6'e54e9e38'04464cdd_u128},
- {Sign::POS, -136, 0xfb7b5d29'7f388a12'cb78b383'f4b59dce_u128},
- {Sign::POS, -136, 0xff7f5515'88de024f'ee055fc5'15062c04_u128},
- {Sign::POS, -135, 0x81c1ae90'd131de38'207812b4'3382acdd_u128},
- {Sign::POS, -135, 0x83c3baa7'26a721cc'dc90c4c4'b61f3a87_u128},
- {Sign::POS, -135, 0x85c5cece'05941dbc'1a03f13f'b2c978b1_u128},
- {Sign::POS, -135, 0x87c7eb05'aec1304f'b36f282e'83a7dc36_u128},
- {Sign::POS, -135, 0x89a9eccd'56a980c0'd82a4661'6d4c393f_u128},
- {Sign::POS, -135, 0x8bac18a6'40185360'bc6ff847'13c9babd_u128},
- {Sign::POS, -135, 0x8dae4c90'b22574f4'9f7942a5'16fc2d8a_u128},
- {Sign::POS, -135, 0x8fb0888c'eda546ab'15e50cfd'9b29b427_u128},
- {Sign::POS, -135, 0x91b2cc9b'336f3718'9f465296'ae7dd49a_u128},
- {Sign::POS, -135, 0x93b518bb'c45dc268'b49c1eb9'b348e6e4_u128},
- {Sign::POS, -135, 0x95b76cee'e14e728e'daa320cd'64c9d9c7_u128},
- {Sign::POS, -135, 0x9799a333'de49b963'75a91950'ffe1e3b5_u128},
- {Sign::POS, -135, 0x999c070b'a32068cd'5c6abcbf'43f03f14_u128},
- {Sign::POS, -135, 0x9b9e72f6'b295ad4f'5a9e7f26'5d1ed157_u128},
- {Sign::POS, -135, 0x9da0e6f5'4d9318fd'efeb98d0'2a195c17_u128},
- {Sign::POS, -135, 0x9fa36307'b5054ca8'2aa503a3'110ab5a7_u128},
- {Sign::POS, -135, 0xa1a5e72e'29dbf808'd0fe7e05'869eb825_u128},
- {Sign::POS, -135, 0xa3884a68'a750cb10'e80a28f4'e1e500d2_u128},
- {Sign::POS, -135, 0xa58ade36'aeef9f0b'53106415'1ca6e30b_u128},
- {Sign::POS, -135, 0xa78d7a19'82c4b08f'27c01ffa'8e2e3c4b_u128},
- {Sign::POS, -135, 0xa9901e11'63cbbbf5'7ba9408d'c857d568_u128},
- {Sign::POS, -135, 0xab92ca1e'93038d76'104d1e33'31d3b4fa_u128},
- {Sign::POS, -135, 0xad957e41'516e0158'9343c846'fcdf9137_u128},
- {Sign::POS, -135, 0xaf780e79'b2514889'3977e89a'ec59bfa2_u128},
- {Sign::POS, -135, 0xb17ad246'ef3713bc'913d4e3d'c55c3e6e_u128},
- {Sign::POS, -135, 0xb37d9e2a'7a56b09d'777b52a9'e70d8bcc_u128},
- {Sign::POS, -135, 0xb5807224'94be0c91'55de916f'd30591de_u128},
- {Sign::POS, -135, 0xb7834e35'7f7e2600'e79cfb37'be2861e4_u128},
- {Sign::POS, -135, 0xb986325d'7bab0c89'90983104'd3805389_u128},
- {Sign::POS, -135, 0xbb68ef9c'254aa378'59e3b2ec'71ce64f4_u128},
- {Sign::POS, -135, 0xbd6be371'8c77636f'e83183bf'3dd612ef_u128},
- {Sign::POS, -135, 0xbf6edf5e'c44d9d35'c4e3b0ac'2fd52b7f_u128},
-};
-
-// Logarithm range reduction - Step 3:
-// s(k) = 2^-21 round( 2^21 / (1 + k*2^-21) ) - 1 for k = -69 .. 69
-// Output range:
-// [-0x1.012bb800000800114p-22, 0x1p-22 ]
-constexpr double S3[139] = {
- 0x1.14p-15, 0x1.1p-15, 0x1.0cp-15, 0x1.08p-15, 0x1.04p-15, 0x1p-15,
- 0x1.f8p-16, 0x1.fp-16, 0x1.e8p-16, 0x1.ep-16, 0x1.d8p-16, 0x1.dp-16,
- 0x1.c8p-16, 0x1.cp-16, 0x1.b8p-16, 0x1.bp-16, 0x1.a8p-16, 0x1.ap-16,
- 0x1.98p-16, 0x1.9p-16, 0x1.88p-16, 0x1.8p-16, 0x1.78p-16, 0x1.7p-16,
- 0x1.68p-16, 0x1.6p-16, 0x1.58p-16, 0x1.5p-16, 0x1.48p-16, 0x1.4p-16,
- 0x1.38p-16, 0x1.3p-16, 0x1.28p-16, 0x1.2p-16, 0x1.18p-16, 0x1.1p-16,
- 0x1.08p-16, 0x1p-16, 0x1.fp-17, 0x1.ep-17, 0x1.dp-17, 0x1.cp-17,
- 0x1.bp-17, 0x1.ap-17, 0x1.9p-17, 0x1.8p-17, 0x1.7p-17, 0x1.6p-17,
- 0x1.5p-17, 0x1.4p-17, 0x1.3p-17, 0x1.2p-17, 0x1.1p-17, 0x1p-17,
- 0x1.ep-18, 0x1.cp-18, 0x1.ap-18, 0x1.8p-18, 0x1.6p-18, 0x1.4p-18,
- 0x1.2p-18, 0x1p-18, 0x1.cp-19, 0x1.8p-19, 0x1.4p-19, 0x1p-19,
- 0x1.8p-20, 0x1p-20, 0x1p-21, 0.0, -0x1p-21, -0x1p-20,
- -0x1.8p-20, -0x1p-19, -0x1.4p-19, -0x1.8p-19, -0x1.cp-19, -0x1p-18,
- -0x1.2p-18, -0x1.4p-18, -0x1.6p-18, -0x1.8p-18, -0x1.ap-18, -0x1.cp-18,
- -0x1.ep-18, -0x1p-17, -0x1.1p-17, -0x1.2p-17, -0x1.3p-17, -0x1.4p-17,
- -0x1.5p-17, -0x1.6p-17, -0x1.7p-17, -0x1.8p-17, -0x1.9p-17, -0x1.ap-17,
- -0x1.bp-17, -0x1.cp-17, -0x1.dp-17, -0x1.ep-17, -0x1.fp-17, -0x1p-16,
- -0x1.08p-16, -0x1.1p-16, -0x1.18p-16, -0x1.2p-16, -0x1.28p-16, -0x1.3p-16,
- -0x1.38p-16, -0x1.4p-16, -0x1.48p-16, -0x1.5p-16, -0x1.58p-16, -0x1.6p-16,
- -0x1.68p-16, -0x1.7p-16, -0x1.78p-16, -0x1.8p-16, -0x1.88p-16, -0x1.9p-16,
- -0x1.98p-16, -0x1.ap-16, -0x1.a8p-16, -0x1.bp-16, -0x1.b8p-16, -0x1.cp-16,
- -0x1.c8p-16, -0x1.dp-16, -0x1.d8p-16, -0x1.ep-16, -0x1.e8p-16, -0x1.fp-16,
- -0x1.f8p-16, -0x1p-15, -0x1.04p-15, -0x1.08p-15, -0x1.0cp-15, -0x1.1p-15,
- -0x1.14p-15,
-};
-
-// -log(r) for the third step, generated by SageMath with:
-//
-// for i in range(-69, 70):
-// r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
-// s, m, e = RealField(128)(r).log().sign_mantissa_exponent();
-// print("{Sign::POS," if (s == -1) else "{Sign::NEG,", e, ",
-// format_hex(m), "},");
-constexpr Float128 LOG_R3[139] = {
- {Sign::NEG, -142, 0x89ff6b38'd5de2622'e39d3faf'42340ed7_u128},
- {Sign::NEG, -142, 0x87ff6f80'ccb40f16'7ff33266'82c02485_u128},
- {Sign::NEG, -142, 0x85ff73b8'c3cdf731'5caf4fbe'343cf928_u128},
- {Sign::NEG, -142, 0x83ff77e0'bb2ade79'cdb6e554'348f7fe8_u128},
- {Sign::NEG, -142, 0x81ff7bf8'b2c9c4f6'0ef009c2'457de25d_u128},
- {Sign::NEG, -143, 0xffff0001'55535558'8883333c'57b57c74_u128},
- {Sign::NEG, -143, 0xfbff07f1'45931f44'f32668f3'9c70d183_u128},
- {Sign::NEG, -143, 0xf7ff0fc1'3650e7bd'459a73c6'a6486fe3_u128},
- {Sign::NEG, -143, 0xf3ff1771'278aaecd'37b18cca'7dd3a29f_u128},
- {Sign::NEG, -143, 0xefff1f01'193e7480'513f610d'21bcfc78_u128},
- {Sign::NEG, -143, 0xebff2671'0b6a38e1'ea190b95'c0690b7b_u128},
- {Sign::NEG, -143, 0xe7ff2dc0'fe0bfbfd'2a150f64'f0ad1743_u128},
- {Sign::NEG, -143, 0xe3ff34f0'f121bddd'090b5174'e995e9d1_u128},
- {Sign::NEG, -143, 0xdfff3c00'e4a97e8c'4ed512b9'b93ea2bf_u128},
- {Sign::NEG, -143, 0xdbff42f0'd8a13e15'934cea21'7ab794a2_u128},
- {Sign::NEG, -143, 0xd7ff49c0'cd06fc83'3e4ebe94'8afd2c76_u128},
- {Sign::NEG, -143, 0xd3ff5070'c1d8b9df'87b7c0f5'bcfee2e1_u128},
- {Sign::NEG, -143, 0xcfff5700'b7147634'77666622'8cb6371b_u128},
- {Sign::NEG, -143, 0xcbff5d70'acb8318b'e53a60f3'514db358_u128},
- {Sign::NEG, -143, 0xc7ff63c0'a2c1ebef'79149c3b'6e57fa86_u128},
- {Sign::NEG, -143, 0xc3ff69f0'992fa568'aad734c9'8416df2a_u128},
- {Sign::NEG, -143, 0xbfff7000'8fff5e00'c2657367'9ed28334_u128},
- {Sign::NEG, -143, 0xbbff75f0'872f15c0'd7a3c6db'6540809f_u128},
- {Sign::NEG, -143, 0xb7ff7bc0'7ebcccb1'd277bde6'45fb1aad_u128},
- {Sign::NEG, -143, 0xb3ff8170'76a682dc'6ac80145'a4087793_u128},
- {Sign::NEG, -143, 0xafff8700'6eea3849'287c4db3'0271e265_u128},
- {Sign::NEG, -143, 0xabff8c70'6785ed00'637d6de4'2eeb151e_u128},
- {Sign::NEG, -143, 0xa7ff91c0'6077a10a'43b5348b'6b898a8c_u128},
- {Sign::NEG, -143, 0xa3ff96f0'59bd546e'c10e7657'978bd7f6_u128},
- {Sign::NEG, -143, 0x9fff9c00'53550735'a37503f4'57310e59_u128},
- {Sign::NEG, -143, 0x9bffa0f0'4d3cb966'82d5a40a'3aa022ff_u128},
- {Sign::NEG, -143, 0x97ffa5c0'47726b08'c71e0d3e'e3df5f4d_u128},
- {Sign::NEG, -143, 0x93ffaa70'41f41c23'a83ce035'2bdbd79b_u128},
- {Sign::NEG, -143, 0x8fffaf00'3cbfccbe'2e21a18d'4680e8e4_u128},
- {Sign::NEG, -143, 0x8bffb370'37d37cdf'30bcb3e4'e5dfbd28_u128},
- {Sign::NEG, -143, 0x87ffb7c0'332d2c8d'57ff51d7'5c66d64a_u128},
- {Sign::NEG, -143, 0x83ffbbf0'2ecadbcf'1bdb87fd'be299f43_u128},
- {Sign::NEG, -144, 0xffff8000'55551555'88885dde'02700703_u128},
- {Sign::NEG, -144, 0xf7ff87e0'4d94724c'd259ca80'3a0c1870_u128},
- {Sign::NEG, -144, 0xefff8f80'464fce8f'e5141308'51c7070a_u128},
- {Sign::NEG, -144, 0xe7ff96e0'3f832a2a'30a16898'f3073a64_u128},
- {Sign::NEG, -144, 0xdfff9e00'392a8526'c4ed6451'7b2949ce_u128},
- {Sign::NEG, -144, 0xd7ffa4e0'3341df90'51e4fb4e'32cf6350_u128},
- {Sign::NEG, -144, 0xcfffab80'2dc53971'277672a8'8350bcce_u128},
- {Sign::NEG, -144, 0xc7ffb1e0'28b092d3'35915377'2a490f06_u128},
- {Sign::NEG, -144, 0xbfffb800'23ffebc0'0c265ece'6b481a0e_u128},
- {Sign::NEG, -144, 0xb7ffbde0'1faf4440'db2781c0'3fa132f6_u128},
- {Sign::NEG, -144, 0xafffc380'1bba9c5e'7287c95c'845ada33_u128},
- {Sign::NEG, -144, 0xa7ffc8e0'181df421'423b56b1'263e5a77_u128},
- {Sign::NEG, -144, 0x9fffce00'14d54b91'5a3752ca'4c076fa3_u128},
- {Sign::NEG, -144, 0x97ffd2e0'11dca2b6'6a71e2b2'7eb3f573_u128},
- {Sign::NEG, -144, 0x8fffd780'0f2ff997'c2e21b72'cff39d8f_u128},
- {Sign::NEG, -144, 0x87ffdbe0'0ccb503c'537ff612'feb7ac9e_u128},
- {Sign::NEG, -145, 0xffffc000'15554d55'58888733'33c57c18_u128},
- {Sign::NEG, -145, 0xefffc7c0'1193f9d1'fa514218'42311c42_u128},
- {Sign::NEG, -145, 0xdfffcf00'0e4aa5fa'2c4ed6de'475b942c_u128},
- {Sign::NEG, -145, 0xcfffd5c0'0b7151d8'ce77678c'bb6fcb88_u128},
- {Sign::NEG, -145, 0xbfffdc00'08fffd78'00c26629'a679ed3b_u128},
- {Sign::NEG, -145, 0xafffe1c0'06eea8e1'23287cb9'd3072728_u128},
- {Sign::NEG, -145, 0x9fffe700'0535541c'd5a37540'fd057315_u128},
- {Sign::NEG, -145, 0x8fffebc0'03cbff32'f82e21c1'fce36810_u128},
- {Sign::NEG, -146, 0xffffe000'05555455'5588887d'dde02702_u128},
- {Sign::NEG, -146, 0xdfffe780'0392aa14'9ac4ed72'adf5b295_u128},
- {Sign::NEG, -146, 0xbfffee00'023fffaf'000c2664'8066b482_u128},
- {Sign::NEG, -146, 0x9ffff380'014d552e'455a3754'b292c077_u128},
- {Sign::NEG, -147, 0xfffff000'01555535'55588888'33333c58_u128},
- {Sign::NEG, -147, 0xbffff700'008ffff5'e000c266'5736679f_u128},
- {Sign::NEG, -148, 0xfffff800'00555551'55558888'85ddde02_u128},
- {Sign::NEG, -149, 0xfffffc00'00155554'd5555888'88733334_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -148, 0x80000200'000aaaaa'eaaaac44'444eeeef_u128},
- {Sign::POS, -147, 0x80000400'002aaaac'aaaac444'459999ac_u128},
- {Sign::POS, -147, 0xc0000900'0090000a'2000c266'7596679f_u128},
- {Sign::POS, -146, 0x80000800'00aaaaba'aaac4444'6eeef381_u128},
- {Sign::POS, -146, 0xa0000c80'014d557c'655a3755'f81815cc_u128},
- {Sign::POS, -146, 0xc0001200'02400051'000c2668'4c66b482_u128},
- {Sign::POS, -146, 0xe0001880'0392ab40'bac4ed7c'40fb07eb_u128},
- {Sign::POS, -145, 0x80001000'02aaab2a'aac44449'999abe2c_u128},
- {Sign::POS, -145, 0x90001440'03cc00cd'082e21d7'9cbb6812_u128},
- {Sign::POS, -145, 0xa0001900'0535568d'd5a37569'adb01dc3_u128},
- {Sign::POS, -145, 0xb0001e40'06eeac74'33287d01'e8c9d1d9_u128},
- {Sign::POS, -145, 0xc0002400'09000288'00c266a3'2679ed48_u128},
- {Sign::POS, -145, 0xd0002a40'0b7158d1'de776851'22b2764b_u128},
- {Sign::POS, -145, 0xe0003100'0e4aaf5b'2c4ed810'a8063f03_u128},
- {Sign::POS, -145, 0xf0003840'1194062e'0a5143e7'be891c8f_u128},
- {Sign::POS, -144, 0x80002000'0aaaaeaa'ac4444ee'ef3813a1_u128},
- {Sign::POS, -144, 0x88002420'0ccb5a6e'5b7ff7fe'1339025b_u128},
- {Sign::POS, -144, 0x90002880'0f300668'42e21e26'caf39e33_u128},
- {Sign::POS, -144, 0x98002d20'11dcb29e'f271e66f'a5554bc6_u128},
- {Sign::POS, -144, 0xa0003200'14d55f19'5a3757e0'615cc676_u128},
- {Sign::POS, -144, 0xa8003720'181e0bde'ca3b5d82'10ca5cab_u128},
- {Sign::POS, -144, 0xb0003c80'1bbab8f6'f287d25f'3cb032bb_u128},
- {Sign::POS, -144, 0xb8004220'1faf6669'e3278d84'0be28cdb_u128},
- {Sign::POS, -144, 0xc0004800'24001440'0c266dfe'6b482076_u128},
- {Sign::POS, -144, 0xc8004e20'28b0c282'3d9166de'380a6d3d_u128},
- {Sign::POS, -144, 0xd0005480'2dc57139'a7768b35'6ba61e4b_u128},
- {Sign::POS, -144, 0xd8005b20'3342206f'd9e51a18'49db73c1_u128},
- {Sign::POS, -144, 0xe0006200'392ad02e'c4ed8a9d'907eb521_u128},
- {Sign::POS, -144, 0xe8006920'3f838080'b8a197de'a928acd7_u128},
- {Sign::POS, -144, 0xf0007080'46503170'65144cf7'dcc72d3b_u128},
- {Sign::POS, -144, 0xf8007820'4d94e308'da5a1108'890d9f6a_u128},
- {Sign::POS, -143, 0x80004000'2aaacaaa'c4445999'abe2ce2c_u128},
- {Sign::POS, -143, 0x84004410'2ecb2431'1fdbbb4f'3bffc832_u128},
- {Sign::POS, -143, 0x88004840'332d7e1d'97ff8f39'ec91b4ee_u128},
- {Sign::POS, -143, 0x8c004c90'37d3d876'74bcfcf0'b3f0a95d_u128},
- {Sign::POS, -143, 0x90005100'3cc03342'2e21f80c'a6813aff_u128},
- {Sign::POS, -143, 0x94005590'41f48e87'6c3d4629'170ce87f_u128},
- {Sign::POS, -143, 0x98005a40'4772ea4d'071e84e3'b80a8881_u128},
- {Sign::POS, -143, 0x9c005f10'4d3d469a'06d62fdc'bdd6bec3_u128},
- {Sign::POS, -143, 0xa0006400'5355a375'a375a6b7'01dc77c0_u128},
- {Sign::POS, -143, 0xa4006910'59be00e7'450f3318'26ad6b05_u128},
- {Sign::POS, -143, 0xa8006e40'60785ef6'83b60ea8'bd0aa459_u128},
- {Sign::POS, -143, 0xac007390'6786bdab'277e6914'69dd13f5_u128},
- {Sign::POS, -143, 0xb0007900'6eeb1d0d'287d6e0a'0d1e25eb_u128},
- {Sign::POS, -143, 0xb4007e90'76a77d24'aec94b3b'e9b060f5_u128},
- {Sign::POS, -143, 0xb8008440'7ebdddfa'1279365f'ce280cce_u128},
- {Sign::POS, -143, 0xbc008a10'87303f95'dba5732f'3e83e04a_u128},
- {Sign::POS, -143, 0xc0009000'9000a200'c2675967'9ed5b754_u128},
- {Sign::POS, -143, 0xc4009610'99310543'aed95aca'5edb5109_u128},
- {Sign::POS, -143, 0xc8009c40'a2c36967'b917091d'2687160f_u128},
- {Sign::POS, -143, 0xcc00a290'acb9ce76'293d1c2a'0378e75d_u128},
- {Sign::POS, -143, 0xd000a900'b7163478'776977bf'9766f5a7_u128},
- {Sign::POS, -143, 0xd400af90'c1da9b78'4bbb31b1'4776a18b_u128},
- {Sign::POS, -143, 0xd800b640'cd09037f'7e5297d7'6c8564ba_u128},
- {Sign::POS, -143, 0xdc00bd10'd8a36c98'1751360f'8461c447_u128},
- {Sign::POS, -143, 0xe000c400'e4abd6cc'4ed9dc3c'63f44c41_u128},
- {Sign::POS, -143, 0xe400cb10'f1244226'8d10a446'6a5894d5_u128},
- {Sign::POS, -143, 0xe800d240'fe0eaeb1'6a1af81b'b4e6510e_u128},
- {Sign::POS, -143, 0xec00d991'0b6d1c77'ae1f97b0'542a677a_u128},
- {Sign::POS, -143, 0xf000e101'19418b84'51469efe'81d014cc_u128},
- {Sign::POS, -143, 0xf400e891'278dfbe2'7bb98c06'd77a18b4_u128},
- {Sign::POS, -143, 0xf800f041'36546d9d'85a344d0'868bed17_u128},
- {Sign::POS, -143, 0xfc00f811'4596e0c0'f7301d69'90e307cc_u128},
- {Sign::POS, -142, 0x80008000'aaabaaac'4446eef3'8140138f_u128},
- {Sign::POS, -142, 0x82008408'b2cbe5b8'10f5e432'96105497_u128},
- {Sign::POS, -142, 0x84008820'bb2d2189'edbd4f83'ef63f730_u128},
- {Sign::POS, -142, 0x86008c48'c3d05e27'feb654fd'541c638e_u128},
- {Sign::POS, -142, 0x88009080'ccb69b98'7ffadeb8'882f7674_u128},
- {Sign::POS, -142, 0x8a0094c8'd5e0d9e1'c5a59fd3'6bd44397_u128},
-};
-
-// Minimax polynomial generated by Sollya with:
-// > P = fpminimax((log(1 + x) - x)/x^2, 3, [|1, 128...|],
-// [-0x1.01928p-22 , 0x1p-22]);
-// > P;
-// > dirtyinfnorm(log(1 + x)/x - 1 - x*P, [-0x1.01928p-22 , 0x1p-22]);
-// 0x1.ce1e...p-116
-constexpr Float128 BIG_COEFFS[4]{
- {Sign::POS, -130, 0xccccccd7'4818e397'7ed78465'd460315b_u128},
- {Sign::NEG, -129, 0x80000000'000478b0'c6388a23'871ce156_u128},
- {Sign::POS, -129, 0xaaaaaaaa'aaaaaaaa'aa807bd8'67763262_u128},
- {Sign::NEG, -128, 0x80000000'00000000'00000000'00000000_u128},
-};
-
-[[maybe_unused]] LIBC_INLINE double log1p_accurate(int e_x, int index,
- fputil::DoubleDouble m_x) {
- Float128 e_x_f128(static_cast<float>(e_x));
- Float128 sum = fputil::quick_mul(LOG_2, e_x_f128);
- sum = fputil::quick_add(sum, LOG_R1[index]);
-
- // fputil::DoubleDouble v4;
- Float128 v = fputil::quick_add(Float128(m_x.hi), Float128(m_x.lo));
-
- // Skip 2nd range reduction step if |m_x| <= 2^-15.
- if (m_x.hi > 0x1p-15 || m_x.hi < -0x1p-15) {
- // Range reduction - Step 2.
- // For k such that: k * 2^-14 - 2^-15 <= m_x.hi < k * 2^-14 + 2^-15,
- // Let s_k = 2^-18 * round( 2^18 / (1 + k*2^-14) ) - 1
- // Then the 2nd reduced argument is:
- // (1 + s_k) * (1 + m_x) - 1 =
- // = s_k + m_x + s_k * m_x
- // Output range:
- // -0x1.1037c00000040271p-15 <= v2.hi + v2.lo <= 0x1.108480000008096cp-15
- int idx2 = static_cast<int>(0x1p14 * (m_x.hi + (91 * 0x1p-14 + 0x1p-15)));
- sum = fputil::quick_add(sum, LOG_R2[idx2]);
- Float128 s2 = Float128(S2[idx2]);
- v = fputil::quick_add(fputil::quick_add(v, s2), fputil::quick_mul(v, s2));
- }
-
- // Skip 3rd range reduction step if |v| <= 2^-22.
- if (v.exponent > -150) {
- // Range reduction - Step 3.
- // For k such that: k * 2^-21 - 2^-22 <= v2.hi < k * 2^-21 + 2^-22,
- // Let s_k = 2^-21 * round( 2^21 / (1 + k*2^-21) ) - 1
- // Then the 3rd reduced argument is:
- // v3.hi + v3.lo ~ (1 + s_k) * (1 + v2.hi + v2.lo) - 1
- // Output range:
- // -0x1.012bb800000800114p-22 <= v3.hi + v3.lo <= 0x1p-22
- int idx3 =
- static_cast<int>(0x1p21 * (double(v) + (69 * 0x1p-21 + 0x1p-22)));
- sum = fputil::quick_add(sum, LOG_R3[idx3]);
- Float128 s3 = Float128(S3[idx3]);
- v = fputil::quick_add(fputil::quick_add(v, s3), fputil::quick_mul(v, s3));
- }
-
- // Polynomial approximation
- Float128 p = fputil::quick_mul(v, BIG_COEFFS[0]);
- p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[1]));
- p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[2]));
- p = fputil::quick_mul(v, fputil::quick_add(p, BIG_COEFFS[3]));
- p = fputil::quick_add(v, fputil::quick_mul(v, p));
-
- Float128 r = fputil::quick_add(sum, p);
-
- return static_cast<double>(r);
-}
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-} // namespace
-
-LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
- using FPBits_t = typename fputil::FPBits<double>;
-
- constexpr int EXP_BIAS = FPBits_t::EXP_BIAS;
- constexpr int FRACTION_LEN = FPBits_t::FRACTION_LEN;
- FPBits_t xbits(x);
- uint64_t x_u = xbits.uintval();
-
- fputil::DoubleDouble x_dd{0.0, 0.0};
-
- uint16_t x_exp = xbits.get_biased_exponent();
-
- if (x_exp >= EXP_BIAS) {
- // |x| >= 1
- if (LIBC_UNLIKELY(x_u >= 0x4650'0000'0000'0000ULL)) {
- // x >= 2^102 or x is negative, inf, or NaN
- if (LIBC_UNLIKELY(x_u > FPBits_t::max_normal().uintval())) {
- // x <= -1.0 or x is Inf or NaN
- if (x_u == 0xbff0'0000'0000'0000ULL) {
- // x = -1.0
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits_t::inf(Sign::NEG).get_val();
- }
- if (xbits.is_neg() && !xbits.is_nan()) {
- // x < -1.0
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
- // x is +Inf or NaN
- if (xbits.is_inf() && xbits.is_pos())
- return x;
-
- if (xbits.is_signaling_nan())
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
- x_dd.hi = x;
- } else {
- x_dd = fputil::exact_add(x, 1.0);
- }
- } else {
- // |x| < 1
- if (LIBC_UNLIKELY(xbits.get_biased_exponent() <
- EXP_BIAS - FRACTION_LEN - 1)) {
- // Quick return when |x| < 2^-53.
- // Since log(1 + x) = x - x^2/2 + x^3/3 - ...,
- // for |x| < 2^-53,
- // x > log(1 + x) > x - x^2 > x(1 - 2^-54) > x - ulp(x)/2
- // Thus,
- // log(1 + x) = nextafter(x, -inf) for FE_DOWNWARD, or
- // FE_TOWARDZERO and x > 0,
- // = x otherwise.
- if (x + x == 0.0)
- return x + x; // Handle FTZ/DAZ correctly.
-
- volatile float tp = 1.0f;
- volatile float tn = -1.0f;
- bool rdp = (tp - 0x1p-25f != tp);
- bool rdn = (tn - 0x1p-24f != tn);
-
- if (x > 0 && rdp) {
- return FPBits_t(x_u - 1).get_val();
- }
-
- if (x < 0 && rdn) {
- return FPBits_t(x_u + 1).get_val();
- }
-
- return x;
- }
- x_dd = fputil::exact_add(1.0, x);
- }
-
- // At this point, x_dd is the exact sum of 1 + x:
- // x_dd.hi + x_dd.lo = x + 1.0 exactly.
- // |x_dd.hi| >= 2^-54
- // |x_dd.lo| < ulp(x_dd.hi)
-
- FPBits_t xhi_bits(x_dd.hi);
- uint64_t xhi_frac = xhi_bits.get_mantissa();
- x_u = xhi_bits.uintval();
- // Range reduction:
- // Find k such that |x_hi - k * 2^-7| <= 2^-8.
- int idx = static_cast<int>((xhi_frac + (1ULL << (FRACTION_LEN - 8))) >>
- (FRACTION_LEN - 7));
- int x_e = xhi_bits.get_exponent() + (idx >> 7);
- double e_x = static_cast<double>(x_e);
-
- // hi is exact
- // ulp(hi) = ulp(LOG_2_HI) = ulp(LOG_R1_DD[idx].hi) = 2^-43
- double hi = fputil::multiply_add(e_x, LOG_2_HI, LOG_R1_DD[idx].hi);
- // lo errors < |e_x| * ulp(LOG_2_LO) + ulp(LOG_R1[idx].lo)
- // <= 2^11 * 2^(-43-53) = 2^-85
- double lo = fputil::multiply_add(e_x, LOG_2_LO, LOG_R1_DD[idx].lo);
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Error bound of e_x * log(2) - log(r1)
- constexpr double ERR_HI[2] = {0x1.0p-85, 0.0};
- double err_hi = ERR_HI[hi == 0.0];
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // Scale x_dd by 2^(-xh_bits.get_exponent()).
- int64_t s_u = static_cast<int64_t>(x_u & FPBits_t::EXP_MASK) -
- (static_cast<int64_t>(EXP_BIAS) << FRACTION_LEN);
- // Normalize arguments:
- // 1 <= m_dd.hi < 2
- // |m_dd.lo| < 2^-52.
- // This is exact.
- uint64_t m_hi = FPBits_t::one().uintval() | xhi_frac;
-
- uint64_t m_lo =
- FPBits_t(x_dd.lo).abs().get_val() > x_dd.hi * 0x1.0p-127
- ? static_cast<uint64_t>(cpp::bit_cast<int64_t>(x_dd.lo) - s_u)
- : 0;
-
- fputil::DoubleDouble m_dd{FPBits_t(m_lo).get_val(), FPBits_t(m_hi).get_val()};
-
- // Perform range reduction:
- // r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1
- // = (r * m_dd.hi - 1) + r * m_dd.lo
- // = v_hi + (v_lo.hi + v_lo.lo)
- // where:
- // v_hi = r * m_dd.hi - 1 (exact)
- // v_lo.hi + v_lo.lo = r * m_dd.lo (exact)
- // Bounds on the values:
- // -0x1.69000000000edp-8 < r * m - 1 < 0x1.7f00000000081p-8
- // |v_lo.hi| <= |r| * |m_dd.lo| < 2^-52
- // |v_lo.lo| < ulp(v_lo.hi) <= 2^(-52 - 53) = 2^(-105)
- double r = R1[idx];
- double v_hi;
- fputil::DoubleDouble v_lo = fputil::exact_mult(m_dd.lo, r);
-
- // Perform exact range reduction
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- v_hi = fputil::multiply_add(r, m_dd.hi, -1.0); // Exact.
-#else
- // c = 1 + idx * 2^-7.
- double c = FPBits_t((static_cast<uint64_t>(idx) << (FRACTION_LEN - 7)) +
- uint64_t(0x3FF0'0000'0000'0000ULL))
- .get_val();
- v_hi = fputil::multiply_add(r, m_dd.hi - c, RCM1[idx]); // Exact
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- // Range reduction output:
- // -0x1.69000000000edp-8 < v_hi + v_lo < 0x1.7f00000000081p-8
- // |v_dd.lo| < ulp(v_dd.hi) <= 2^(-7 - 53) = 2^-60
- fputil::DoubleDouble v_dd = fputil::exact_add(v_hi, v_lo.hi);
- v_dd.lo += v_lo.lo;
-
- // Exact sum:
- // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
- fputil::DoubleDouble r1 = fputil::exact_add(hi, v_dd.hi);
-
- // Overall error is bounded by:
- // C * ulp(v_sq) + err_hi
- double v_sq = v_dd.hi * v_dd.hi;
- double p0 = fputil::multiply_add(v_dd.hi, P_COEFFS[1], P_COEFFS[0]);
- double p1 = fputil::multiply_add(v_dd.hi, P_COEFFS[3], P_COEFFS[2]);
- double p2 = fputil::multiply_add(v_dd.hi, P_COEFFS[5], P_COEFFS[4]);
- double p = fputil::polyeval(v_sq, (v_dd.lo + r1.lo) + lo, p0, p1, p2);
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return r1.hi + p;
-#else
- double err = fputil::multiply_add(v_sq, P_ERR, err_hi);
-
- double left = r1.hi + (p - err);
- double right = r1.hi + (p + err);
-
- // Ziv's test to see if fast pass is accurate enough.
- if (left == right)
- return left;
-
- return log1p_accurate(x_e, idx, v_dd);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-}
+LLVM_LIBC_FUNCTION(double, log1p, (double x)) { return math::log1p(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/log2.cpp b/libc/src/math/generic/log2.cpp
index ae7a658..e292a02 100644
--- a/libc/src/math/generic/log2.cpp
+++ b/libc/src/math/generic/log2.cpp
@@ -7,967 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/log2.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/integer_literals.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-
-#include "src/__support/math/common_constants.h"
-#include "src/__support/math/log_range_reduction.h"
+#include "src/__support/math/log2.h"
namespace LIBC_NAMESPACE_DECL {
-
-// 128-bit precision dyadic floating point numbers.
-using Float128 = typename fputil::DyadicFloat<128>;
-
-using LIBC_NAMESPACE::operator""_u128;
-
-namespace {
-
-using namespace common_constants_internal;
-using namespace math::log_range_reduction_internal;
-
-constexpr fputil::DoubleDouble LOG2_E = {0x1.777d0ffda0d24p-56,
- 0x1.71547652b82fep0};
-
-alignas(16) const fputil::DoubleDouble LOG_R1[128] = {
- {0.0, 0.0},
- {0x1.46662d417cedp-62, 0x1.010157588de71p-7},
- {0x1.27c8e8416e71fp-60, 0x1.0205658935847p-6},
- {-0x1.d192d0619fa67p-60, 0x1.8492528c8cabfp-6},
- {0x1.c05cf1d753622p-59, 0x1.0415d89e74444p-5},
- {-0x1.cdd6f7f4a137ep-59, 0x1.466aed42de3eap-5},
- {0x1.a8be97660a23dp-60, 0x1.894aa149fb343p-5},
- {-0x1.e48fb0500efd4p-59, 0x1.ccb73cdddb2ccp-5},
- {-0x1.dd7009902bf32p-58, 0x1.08598b59e3a07p-4},
- {-0x1.7558367a6acf6p-59, 0x1.1973bd1465567p-4},
- {0x1.7a976d3b5b45fp-59, 0x1.3bdf5a7d1ee64p-4},
- {0x1.f38745c5c450ap-58, 0x1.5e95a4d9791cbp-4},
- {-0x1.72566212cdd05p-61, 0x1.700d30aeac0e1p-4},
- {-0x1.478a85704ccb7p-58, 0x1.9335e5d594989p-4},
- {-0x1.0057eed1ca59fp-59, 0x1.b6ac88dad5b1cp-4},
- {0x1.a38cb559a6706p-58, 0x1.c885801bc4b23p-4},
- {-0x1.a2bf991780d3fp-59, 0x1.ec739830a112p-4},
- {-0x1.ac9f4215f9393p-58, 0x1.fe89139dbd566p-4},
- {-0x1.0e63a5f01c691p-58, 0x1.1178e8227e47cp-3},
- {-0x1.c6ef1d9b2ef7ep-59, 0x1.1aa2b7e23f72ap-3},
- {-0x1.499a3f25af95fp-58, 0x1.2d1610c86813ap-3},
- {0x1.7d411a5b944adp-58, 0x1.365fcb0159016p-3},
- {-0x1.0d5604930f135p-58, 0x1.4913d8333b561p-3},
- {-0x1.71a9682395bfdp-61, 0x1.527e5e4a1b58dp-3},
- {-0x1.d34f0f4621bedp-60, 0x1.6574ebe8c133ap-3},
- {-0x1.8de59c21e166cp-57, 0x1.6f0128b756abcp-3},
- {-0x1.1232ce70be781p-57, 0x1.823c16551a3c2p-3},
- {0x1.55aa8b6997a4p-58, 0x1.8beafeb38fe8cp-3},
- {0x1.142c507fb7a3dp-58, 0x1.95a5adcf7017fp-3},
- {0x1.bcafa9de97203p-57, 0x1.a93ed3c8ad9e3p-3},
- {-0x1.6353ab386a94dp-57, 0x1.b31d8575bce3dp-3},
- {0x1.dd355f6a516d7p-60, 0x1.bd087383bd8adp-3},
- {0x1.60629242471a2p-57, 0x1.d1037f2655e7bp-3},
- {0x1.aa11d49f96cb9p-58, 0x1.db13db0d4894p-3},
- {0x1.2276041f43042p-59, 0x1.e530effe71012p-3},
- {-0x1.08ab2ddc708ap-58, 0x1.ef5ade4dcffe6p-3},
- {0x1.f665066f980a2p-57, 0x1.f991c6cb3b379p-3},
- {0x1.cdb16ed4e9138p-56, 0x1.07138604d5862p-2},
- {0x1.162c79d5d11eep-58, 0x1.0c42d676162e3p-2},
- {-0x1.0e63a5f01c691p-57, 0x1.1178e8227e47cp-2},
- {0x1.66fbd28b40935p-56, 0x1.16b5ccbacfb73p-2},
- {-0x1.12aeb84249223p-57, 0x1.1bf99635a6b95p-2},
- {0x1.e0efadd9db02bp-56, 0x1.269621134db92p-2},
- {-0x1.82dad7fd86088p-56, 0x1.2bef07cdc9354p-2},
- {-0x1.3d69909e5c3dcp-56, 0x1.314f1e1d35ce4p-2},
- {-0x1.324f0e883858ep-58, 0x1.36b6776be1117p-2},
- {-0x1.2ad27e50a8ec6p-56, 0x1.3c25277333184p-2},
- {0x1.0dbb243827392p-57, 0x1.419b423d5e8c7p-2},
- {0x1.8fb4c14c56eefp-60, 0x1.4718dc271c41bp-2},
- {-0x1.123615b147a5dp-58, 0x1.4c9e09e172c3cp-2},
- {-0x1.8f7e9b38a6979p-57, 0x1.522ae0738a3d8p-2},
- {-0x1.0908d15f88b63p-57, 0x1.57bf753c8d1fbp-2},
- {-0x1.6541148cbb8a2p-56, 0x1.5d5bddf595f3p-2},
- {0x1.dc18ce51fff99p-57, 0x1.630030b3aac49p-2},
- {0x1.a64eadd740178p-58, 0x1.68ac83e9c6a14p-2},
- {0x1.657c222d868cdp-58, 0x1.6e60ee6af1972p-2},
- {0x1.84a4ee3059583p-56, 0x1.741d876c67bb1p-2},
- {-0x1.c168817443f22p-56, 0x1.79e26687cfb3ep-2},
- {-0x1.219024acd3b77p-58, 0x1.7fafa3bd8151cp-2},
- {-0x1.486666443b153p-56, 0x1.85855776dcbfbp-2},
- {-0x1.70f2f38238303p-56, 0x1.8b639a88b2df5p-2},
- {-0x1.ad4bb98c1f2c5p-56, 0x1.914a8635bf68ap-2},
- {-0x1.89d2816cf838fp-57, 0x1.973a3431356aep-2},
- {0x1.87bcbcfd3e187p-59, 0x1.9d32bea15ed3bp-2},
- {-0x1.ba8062860ae23p-57, 0x1.a33440224fa79p-2},
- {-0x1.ba8062860ae23p-57, 0x1.a33440224fa79p-2},
- {0x1.bcafa9de97203p-56, 0x1.a93ed3c8ad9e3p-2},
- {0x1.9d56c45dd3e86p-56, 0x1.af5295248cddp-2},
- {0x1.494b610665378p-56, 0x1.b56fa04462909p-2},
- {0x1.6fd02999b21e1p-59, 0x1.bb9611b80e2fbp-2},
- {-0x1.bfc00b8f3feaap-56, 0x1.c1c60693fa39ep-2},
- {-0x1.bfc00b8f3feaap-56, 0x1.c1c60693fa39ep-2},
- {0x1.223eadb651b4ap-57, 0x1.c7ff9c74554c9p-2},
- {0x1.0798270b29f39p-56, 0x1.ce42f18064743p-2},
- {0x1.d7f4d3b3d406bp-56, 0x1.d490246defa6bp-2},
- {-0x1.0b5837185a661p-56, 0x1.dae75484c9616p-2},
- {-0x1.ac81cc8a4dfb8p-56, 0x1.e148a1a2726cep-2},
- {-0x1.ac81cc8a4dfb8p-56, 0x1.e148a1a2726cep-2},
- {0x1.57d646a17bc6ap-56, 0x1.e7b42c3ddad73p-2},
- {-0x1.74b71fb5e57e3p-62, 0x1.ee2a156b413e5p-2},
- {-0x1.0d487f5aba5e5p-57, 0x1.f4aa7ee03192dp-2},
- {-0x1.0d487f5aba5e5p-57, 0x1.f4aa7ee03192dp-2},
- {0x1.7e8f05924d259p-57, 0x1.fb358af7a4884p-2},
- {0x1.1713a36138e19p-57, 0x1.00e5ae5b207abp-1},
- {-0x1.17f9e54e78104p-57, 0x1.04360be7603adp-1},
- {-0x1.17f9e54e78104p-57, 0x1.04360be7603adp-1},
- {0x1.2241edf5fd1f7p-57, 0x1.078bf0533c568p-1},
- {0x1.0d710fcfc4e0dp-55, 0x1.0ae76e2d054fap-1},
- {0x1.0d710fcfc4e0dp-55, 0x1.0ae76e2d054fap-1},
- {0x1.3300f002e836ep-55, 0x1.0e4898611cce1p-1},
- {-0x1.91eee7772c7c2p-55, 0x1.11af823c75aa8p-1},
- {-0x1.91eee7772c7c2p-55, 0x1.11af823c75aa8p-1},
- {0x1.342eb628dba17p-56, 0x1.151c3f6f29612p-1},
- {0x1.89df1568ca0bp-55, 0x1.188ee40f23ca6p-1},
- {0x1.89df1568ca0bp-55, 0x1.188ee40f23ca6p-1},
- {0x1.59bddae1ccce2p-56, 0x1.1c07849ae6007p-1},
- {-0x1.2164ff40e9817p-56, 0x1.1f8635fc61659p-1},
- {-0x1.2164ff40e9817p-56, 0x1.1f8635fc61659p-1},
- {-0x1.fcc8dbccc25cbp-57, 0x1.230b0d8bebc98p-1},
- {0x1.e0efadd9db02bp-55, 0x1.269621134db92p-1},
- {0x1.e0efadd9db02bp-55, 0x1.269621134db92p-1},
- {-0x1.6a0c343be95dcp-56, 0x1.2a2786d0ec107p-1},
- {-0x1.b941ee770436bp-56, 0x1.2dbf557b0df43p-1},
- {-0x1.b941ee770436bp-56, 0x1.2dbf557b0df43p-1},
- {0x1.6c3a5f12642c9p-57, 0x1.315da4434068bp-1},
- {0x1.6c3a5f12642c9p-57, 0x1.315da4434068bp-1},
- {-0x1.f01ab6065515cp-56, 0x1.35028ad9d8c86p-1},
- {0x1.21512aa596ea3p-55, 0x1.38ae2171976e7p-1},
- {0x1.21512aa596ea3p-55, 0x1.38ae2171976e7p-1},
- {0x1.1930603d87b6ep-56, 0x1.3c6080c36bfb5p-1},
- {0x1.1930603d87b6ep-56, 0x1.3c6080c36bfb5p-1},
- {0x1.86cf0f38b461ap-57, 0x1.4019c2125ca93p-1},
- {-0x1.84f481051f71ap-56, 0x1.43d9ff2f923c5p-1},
- {-0x1.84f481051f71ap-56, 0x1.43d9ff2f923c5p-1},
- {0x1.2541aca7d5844p-55, 0x1.47a1527e8a2d3p-1},
- {0x1.2541aca7d5844p-55, 0x1.47a1527e8a2d3p-1},
- {0x1.c457b531506f6p-55, 0x1.4b6fd6f970c1fp-1},
- {0x1.c457b531506f6p-55, 0x1.4b6fd6f970c1fp-1},
- {0x1.d749362382a77p-56, 0x1.4f45a835a4e19p-1},
- {0x1.d749362382a77p-56, 0x1.4f45a835a4e19p-1},
- {0x1.988ba4aea614dp-56, 0x1.5322e26867857p-1},
- {0x1.988ba4aea614dp-56, 0x1.5322e26867857p-1},
- {0x1.80bff3303dd48p-55, 0x1.5707a26bb8c66p-1},
- {0x1.80bff3303dd48p-55, 0x1.5707a26bb8c66p-1},
- {-0x1.6714fbcd8135bp-55, 0x1.5af405c3649ep-1},
- {-0x1.6714fbcd8135bp-55, 0x1.5af405c3649ep-1},
- {0x1.1c066d235ee63p-56, 0x1.5ee82aa24192p-1},
- {0.0, 0.0},
-};
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-// Extra errors from P is from using x^2 to reduce evaluation latency.
-constexpr double P_ERR = 0x1.0p-49;
-
-alignas(16) constexpr LogRR LOG2_TABLE = {
- // -log2(r) with 128-bit precision generated by SageMath with:
- // def format_hex(value):
- // l = hex(value)[2:]
- // n = 8
- // x = [l[i:i + n] for i in range(0, len(l), n)]
- // return "0x" + "'".join(x) + "_u128"
- // for i in range(1, 127):
- // r = 2^-8 * ceil( 2^8 * (1 - 2^(-8)) / (1 + i*2^(-7)) );
- // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
- // print("{Sign::POS,", e, ", format_hex(m), "},");
- /* .step_1 = */ {
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -134, 0xb963dd10'7b993ada'e8c25163'0adb856a_u128},
- {Sign::POS, -133, 0xba1f7430'f9aab1b2'a41b08fb'e05f82d0_u128},
- {Sign::POS, -132, 0x8c25c726'2b57c149'1f06c085'bc1b865d_u128},
- {Sign::POS, -132, 0xbb9ca64e'cac6aaef'2e1c07f0'438ebac0_u128},
- {Sign::POS, -132, 0xeb75e8f8'ff5ff022'aacc0e21'd6541224_u128},
- {Sign::POS, -131, 0x8dd99530'02a4e866'31514aef'39ce6303_u128},
- {Sign::POS, -131, 0xa62b07f3'457c4070'50799bea'aab2940c_u128},
- {Sign::POS, -131, 0xbeb024b6'7dda6339'da288fc6'15a727dc_u128},
- {Sign::POS, -131, 0xcb0657cd'5dbe4f6f'22dbbace'd44516ce_u128},
- {Sign::POS, -131, 0xe3da945b'878e27d0'd939dcee'cdd9ce05_u128},
- {Sign::POS, -131, 0xfce4aee0'e88b2749'9596a8e2'e84c8f45_u128},
- {Sign::POS, -130, 0x84bf1c67'3032495d'243efd93'25954cfe_u128},
- {Sign::POS, -130, 0x916d6e15'59a4b696'91d79938'e7226384_u128},
- {Sign::POS, -130, 0x9e37db28'66f2850b'22563c9e'd9462091_u128},
- {Sign::POS, -130, 0xa4a7c31d'c6f9a5d5'3a53ca11'81015ada_u128},
- {Sign::POS, -130, 0xb19d45fa'1be70855'3eb8023e'ed65d601_u128},
- {Sign::POS, -130, 0xb823018e'3cfc25f0'ce5cabbd'2d753d9b_u128},
- {Sign::POS, -130, 0xc544c055'fde99333'54dbf16f'b0695ee3_u128},
- {Sign::POS, -130, 0xcbe0e589'e3f6042d'5196a85a'067c6739_u128},
- {Sign::POS, -130, 0xd930124b'ea9a2c66'f349845e'48955078_u128},
- {Sign::POS, -130, 0xdfe33d3f'ffa66037'815ef705'cfaef035_u128},
- {Sign::POS, -130, 0xed61169f'220e97f2'2ba704dc'aa76f41d_u128},
- {Sign::POS, -130, 0xf42be9e9'b09b3def'2062f36b'c14d0d93_u128},
- {Sign::POS, -129, 0x80ecdde7'd30ea2ed'13288019'4144b02b_u128},
- {Sign::POS, -129, 0x845e706c'afd1bf61'54880de6'3812fd49_u128},
- {Sign::POS, -129, 0x8b4e029b'1f8ac391'a87c02ea'f36e2c29_u128},
- {Sign::POS, -129, 0x8ecc164e'a93841ae'9804237e'c8d9431d_u128},
- {Sign::POS, -129, 0x924e6958'9e6b6268'20f81ca9'5d9e7968_u128},
- {Sign::POS, -129, 0x995ff71b'8773432d'124bc6f1'acf95dc4_u128},
- {Sign::POS, -129, 0x9cef470a'acfb7bf9'5a5e8e21'bff3336b_u128},
- {Sign::POS, -129, 0xa08300be'1f651473'4e53fa33'29f65894_u128},
- {Sign::POS, -129, 0xa7b7dd96'762cc3c7'2742d729'6a39eed6_u128},
- {Sign::POS, -129, 0xab591735'abc724e4'f359c554'4bc5e134_u128},
- {Sign::POS, -129, 0xaefee78f'75707221'6b6c874d'd96e1d75_u128},
- {Sign::POS, -129, 0xb2a95a4c'c313bb59'21006678'c0a5c390_u128},
- {Sign::POS, -129, 0xb6587b43'2e47501b'6d40900b'25024b32_u128},
- {Sign::POS, -129, 0xbdc4f816'7955698f'89e2eb55'3b279b3d_u128},
- {Sign::POS, -129, 0xc1826c86'08fe9951'd58525aa'd392ca50_u128},
- {Sign::POS, -129, 0xc544c055'fde99333'54dbf16f'b0695ee3_u128},
- {Sign::POS, -129, 0xc90c0049'26e9dbfb'88d5eae3'326327bb_u128},
- {Sign::POS, -129, 0xccd83954'b6359379'46dfa05b'ddfded8c_u128},
- {Sign::POS, -129, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
- {Sign::POS, -129, 0xd85b3fa7'a3407fa8'7b11f1c5'160c515c_u128},
- {Sign::POS, -129, 0xdc3be2bd'8d837f7f'1339e567'7ec44dd0_u128},
- {Sign::POS, -129, 0xe021c2cf'17ed9bdb'ea2b8c7b'b0ee9c8b_u128},
- {Sign::POS, -129, 0xe40cee16'a2ff21c4'aec56233'2791fe38_u128},
- {Sign::POS, -129, 0xe7fd7308'd6895b14'71682eba'cca79cfa_u128},
- {Sign::POS, -129, 0xebf36055'e1abc61e'a5ad5ce9'fb5a7bb6_u128},
- {Sign::POS, -129, 0xefeec4ea'c371584e'32251905'31a852c5_u128},
- {Sign::POS, -129, 0xf3efaff2'9c559a77'da8ad649'da21eab0_u128},
- {Sign::POS, -129, 0xf7f630d8'08fc2ada'4c3e2ea7'c15c3d1e_u128},
- {Sign::POS, -129, 0xfc025746'86680cc6'bcb9bfa9'852e0d35_u128},
- {Sign::POS, -128, 0x800a1995'f0019518'ce032f41'd1e774e8_u128},
- {Sign::POS, -128, 0x8215ea5c'd3e4c4c7'9b39ffee'bc29372a_u128},
- {Sign::POS, -128, 0x8424a633'5c777e0b'87f95f1b'efb6f806_u128},
- {Sign::POS, -128, 0x86365578'62acb7ce'b987b42e'3bb332a1_u128},
- {Sign::POS, -128, 0x884b00ae'f726cec5'139a7ba8'3bf2d136_u128},
- {Sign::POS, -128, 0x8a62b07f'3457c407'050799be'aaab2941_u128},
- {Sign::POS, -128, 0x8c7d6db7'169e0cda'8bd74461'7e9b7d52_u128},
- {Sign::POS, -128, 0x8e9b414b'5a92a606'046ad444'333ceb10_u128},
- {Sign::POS, -128, 0x90bc3458'61bf3d52'ef4c737f'ba4f5d66_u128},
- {Sign::POS, -128, 0x92e05023'1df57d6f'ae441c09'd761c549_u128},
- {Sign::POS, -128, 0x95079e1a'0382dc79'6e36aa9c'e90a3879_u128},
- {Sign::POS, -128, 0x973227d6'027ebd8a'0efca1a1'84e93809_u128},
- {Sign::POS, -128, 0x973227d6'027ebd8a'0efca1a1'84e93809_u128},
- {Sign::POS, -128, 0x995ff71b'8773432d'124bc6f1'acf95dc4_u128},
- {Sign::POS, -128, 0x9b9115db'83a3dd2d'352bea51'e58ea9e8_u128},
- {Sign::POS, -128, 0x9dc58e34'7d37696d'266d6cdc'959153bc_u128},
- {Sign::POS, -128, 0x9ffd6a73'a78eaf35'4527d82c'8214ddca_u128},
- {Sign::POS, -128, 0xa238b516'0413106e'404cabb7'6d600e3c_u128},
- {Sign::POS, -128, 0xa238b516'0413106e'404cabb7'6d600e3c_u128},
- {Sign::POS, -128, 0xa47778c9'8bcc86a1'cab7d2ec'23f0eef3_u128},
- {Sign::POS, -128, 0xa6b9c06e'6211646b'761c48dd'859de2d3_u128},
- {Sign::POS, -128, 0xa8ff9718'10a5e181'7fd3b7d7'e5d148bb_u128},
- {Sign::POS, -128, 0xab49080e'cda53208'c27c6780'd92b4d11_u128},
- {Sign::POS, -128, 0xad961ed0'cb91d406'db502402'c94092cd_u128},
- {Sign::POS, -128, 0xad961ed0'cb91d406'db502402'c94092cd_u128},
- {Sign::POS, -128, 0xafe6e713'93eeda29'3432ef6b'732b6843_u128},
- {Sign::POS, -128, 0xb23b6cc5'6cc84c99'bb324da7'e046e792_u128},
- {Sign::POS, -128, 0xb493bc0e'c9954243'b21709ce'430c8e24_u128},
- {Sign::POS, -128, 0xb493bc0e'c9954243'b21709ce'430c8e24_u128},
- {Sign::POS, -128, 0xb6efe153'c7e319f6'e91ad16e'cff10111_u128},
- {Sign::POS, -128, 0xb94fe935'b83e3eb5'ce31e481'cd797e79_u128},
- {Sign::POS, -128, 0xbbb3e094'b3d228d3'da3e961a'96c580fa_u128},
- {Sign::POS, -128, 0xbbb3e094'b3d228d3'da3e961a'96c580fa_u128},
- {Sign::POS, -128, 0xbe1bd491'3f3fda43'f396598a'ae91499a_u128},
- {Sign::POS, -128, 0xc087d28d'fb2febb8'ae4cceb0'f621941b_u128},
- {Sign::POS, -128, 0xc087d28d'fb2febb8'ae4cceb0'f621941b_u128},
- {Sign::POS, -128, 0xc2f7e831'632b6670'6c1855c4'2078f81b_u128},
- {Sign::POS, -128, 0xc56c2367'9b4d206e'169535fb'8bf577c8_u128},
- {Sign::POS, -128, 0xc56c2367'9b4d206e'169535fb'8bf577c8_u128},
- {Sign::POS, -128, 0xc7e49264'4d64237e'3b24cecc'60217942_u128},
- {Sign::POS, -128, 0xca6143a4'9626d820'3dc2687f'cf939696_u128},
- {Sign::POS, -128, 0xca6143a4'9626d820'3dc2687f'cf939696_u128},
- {Sign::POS, -128, 0xcce245f1'031e41fa'0a62e6ad'd1a901a0_u128},
- {Sign::POS, -128, 0xcf67a85f'a1f89a04'5bb6e231'38ad51e1_u128},
- {Sign::POS, -128, 0xcf67a85f'a1f89a04'5bb6e231'38ad51e1_u128},
- {Sign::POS, -128, 0xd1f17a56'21fb01ac'7fc60a51'03092bae_u128},
- {Sign::POS, -128, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
- {Sign::POS, -128, 0xd47fcb8c'0852f0c0'bfe9dbeb'f2e8a45e_u128},
- {Sign::POS, -128, 0xd712ac0c'f811659d'8e2d7d37'8127d823_u128},
- {Sign::POS, -128, 0xd9aa2c3b'0ea3cbc1'5c1a7f14'b168b365_u128},
- {Sign::POS, -128, 0xd9aa2c3b'0ea3cbc1'5c1a7f14'b168b365_u128},
- {Sign::POS, -128, 0xdc465cd1'55a90942'b7579f0f'8d3d514b_u128},
- {Sign::POS, -128, 0xdc465cd1'55a90942'b7579f0f'8d3d514b_u128},
- {Sign::POS, -128, 0xdee74ee6'4b0c38d3'b087205e'b55aea85_u128},
- {Sign::POS, -128, 0xe18d13ee'805a4de3'424a2623'd60dfb16_u128},
- {Sign::POS, -128, 0xe18d13ee'805a4de3'424a2623'd60dfb16_u128},
- {Sign::POS, -128, 0xe437bdbf'5254459c'4d3a591a'e6854787_u128},
- {Sign::POS, -128, 0xe437bdbf'5254459c'4d3a591a'e6854787_u128},
- {Sign::POS, -128, 0xe6e75e91'b9cca551'8dcdb6b2'4c5c5cdf_u128},
- {Sign::POS, -128, 0xe99c0905'36ece983'33ac7d9e'bba8a53c_u128},
- {Sign::POS, -128, 0xe99c0905'36ece983'33ac7d9e'bba8a53c_u128},
- {Sign::POS, -128, 0xec55d022'd80e3d27'fb2eede4'b59d8959_u128},
- {Sign::POS, -128, 0xec55d022'd80e3d27'fb2eede4'b59d8959_u128},
- {Sign::POS, -128, 0xef14c760'5d60654c'308b4546'66de8f99_u128},
- {Sign::POS, -128, 0xef14c760'5d60654c'308b4546'66de8f99_u128},
- {Sign::POS, -128, 0xf1d902a3'7aaa5085'8383cb0c'e23bebd4_u128},
- {Sign::POS, -128, 0xf1d902a3'7aaa5085'8383cb0c'e23bebd4_u128},
- {Sign::POS, -128, 0xf4a29645'38813c67'64fc87b4'a41f7b70_u128},
- {Sign::POS, -128, 0xf4a29645'38813c67'64fc87b4'a41f7b70_u128},
- {Sign::POS, -128, 0xf7719715'7665f689'3f5d7d82'b65c5686_u128},
- {Sign::POS, -128, 0xf7719715'7665f689'3f5d7d82'b65c5686_u128},
- {Sign::POS, -128, 0xfa461a5e'8f4b759d'6476077b'9fbd41ae_u128},
- {Sign::POS, -128, 0xfa461a5e'8f4b759d'6476077b'9fbd41ae_u128},
- {Sign::POS, -128, 0xfd2035e9'221ef5d0'0e3909ff'd0d61778_u128},
- {Sign::POS, 0, 0_u128},
- },
- // -log2(r) for the second step, generated by SageMath with:
- //
- // for i in range(-2^6, 2^7 + 1):
- // r = 2^-16 * round( 2^16 / (1 + i*2^(-14)) );
- // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
- // print("{Sign::NEG," if s == 1 else "{Sign::POS,", e, ",
- // format_hex(m), "},");
- /* .step_2 = */
- {
- {Sign::NEG, -135, 0xb9061559'18954401'b5cfed58'337e848a_u128},
- {Sign::NEG, -135, 0xb6264958'a3c7fa2b'ffaf2ac1'b1d20910_u128},
- {Sign::NEG, -135, 0xb34671e4'39aa448e'52521a39'50ea2ed8_u128},
- {Sign::NEG, -135, 0xb0668efb'7ef48ab7'f87e1abd'ee10fd95_u128},
- {Sign::NEG, -135, 0xad86a09e'185af0e8'fbd43bbc'c24c5e43_u128},
- {Sign::NEG, -135, 0xaaa6a6cb'aa8d57ce'2f4f5d48'f9796742_u128},
- {Sign::NEG, -135, 0xa7c6a183'da375c3d'3477fd67'c1cab6b3_u128},
- {Sign::NEG, -135, 0xa4e690c6'4c0056f0'7b4d33eb'381fe558_u128},
- {Sign::NEG, -135, 0xa2067492'a48b5c43'3ce25e48'cb498dea_u128},
- {Sign::NEG, -135, 0x9f264ce8'88773bed'70b0fcc9'e4330983_u128},
- {Sign::NEG, -135, 0x9c4619c7'9c5e80bf'bc9e4267'd3189b22_u128},
- {Sign::NEG, -135, 0x9965db2f'84d7705f'5fb3d896'326615c4_u128},
- {Sign::NEG, -135, 0x9685911f'e6740b02'178b5831'1e96d323_u128},
- {Sign::NEG, -135, 0x93a53b98'65c20b2a'006bf8b6'cf73d847_u128},
- {Sign::NEG, -135, 0x90c4da98'a74ae561'7019f6e6'4a580a02_u128},
- {Sign::NEG, -135, 0x8de46e20'4f93c7f6'cb5733cf'0eb4191d_u128},
- {Sign::NEG, -135, 0x8b03f62f'031d9ab8'56148d4f'c5e415b6_u128},
- {Sign::NEG, -135, 0x882372c4'6664feaf'fe5370f4'25872623_u128},
- {Sign::NEG, -135, 0x8542e3e0'1de24ddf'21b72a14'57ee70d6_u128},
- {Sign::NEG, -135, 0x81aa211f'1e332fcf'abff4f89'968bed0b_u128},
- {Sign::NEG, -136, 0xfd92f0cf'88d75f24'86410a67'6480a5a7_u128},
- {Sign::NEG, -136, 0xf7d1886b'2a876289'44280889'021970e4_u128},
- {Sign::NEG, -136, 0xf2100910'6a42bc14'32eb139d'9812090d_u128},
- {Sign::NEG, -136, 0xec4e72be'90cd2d2d'bef9dd41'e8e42810_u128},
- {Sign::NEG, -136, 0xe68cc574'e6e1e5d7'689d08ca'6c7c3eb1_u128},
- {Sign::NEG, -136, 0xe0cb0132'b5338423'01ef259a'7f69821d_u128},
- {Sign::NEG, -136, 0xdb0925f7'446c13a9'e22cea71'b7bb8467_u128},
- {Sign::NEG, -136, 0xd54733c1'dd2d0d04'0e5bb273'03f542fe_u128},
- {Sign::NEG, -136, 0xcf852a91'c80f553f'57453c8d'5dc64ce1_u128},
- {Sign::NEG, -136, 0xc9c30a66'4da33d56'6cc7add1'fc09ef92_u128},
- {Sign::NEG, -136, 0xc400d33e'b67081a7'e678d728'0de1c07f_u128},
- {Sign::NEG, -136, 0xbe3e851a'4af6496d'419bbeb2'239bdc39_u128},
- {Sign::NEG, -136, 0xb87c1ff8'53ab2631'd4676d1d'81755809_u128},
- {Sign::NEG, -136, 0xb2b9a3d8'18fd1349'b69dfef7'ac2e2890_u128},
- {Sign::NEG, -136, 0xacf710b8'e3517548'9f72fa0a'8fccabc0_u128},
- {Sign::NEG, -136, 0xa7346699'fb051978'b8bfe6a3'addb988e_u128},
- {Sign::NEG, -136, 0xa171a57a'a86c3551'67862c8e'c9dcd60d_u128},
- {Sign::NEG, -136, 0x9baecd5a'33d265ee'09bd3370'909e28a6_u128},
- {Sign::NEG, -136, 0x95ebde37'e57aaf84'a96bc611'b991419b_u128},
- {Sign::NEG, -136, 0x9028d813'059f7cdc'a50bb80f'203f0d62_u128},
- {Sign::NEG, -136, 0x8a65baea'dc729ec5'4d36cd47'4f65a317_u128},
- {Sign::NEG, -136, 0x84a286be'b21d4b8c'779be241'ef4874a3_u128},
- {Sign::NEG, -137, 0xfdbe771b'9d803cea'0e76a962'fa65ace3_u128},
- {Sign::NEG, -137, 0xf237b2ae'f4e62e5a'd3d35627'464a5267_u128},
- {Sign::NEG, -137, 0xe6b0c035'fa8b328c'162ef4b0'e838c363_u128},
- {Sign::NEG, -137, 0xdb299faf'3e7cd74f'77bb10b9'76b3b9ca_u128},
- {Sign::NEG, -137, 0xcfa25119'50b77014'209853ce'e70bc58b_u128},
- {Sign::NEG, -137, 0xc41ad472'c12614d3'63f9b57c'baf2e58d_u128},
- {Sign::NEG, -137, 0xb89329ba'1fa2a0fd'4fca1c93'1bd6e6d6_u128},
- {Sign::NEG, -137, 0xad0b50ed'fbf5b265'26d26e43'4a53490a_u128},
- {Sign::NEG, -137, 0xa1834a0c'e5d6a82d'c55e0790'78dc86a0_u128},
- {Sign::NEG, -137, 0x95fb1515'6ceba1b5'f05b9d5b'd28f540b_u128},
- {Sign::NEG, -137, 0x8a72b206'20c97d84'8ef87f1a'11cdb727_u128},
- {Sign::NEG, -138, 0xfdd441bb'21e7b069'9d687011'4c1183cf_u128},
- {Sign::NEG, -138, 0xe6c2c334'99ba16c4'63d514ff'f97e86f3_u128},
- {Sign::NEG, -138, 0xcfb0e875'c7cc5929'11a38190'1eadd883_u128},
- {Sign::NEG, -138, 0xb89eb17b'cabe1857'a9d69d37'bc0a5bac_u128},
- {Sign::NEG, -138, 0xa18c1e43'c10c6898'2dc97c9f'fefd2497_u128},
- {Sign::NEG, -138, 0x8a792eca'c911cf92'0dcdc8af'cb2ac09a_u128},
- {Sign::NEG, -139, 0xe6cbc61c'020c8446'dd454eb3'a1489470_u128},
- {Sign::NEG, -139, 0xb8a47615'0dfe4470'87803586'4d84b319_u128},
- {Sign::NEG, -139, 0x8a7c6d7a'f1de7942'7ce595cc'53b8342c_u128},
- {Sign::NEG, -140, 0xb8a7588f'd29b1baa'4710b590'49899141_u128},
- {Sign::NEG, -141, 0xb8a8c9d8'be9ae994'5957f633'309d74e3_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -141, 0xb8abac81'ab576f3b'8268aba0'30b1adf6_u128},
- {Sign::POS, -140, 0xb8ad1de1'ac9ea6a5'1511cba2'fb213a10_u128},
- {Sign::POS, -139, 0x8a82eb77'08262500'6379fb9f'd9bc6235_u128},
- {Sign::POS, -139, 0xb8b000b8'c65957cc'b6fe1bf6'01ee27d5_u128},
- {Sign::POS, -139, 0xe6ddcebb'd72d3f7f'8c6e6069'3a14e6d0_u128},
- {Sign::POS, -138, 0x8a862ac3'0095c084'e9bcfd0c'62eaa2ca_u128},
- {Sign::POS, -138, 0xa19dca8e'85918b6d'73b21420'9a5234a7_u128},
- {Sign::POS, -138, 0xb8b5c6c3'5e142a9b'347d4ca3'109fe4db_u128},
- {Sign::POS, -138, 0xcfce1f64'6dca7745'37a62c48'783bb066_u128},
- {Sign::POS, -138, 0xe6e6d474'9883fbe3'0794b643'7fb56344_u128},
- {Sign::POS, -138, 0xfdffe5f6'c232f658'1cb9a45e'd90318e6_u128},
- {Sign::POS, -137, 0x8a8ca9f6'e7762d0f'bc118e5d'bbef7dbc_u128},
- {Sign::POS, -137, 0x96198f2e'5173e93b'b4c0fb95'35907cf8_u128},
- {Sign::POS, -137, 0xa1a6a2a3'113fe246'c051d2c5'f00a9bb9_u128},
- {Sign::POS, -137, 0xad33e456'9918a8d5'55326987'8c1e5110_u128},
- {Sign::POS, -137, 0xb8c1544a'5b4e2caf'bc906750'b0ce372c_u128},
- {Sign::POS, -137, 0xc44ef27f'ca41bdd8'4c50eaa6'3be294b6_u128},
- {Sign::POS, -137, 0xcfdcbef8'58660da1'b6cb28db'8c065b44_u128},
- {Sign::POS, -137, 0xdb6ab9b5'783f2fc5'70479336'830ceb05_u128},
- {Sign::POS, -137, 0xe6f8e2b8'9c629b7a'2a458c83'1f6aeb49_u128},
- {Sign::POS, -137, 0xf2873a03'37772c8a'6489ba5b'd391e206_u128},
- {Sign::POS, -137, 0xfe15bf96'bc35246b'13f6fda5'10aeec3b_u128},
- {Sign::POS, -136, 0x84d239ba'4eb315a9'2f9a0ef9'e8250836_u128},
- {Sign::POS, -136, 0x8a99aacf'26f2a8a7'389019e8'22b70f1e_u128},
- {Sign::POS, -136, 0x9061330a'a04f87ae'308beeff'a12cf669_u128},
- {Sign::POS, -136, 0x9628d26d'7448a43f'9886a71b'25a2085d_u128},
- {Sign::POS, -136, 0x9bf088f8'5c65a56b'70ba9ceb'e0b969c3_u128},
- {Sign::POS, -136, 0xa1b856ac'1236e85b'cd855dc7'05ea2bea_u128},
- {Sign::POS, -136, 0xa7803b89'4f5580e0'7736196b'11afb331_u128},
- {Sign::POS, -136, 0xad483790'cd6339fa'94c99761'b8eab3d8_u128},
- {Sign::POS, -136, 0xb3104ac3'460a9668'6194b8c0'40814736_u128},
- {Sign::POS, -136, 0xb8d87521'72fed130'edde8d24'c7a999cc_u128},
- {Sign::POS, -136, 0xbea0b6ac'0dfbde2f'ea6b01eb'de42f1d0_u128},
- {Sign::POS, -136, 0xc4690f63'd0c66aa1'7ef732b6'9334cf50_u128},
- {Sign::POS, -136, 0xca317f49'752bddae'2ba86275'fcfc2d72_u128},
- {Sign::POS, -136, 0xcffa065d'b50258f6'b56ea44e'185bf99f_u128},
- {Sign::POS, -136, 0xd5c2a4a1'4a28b920'1d5c3bbe'b6902bfe_u128},
- {Sign::POS, -136, 0xdb8b5a14'ee86965f'a2f2bb9e'156b0f37_u128},
- {Sign::POS, -136, 0xe15426b9'5c0c4506'd166eb8d'a06ab5ef_u128},
- {Sign::POS, -136, 0xe71d0a8f'4cb2d60f'97dc7bae'4219de0f_u128},
- {Sign::POS, -136, 0xece60597'7a7c17a8'6c9a8e76'98f416c4_u128},
- {Sign::POS, -136, 0xf2af17d2'9f7295c0'7b3a20aa'5289695e_u128},
- {Sign::POS, -136, 0xf8784141'75a99a93'ddcf578e'e2c2897b_u128},
- {Sign::POS, -136, 0xfe4181e4'b73d2f37'e10ebd96'c3ec30ec_u128},
- {Sign::POS, -135, 0x82056cde'8f290e13'a9b7baec'b34ba577_u128},
- {Sign::POS, -135, 0x8430f56d'5e1edfd1'2da910dc'61c182da_u128},
- {Sign::POS, -135, 0x8715b5a8'f27bed90'faca09dc'7e0ba8b5_u128},
- {Sign::POS, -135, 0x89fa8180'19a2cace'0d723876'173c0947_u128},
- {Sign::POS, -135, 0x8cdf58f3'30b64515'4e6651df'154e8f8c_u128},
- {Sign::POS, -135, 0x8fc43c02'94dd8af3'ee54b77d'3bc34b6d_u128},
- {Sign::POS, -135, 0x92a92aae'a3442c3d'ad07dde9'b5f92cce_u128},
- {Sign::POS, -135, 0x958e24f7'b91a1a53'261aacf9'44b638f0_u128},
- {Sign::POS, -135, 0x98732ade'3393a868'232f5d64'a85b219d_u128},
- {Sign::POS, -135, 0x9b583c62'6fe98bc9'f3a958bb'706093fc_u128},
- {Sign::POS, -135, 0x9e3d5984'cb58dc25'c9eaa059'e7b0333a_u128},
- {Sign::POS, -135, 0xa1228245'a32313cf'1e154029'663243c0_u128},
- {Sign::POS, -135, 0xa407b6a5'548e1006'16515200'e283d006_u128},
- {Sign::POS, -135, 0xa6ecf6a4'3ce4113d'f498168a'3337ca4f_u128},
- {Sign::POS, -135, 0xa9d24242'b973bb63'8a04a89f'0548a10f_u128},
- {Sign::POS, -135, 0xacb79981'27901623'afaad01f'25772805_u128},
- {Sign::POS, -135, 0xaf9cfc5f'e4908d31'c4f47950'543fe0b8_u128},
- {Sign::POS, -135, 0xb2826adf'4dd0f08e'338655e6'77d0d3ec_u128},
- {Sign::POS, -135, 0xb567e4ff'c0b174cc'f8ac2ce1'9d009541_u128},
- {Sign::POS, -135, 0xb84d6ac1'9a96b35c'344d5e7d'd7b2f465_u128},
- {Sign::POS, -135, 0xbb32fc25'38e9aaca'bd6a217f'b4598ec7_u128},
- {Sign::POS, -135, 0xbe18992a'f917bf0e'bc21ff36'8f562b75_u128},
- {Sign::POS, -135, 0xc0fe41d3'3892b9cc'4944139c'cbf2cb9a_u128},
- {Sign::POS, -135, 0xc3e3f61e'54d0ca9c'1369970c'8b67e6b5_u128},
- {Sign::POS, -135, 0xc6c9b60c'ab4c8752'099b370e'2d04a530_u128},
- {Sign::POS, -135, 0xc9af819e'9984ec44'0b81c3d4'8aff589f_u128},
- {Sign::POS, -135, 0xcc9558d4'7cfd5c90'9f22b809'93be311b_u128},
- {Sign::POS, -135, 0xcf7b3bae'b33da265'ac29209c'8d8985ae_u128},
- {Sign::POS, -135, 0xd2612a2d'99d1ef47'3cbb6a52'0292351d_u128},
- {Sign::POS, -135, 0xd5472451'8e4adc56'43de9ae4'0507ef24_u128},
- {Sign::POS, -135, 0xd82d2a1a'ee3d6a97'69677b90'2ea4df3a_u128},
- {Sign::POS, -135, 0xdb133b8a'17430339'db7a3aff'74967bd5_u128},
- {Sign::POS, -135, 0xddf9589f'66f977de'25990c82'a0066ac6_u128},
- {Sign::POS, -135, 0xe0df815b'3b0302dd'0d424aac'f4babf55_u128},
- {Sign::POS, -135, 0xe30c278d'9936c595'f8e3e7eb'5a7bdebb_u128},
- {Sign::POS, -135, 0xe5f264ad'b62d5810'5ef8bf5a'df5deebe_u128},
- {Sign::POS, -135, 0xe8d8ad75'590bdf92'331d1996'5368fc82_u128},
- {Sign::POS, -135, 0xebbf01e4'df85219e'901c30c4'27e358b8_u128},
- {Sign::POS, -135, 0xeea561fc'a7504dc1'aeac7e98'57253b06_u128},
- {Sign::POS, -135, 0xf18bcdbd'0e28fdd7'e2113e58'93ab5b40_u128},
- {Sign::POS, -135, 0xf4724526'71cf3654'9a4efc80'ae977826_u128},
- {Sign::POS, -135, 0xf758c839'30076689'6bf3ba83'19332c9f_u128},
- {Sign::POS, -135, 0xfa3f56f5'a69a68ed'1d732d30'2e75018b_u128},
- {Sign::POS, -135, 0xfd25f15c'33558362'ba179c5d'bcceec01_u128},
- {Sign::POS, -134, 0x80064bb6'9a0533c0'5543f53b'8ad85039_u128},
- {Sign::POS, -134, 0x8179a494'8347996b'e971a556'5b93cb67_u128},
- {Sign::POS, -134, 0x82ed0348'045f379d'5b399644'ba714691_u128},
- {Sign::POS, -134, 0x846067d1'4c3b8982'5079f1e0'ec4b8496_u128},
- {Sign::POS, -134, 0x85d3d230'89ce40b0'6aba4990'a32e8873_u128},
- {Sign::POS, -134, 0x87474265'ec0b4548'e16770c3'a404291c_u128},
- {Sign::POS, -134, 0x88bab871'a1e8b61c'1edb7ffb'1d6b3eab_u128},
- {Sign::POS, -134, 0x8a2e3453'da5ee8cd'603243e1'ba7c7865_u128},
- {Sign::POS, -134, 0x8ba1b60c'c46869f6'57ea5c03'ea4621dd_u128},
- {Sign::POS, -134, 0x8d153d9c'8f01fd4a'd3534cbf'43bd7fd8_u128},
- {Sign::POS, -134, 0x8e88cb03'692a9dbc'62c8c807'5dc91cd5_u128},
- {Sign::POS, -134, 0x8ffc5e41'81e37d9e'04bb70a5'e3db7b85_u128},
- {Sign::POS, -134, 0x916ff757'083006c7'd3875ba3'2159547a_u128},
- {Sign::POS, -134, 0x9286adfc'a91ba28d'5c94c80e'7a8f66b1_u128},
- {Sign::POS, -134, 0x93fa514b'a0517623'52d313c4'7b4f91db_u128},
- {Sign::POS, -134, 0x956dfa72'866fc57d'80829e9f'3957a4c3_u128},
- {Sign::POS, -134, 0x96e1a971'8a824be5'1cd49179'72015ae7_u128},
- {Sign::POS, -134, 0x98555e48'db96fcd2'1af23c29'ef3032da_u128},
- {Sign::POS, -134, 0x99c918f8'a8be040e'e7f7bf24'0be67b80_u128},
- {Sign::POS, -134, 0x9b3cd981'2109c5dc'2bbe3cd4'f7d868fa_u128},
- {Sign::POS, -134, 0x9cb09fe2'738edf14'8c75d6a4'c5ae460d_u128},
- {Sign::POS, -134, 0x9e246c1c'cf642550'750fb989'c9a06186_u128},
- {Sign::POS, -134, 0x9f983e30'63a2a709'de787e24'4901bdf9_u128},
- {Sign::POS, -134, 0xa10c161d'5f65abc0'1ba3205f'f729efa4_u128},
- {Sign::POS, -134, 0xa27ff3e3'f1cab41b'a864d2a0'38fb19cd_u128},
- {Sign::POS, -134, 0xa3f3d784'49f17a11'fb21f083'a5fec56d_u128},
- {Sign::POS, -134, 0xa567c0fe'96fbf109'594c5552'bcc377f5_u128},
- {Sign::POS, -134, 0xa6dbb053'080e45fc'aeb35a35'3fc5a503_u128},
- {Sign::POS, -134, 0xa84fa581'cc4edf9f'67a5c051'30c0f330_u128},
- {Sign::POS, -134, 0xa9c3a08b'12e65e81'4de5cafd'e1caf46f_u128},
- {Sign::POS, -134, 0xab37a16f'0aff9d32'686fce3d'160e88fd_u128},
- {Sign::POS, -134, 0xacaba82d'e3c7b066'de1375b3'af6749a6_u128},
- {Sign::POS, -134, 0xadc2b114'c632da56'24356904'8ac4affe_u128},
- {Sign::POS, -134, 0xaf36c213'19b80ea2'd6796227'dcd39551_u128},
- {Sign::POS, -134, 0xb0aad8ec'cfb38d51'abc92653'86172074_u128},
- {Sign::POS, -134, 0xb21ef5a2'175ac65e'0caac9f1'7896f2ce_u128},
- {Sign::POS, -134, 0xb3931833'1fe56492'1c65a3c7'f828972b_u128},
- {Sign::POS, -134, 0xb50740a0'188d4daa'abdc6644'6a4286d9_u128},
- {Sign::POS, -134, 0xb67b6ee9'308ea27b'2f3bbe8e'8d72abec_u128},
- {Sign::POS, -134, 0xb7efa30e'9727bf11'b67dbdd7'f03d168c_u128},
- },
- // -log2(r) for the third step, generated by SageMath with:
- //
- // for i in range(-80, 81):
- // r = 2^-21 * round( 2^21 / (1 + i*2^(-21)) );
- // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
- // print("{Sign::NEG," if (s == 1) else "{Sign::POS,", e, ",
- // format_hex(m), "},");
- /* .step_3 = */
- {
- {Sign::NEG, -142, 0xe6d3a96b'978fc16e'26f2c63c'0827ccbb_u128},
- {Sign::NEG, -142, 0xe3f107a9'fbfc50ca'4b56fe66'7c8ec091_u128},
- {Sign::NEG, -142, 0xe10e65d1'4b937265'647d7618'1aec10fc_u128},
- {Sign::NEG, -142, 0xde2bc3e1'8653b4f5'99e8f4d5'379eca79_u128},
- {Sign::NEG, -142, 0xdb4921da'ac3ba730'f07da899'90c20623_u128},
- {Sign::NEG, -142, 0xd8667fbc'bd49d7cd'4a812184'8531851a_u128},
- {Sign::NEG, -142, 0xd583dd87'b97cd580'679a4d85'4ae13619_u128},
- {Sign::NEG, -142, 0xd2a13b3b'a0d32eff'e4d17407'2487a514_u128},
- {Sign::NEG, -142, 0xcfbe98d8'734b7301'3c90319d'969b54be_u128},
- {Sign::NEG, -142, 0xccdbf65e'30e43039'c6a173b0'9ba301e6_u128},
- {Sign::NEG, -142, 0xc9f953cc'd99bf55e'b8317428'd7d8d06b_u128},
- {Sign::NEG, -142, 0xc716b124'6d715125'23cdb51b'cc2061cd_u128},
- {Sign::NEG, -142, 0xc4340e64'ec62d241'f964fc78'084fd515_u128},
- {Sign::NEG, -142, 0xc1516b8e'566f076a'06474fb1'5ccbb015_u128},
- {Sign::NEG, -142, 0xbe6ec8a0'ab947f51'f525ef6d'0b75b1c3_u128},
- {Sign::NEG, -142, 0xbb8c259b'ebd1c8ae'4e13532d'f7ee8da7_u128},
- {Sign::NEG, -142, 0xb8a98280'17257233'76832500'd72a9027_u128},
- {Sign::NEG, -142, 0xb5c6df4d'2d8e0a95'b14a3d28'5e592ba0_u128},
- {Sign::NEG, -142, 0xb2e43c03'2f0a2089'1e9e9dc9'711f6e20_u128},
- {Sign::NEG, -142, 0xb00198a2'1b9842c1'bc176e97'4f255fac_u128},
- {Sign::NEG, -142, 0xad1ef529'f336fff3'64acf87f'c0f648e6_u128},
- {Sign::NEG, -142, 0xaa3c519a'b5e4e6d1'd0b8a157'4433e1f8_u128},
- {Sign::NEG, -142, 0xa759adf4'63a08610'95f4e785'371c69a9_u128},
- {Sign::NEG, -142, 0xa4770a36'fc686c63'277d5db0'0363a46f_u128},
- {Sign::NEG, -142, 0xa1946662'803b287c'd5cea669'485ec36c_u128},
- {Sign::NEG, -142, 0x9eb1c276'ef174910'cec66fda'04833322_u128},
- {Sign::NEG, -142, 0x9bcf1e74'48fb5cd2'1da36f6e'be3851db_u128},
- {Sign::NEG, -142, 0x98ec7a5a'8de5f273'ab055d83'abfc0d82_u128},
- {Sign::NEG, -142, 0x9609d629'bdd598a8'3cecf110'dbda68e9_u128},
- {Sign::NEG, -142, 0x932731e1'd8c8de22'76bbdb56'5a37e84b_u128},
- {Sign::NEG, -142, 0x90448d82'debe5194'd934c388'57eee4f3_u128},
- {Sign::NEG, -142, 0x8d61e90c'cfb481b1'c27b427b'4fbfc7db_u128},
- {Sign::NEG, -142, 0x8a7f447f'aba9fd2b'6e13de50'2b142b39_u128},
- {Sign::NEG, -142, 0x879c9fdb'729d52b3'f4e40620'6614e2ba_u128},
- {Sign::NEG, -142, 0x84b9fb20'248d10fd'4d320daa'3312ea6c_u128},
- {Sign::NEG, -142, 0x81d7564d'c177c6b9'4aa528fc'9d433c1a_u128},
- {Sign::NEG, -143, 0xfde962c8'92b80533'3c8ad047'559b1622_u128},
- {Sign::NEG, -143, 0xf82418c7'7870a69f'acf765a8'fc5bcc31_u128},
- {Sign::NEG, -143, 0xf25ece98'34168f1a'be238832'edd27f20_u128},
- {Sign::NEG, -143, 0xec99843a'c5a6dc07'02644bfc'a329b708_u128},
- {Sign::NEG, -143, 0xe6d439af'2d1eaac6'c6d05a78'8e614744_u128},
- {Sign::NEG, -143, 0xe10eeef5'6a7b18bc'133fe9cc'57a8c1d0_u128},
- {Sign::NEG, -143, 0xdb49a40d'7db94348'aa4cb429'195fb5dd_u128},
- {Sign::NEG, -143, 0xd58458f7'66d647ce'0951ef23'9abbb959_u128},
- {Sign::NEG, -143, 0xcfbf0db3'25cf43ad'686c430c'89143d35_u128},
- {Sign::NEG, -143, 0xc9f9c240'baa15447'ba79c248'afd42c12_u128},
- {Sign::NEG, -143, 0xc43476a0'254996fd'ad19e0a9'2f115327_u128},
- {Sign::NEG, -143, 0xbe6f2ad1'65c5292f'a8ad6ac3'b0c99520_u128},
- {Sign::NEG, -143, 0xb8a9ded4'7c11283d'd0567d4a'9cc5e6a1_u128},
- {Sign::NEG, -143, 0xb2e492a9'682ab188'01f87c65'4b231443_u128},
- {Sign::NEG, -143, 0xad1f4650'2a0ee26d'd6380b08'358051bc_u128},
- {Sign::NEG, -143, 0xa759f9c8'c1bad84e'a07b024d'26d391f6_u128},
- {Sign::NEG, -143, 0xa194ad13'2f2bb089'6ee868cb'69e3a7d8_u128},
- {Sign::NEG, -143, 0x9bcf602f'725e887d'0a6869ef'f6682f73_u128},
- {Sign::NEG, -143, 0x960a131d'8b507d87'f6a44d55'9ccf3f61_u128},
- {Sign::NEG, -143, 0x9044c5dd'79fead08'72066e1d'30a8e210_u128},
- {Sign::NEG, -143, 0x8a7f786f'3e66345c'75ba3245'b1b856af_u128},
- {Sign::NEG, -143, 0x84ba2ad2'd88430e1'b5ac0204'73ab198f_u128},
- {Sign::NEG, -144, 0xfde9ba10'90ab7feb'41127e3a'88eb6741_u128},
- {Sign::NEG, -144, 0xf25f1e1f'1baffdea'bf807875'22aca1c4_u128},
- {Sign::NEG, -144, 0xe6d481d1'5210167b'af00688b'14fa3adc_u128},
- {Sign::NEG, -144, 0xdb49e527'33c60457'4d72837c'8ab4d1e5_u128},
- {Sign::NEG, -144, 0xcfbf4820'c0cc0236'4e38ac27'bb252090_u128},
- {Sign::NEG, -144, 0xc434aabd'f91c4ad0'da3661f9'292f59e8_u128},
- {Sign::NEG, -144, 0xb8aa0cfe'dcb118de'8fd0af9b'dfd21488_u128},
- {Sign::NEG, -144, 0xad1f6ee3'6b84a716'82ee19a9'abf0bfa5_u128},
- {Sign::NEG, -144, 0xa194d06b'a591302f'3cf68d5b'5369a251_u128},
- {Sign::NEG, -144, 0x960a3197'8ad0eede'bcd34f38'c977647e_u128},
- {Sign::NEG, -144, 0x8a7f9267'1b3e1dda'76eee9c9'605e2143_u128},
- {Sign::NEG, -145, 0xfde9e5b4'ada5efae'aa6a3887'f0c803ab_u128},
- {Sign::NEG, -145, 0xe6d4a5e2'7b136f13'6e25927e'582ac191_u128},
- {Sign::NEG, -145, 0xcfbf6557'9eb92f4a'e2ebcac2'f3a8e9eb_u128},
- {Sign::NEG, -145, 0xb8aa2414'188ba5bb'9d9acc22'd5690751_u128},
- {Sign::NEG, -145, 0xa194e217'e87f47cb'1e12604b'6d4132ef_u128},
- {Sign::NEG, -145, 0x8a7f9f63'0e888add'cf340d2a'cb9b92a9_u128},
- {Sign::NEG, -146, 0xe6d4b7eb'1537c8ae'0dc5e49f'bde3c520_u128},
- {Sign::NEG, -146, 0xb8aa2f9e'b95b9332'0c074c95'57c01188_u128},
- {Sign::NEG, -146, 0x8a7fa5e1'09656009'f0f82818'ff9b654f_u128},
- {Sign::NEG, -147, 0xb8aa3564'0a7c33eb'd4cd6120'78bbe9b0_u128},
- {Sign::NEG, -148, 0xb8aa3846'b33aaecf'f08cf68f'42e09fa0_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -148, 0xb8aa3e0c'0513f9b1'68bd0fac'df0ddaaf_u128},
- {Sign::POS, -147, 0xb8aa40ee'ae2ec9b3'192af653'dd41575b_u128},
- {Sign::POS, -146, 0x8a7fb2dd'018e4892'3b5c8984'2e540a51_u128},
- {Sign::POS, -146, 0xb8aa46b4'00c0bee3'34ad8ebd'd8b2750c_u128},
- {Sign::POS, -146, 0xe6d4dbfc'54c5dd1b'70b12bd6'98e5be74_u128},
- {Sign::POS, -145, 0x8a7fb95a'feda5c46'08c7e424'efbd90e1_u128},
- {Sign::POS, -145, 0xa1950570'7dd23344'31b8eba7'74a1de77_u128},
- {Sign::POS, -145, 0xb8aa523e'a755fe32'ee400e8c'68838733_u128},
- {Sign::POS, -145, 0xcfbf9fc5'7b7147be'0e71fa0b'5603bc2f_u128},
- {Sign::POS, -145, 0xe6d4ee04'fa2f9a92'7763c919'd8ac65f1_u128},
- {Sign::POS, -145, 0xfdea3cfd'239c815e'232b270b'b6046ec1_u128},
- {Sign::POS, -144, 0x8a7fc656'fbe1c368'106f3919'7e068972_u128},
- {Sign::POS, -144, 0x960a6e8b'bb581acc'4a4a6f40'12941bd9_u128},
- {Sign::POS, -144, 0xa195171c'd0370c34'5bb34c11'20b3e54b_u128},
- {Sign::POS, -144, 0xad1fc00a'3a845cf9'6bb67313'92a3147a_u128},
- {Sign::POS, -144, 0xb8aa6953'fa45d275'2be1268d'cee3c8fc_u128},
- {Sign::POS, -144, 0xc43512fa'0f813201'd84158d5'd50251a9_u128},
- {Sign::POS, -144, 0xcfbfbcfc'7a3c40fa'3765bda1'5d0ef0fa_u128},
- {Sign::POS, -144, 0xdb4a675b'3a7cc4b9'9a5ddb55'f9cc27d9_u128},
- {Sign::POS, -144, 0xe6d51216'5048829b'dcba1c59'3d918775_u128},
- {Sign::POS, -144, 0xf25fbd2d'bba53ffd'648be060'e1e30a95_u128},
- {Sign::POS, -144, 0xfdea68a1'7c98c23b'22658dc2'f1bcf6e8_u128},
- {Sign::POS, -143, 0x84ba8a38'c9946759'48ad5162'fb4a236e_u128},
- {Sign::POS, -143, 0x8a7fe04e'ffad9560'db7fe378'9405ce3a_u128},
- {Sign::POS, -143, 0x90453693'609acde3'91b56e2e'4f2e5ed8_u128},
- {Sign::POS, -143, 0x960a8d05'ec5ef390'f8998880'c3bb4d76_u128},
- {Sign::POS, -143, 0x9bcfe3a6'a2fce918'e2b87805'2f67efee_u128},
- {Sign::POS, -143, 0xa1953a75'8477912b'67df3991'93f707c0_u128},
- {Sign::POS, -143, 0xa75a9172'90d1ce78'e51b89e4'd5d095e1_u128},
- {Sign::POS, -143, 0xad1fe89d'c80e83b1'fcbbee4e'dbf9f47d_u128},
- {Sign::POS, -143, 0xb2e53ff7'2a309387'964fbd58'b168371b_u128},
- {Sign::POS, -143, 0xb8aa977e'b73ae0aa'dea7276c'a7acd135_u128},
- {Sign::POS, -143, 0xbe6fef34'6f304dcd'47d33f7e'7afc83a6_u128},
- {Sign::POS, -143, 0xc4354718'5213bda0'892603b3'77909123_u128},
- {Sign::POS, -143, 0xc9fa9f2a'5fe812d6'9f32660a'a06239fb_u128},
- {Sign::POS, -143, 0xcfbff76a'98b03021'cbcc5504'd7407f6c_u128},
- {Sign::POS, -143, 0xd5854fd8'fc6ef834'9608c44d'06402ebe_u128},
- {Sign::POS, -143, 0xdb4aa875'8b274dc1'ca3db560'4a863477_u128},
- {Sign::POS, -143, 0xe1100140'44dc137c'7a024036'206c37d6_u128},
- {Sign::POS, -143, 0xe6d55a39'29902c17'fc2e9be8'90ff7ee3_u128},
- {Sign::POS, -143, 0xec9ab360'39467a47'ecdc275c'60da1b53_u128},
- {Sign::POS, -143, 0xf2600cb5'7401e0c0'2d6571e9'4056607f_u128},
- {Sign::POS, -143, 0xf8256638'd9c54234'e4664401'fd1ca2a7_u128},
- {Sign::POS, -143, 0xfdeabfea'6a93815a'7dbba7dc'b50b3fd7_u128},
- {Sign::POS, -142, 0x81d80ce5'1337c072'd541f90d'853c794b_u128},
- {Sign::POS, -142, 0x84bab9ec'06ae11c5'b08f6539'2ce8b75b_u128},
- {Sign::POS, -142, 0x879d670a'0fae2600'6e969a29'f8462436_u128},
- {Sign::POS, -142, 0x8a80143f'2e396e7d'cfc8cbca'a2bf130c_u128},
- {Sign::POS, -142, 0x8d62c18b'62515c98'b737e48c'19421e68_u128},
- {Sign::POS, -142, 0x90456eee'abf761ac'2a9689b9'97c50c0b_u128},
- {Sign::POS, -142, 0x93281c69'0b2cef13'52381fcc'c774d66b_u128},
- {Sign::POS, -142, 0x960ac9fa'7ff37629'7910cec1'dd92dc10_u128},
- {Sign::POS, -142, 0x98ed77a3'0a4c684a'0cb5866b'baff34cb_u128},
- {Sign::POS, -142, 0x9bd02562'aa3936d0'9d5c02c8'0c702d11_u128},
- {Sign::POS, -142, 0x9eb2d339'5fbb5318'dddad053'6b56e775_u128},
- {Sign::POS, -142, 0xa1958127'2ad42e7e'a3a9505d'7f71247a_u128},
- {Sign::POS, -142, 0xa4782f2c'0b853a5d'e6dfbd5d'210830d7_u128},
- {Sign::POS, -142, 0xa75add48'01cfe812'c2372f44'7bdcfa45_u128},
- {Sign::POS, -142, 0xaa3d8b7b'0db5a8f9'73099fd5'32c14b05_u128},
- {Sign::POS, -142, 0xad2039c5'2f37ee6e'5951eef4'83de2c37_u128},
- {Sign::POS, -142, 0xb002e826'665829cd'f7abe6ff'6da76f1e_u128},
- {Sign::POS, -142, 0xb2e5969e'b317cc74'f354411e'd47c5d7b_u128},
- {Sign::POS, -142, 0xb5c8452e'157847c0'1428a99b'a8f5911f_u128},
- {Sign::POS, -142, 0xb8aaf3d4'8d7b0d0c'44a7c433'0edff2c8_u128},
- {Sign::POS, -142, 0xbb8da292'1b218db6'91f1306a'84e4e07b_u128},
- {Sign::POS, -142, 0xbe705166'be6d3b1c'2bc58de4'0cdf7b6a_u128},
- {Sign::POS, -142, 0xc1530052'775f869a'648680b2'54df1d99_u128},
- {Sign::POS, -142, 0xc435af55'45f9e18e'b136b5ac'e0d6f74d_u128},
- {Sign::POS, -142, 0xc7185e6f'2a3dbd56'a979e6c4'34fad480_u128},
- {Sign::POS, -142, 0xc9fb0da0'242c8b50'0794df56'00c90a5a_u128},
- {Sign::POS, -142, 0xccddbce8'33c7bcd8'a86d8081'4ac18cf1_u128},
- {Sign::POS, -142, 0xcfc06c47'5910c34e'8b8ac57a'9cca2d56_u128},
- {Sign::POS, -142, 0xd2a31bbd'9409100f'd314c7e0'3140001f_u128},
- {Sign::POS, -142, 0xd585cb4a'e4b2147a'c3d4c40e'20b5ec89_u128},
- {Sign::POS, -142, 0xd8687aef'4b0d41ed'c5351d72'9060644e_u128},
- {Sign::POS, -142, 0xdb4b2aaa'c71c09c7'614162e1'e12e445d_u128},
- {Sign::POS, -142, 0xde2dda7d'58dfdd66'44a652ea'df8ede85_u128},
- {Sign::POS, -142, 0xe1108a67'005a2e29'3eb1e02a'f3e52c3c_u128},
- {Sign::POS, -142, 0xe3f33a67'bd8c6d6f'415335a2'53a82aa2_u128},
- {Sign::POS, -142, 0xe6d5ea7f'90780c97'611abb08'33305fe1_u128},
- },
- // -log2(r) for the fourth step, generated by SageMath with:
- //
- // for i in range(-65, 65):
- // r = 2^-28 * round( 2^28 / (1 + i*2^(-28)) );
- // s, m, e = RealField(128)(r).log2().sign_mantissa_exponent();
- // print("{Sign::NEG," if (s == 1) else "{Sign::POS,", e, ",
- // format_hex(m), "},");
- /* .step_4 = */
- {
- {Sign::NEG, -149, 0xbb8ce299'0b5d0b90'ef1bffe5'65ce0a46_u128},
- {Sign::NEG, -149, 0xb8aa39b8'07a576e4'bea32445'60ca3d99_u128},
- {Sign::NEG, -149, 0xb5c790d6'd5c354df'8b91f71c'eefa31a2_u128},
- {Sign::NEG, -149, 0xb2e4e7f5'75b6a57b'9096e3d6'84001c0e_u128},
- {Sign::NEG, -149, 0xb0023f13'e77f68b3'086054c7'94367f36_u128},
- {Sign::NEG, -149, 0xad1f9632'2b1d9e80'2d9cb330'94afe4de_u128},
- {Sign::NEG, -149, 0xaa3ced50'409146dd'3afa673c'fb3698f3_u128},
- {Sign::NEG, -149, 0xa75a446e'27da61c4'6b27d803'3e4c6450_u128},
- {Sign::NEG, -149, 0xa4779b8b'e0f8ef2f'f8d36b84'd52a477b_u128},
- {Sign::NEG, -149, 0xa194f2a9'6becef1a'1eab86ae'37c03565_u128},
- {Sign::NEG, -149, 0x9eb249c6'c8b6617d'175e8d56'deb4ce2c_u128},
- {Sign::NEG, -149, 0x9bcfa0e3'f7554653'1d9ae241'436519da_u128},
- {Sign::NEG, -149, 0x98ecf800'f7c99d96'6c0ee71a'dfe44325_u128},
- {Sign::NEG, -149, 0x960a4f1d'ca136741'3d68fc7c'2efb522f_u128},
- {Sign::NEG, -149, 0x9327a63a'6e32a34d'cc5781e8'ac28e749_u128},
- {Sign::NEG, -149, 0x9044fd56'e42751b6'5388d5ce'd3a0f5af_u128},
- {Sign::NEG, -149, 0x8d625473'2bf17275'0dab5588'224c7e4a_u128},
- {Sign::NEG, -149, 0x8a7fab8f'45910584'356d5d59'15c94a70_u128},
- {Sign::NEG, -149, 0x879d02ab'31060ade'057d4871'2c69a6a7_u128},
- {Sign::NEG, -149, 0x84ba59c6'ee50827c'b88970ea'e5341d60_u128},
- {Sign::NEG, -149, 0x81d7b0e2'7d706c5a'89402fcb'bfe331bb_u128},
- {Sign::NEG, -150, 0xfdea0ffb'bccb90e3'649fba08'79ca348b_u128},
- {Sign::NEG, -150, 0xf824be32'22612d78'dccd9edf'bab6f777_u128},
- {Sign::NEG, -150, 0xf25f6c68'2ba1ae69'f066b9aa'4636478e_u128},
- {Sign::NEG, -150, 0xec9a1a9d'd88d13ab'14c7b3cb'21578781_u128},
- {Sign::NEG, -150, 0xe6d4c8d3'29235d30'bf4d347b'528f56e1_u128},
- {Sign::NEG, -150, 0xe10f7708'1d648aef'6553e0c9'e1b70799_u128},
- {Sign::NEG, -150, 0xdb4a253c'b5509cdb'7c385b9b'd80c1375_u128},
- {Sign::NEG, -150, 0xd584d370'f0e792e9'795745ac'402f919d_u128},
- {Sign::NEG, -150, 0xcfbf81a4'd0296d0d'd20d3d8c'2625ac1b_u128},
- {Sign::NEG, -150, 0xc9fa2fd8'53162b3c'fbb6dfa2'97551554_u128},
- {Sign::NEG, -150, 0xc434de0b'79adcd6b'6bb0c62c'a2867d91_u128},
- {Sign::NEG, -150, 0xbe6f8c3e'43f0538d'9757893d'57e40877_u128},
- {Sign::NEG, -150, 0xb8aa3a70'b1ddbd97'f407bebd'c8f8c28e_u128},
- {Sign::NEG, -150, 0xb2e4e8a2'c3760b7e'f71dfa6d'08b016be_u128},
- {Sign::NEG, -150, 0xad1f96d4'78b93d37'15f6cde0'2b5543ce_u128},
- {Sign::NEG, -150, 0xa75a4505'd1a752b4'c5eec882'4692d1e9_u128},
- {Sign::NEG, -150, 0xa194f336'ce404bec'7c627794'7172081a_u128},
- {Sign::NEG, -150, 0x9bcfa167'6e8428d2'aeae662d'c45a61ce_u128},
- {Sign::NEG, -150, 0x960a4f97'b272e95b'd22f1d3b'59110455_u128},
- {Sign::NEG, -150, 0x9044fdc7'9a0c8d7c'5c412380'4ab83462_u128},
- {Sign::NEG, -150, 0x8a7fabf7'25511528'c240fd95'b5cecb89_u128},
- {Sign::NEG, -150, 0x84ba5a26'54408055'798b2dea'b82fadc4_u128},
- {Sign::NEG, -151, 0xfdea10aa'4db59ded'eef86988'e2227ddb_u128},
- {Sign::NEG, -151, 0xf25f6d07'3a400203'62e1207c'0209b090_u128},
- {Sign::NEG, -151, 0xe6d4c963'6e202cd4'39897891'13ec7bee_u128},
- {Sign::NEG, -151, 0xdb4a25be'e9561e49'5daa6556'5e562909_u128},
- {Sign::NEG, -151, 0xcfbf8219'abe1d64b'b9fcd606'2a84acbd_u128},
- {Sign::NEG, -151, 0xc434de73'b5c354c4'3939b586'c46792b3_u128},
- {Sign::NEG, -151, 0xb8aa3acd'06fa999b'c619ea6a'7a9ee85e_u128},
- {Sign::NEG, -151, 0xad1f9725'9f87a4bb'4b5656ef'9e7a27fd_u128},
- {Sign::NEG, -151, 0xa194f37d'7f6a760b'b3a7d900'83f7239c_u128},
- {Sign::NEG, -151, 0x960a4fd4'a6a30d75'e9c74a33'81c0f016_u128},
- {Sign::NEG, -151, 0x8a7fac2b'15316ae2'd86d7fca'f12ed012_u128},
- {Sign::NEG, -152, 0xfdea1101'962b1c76'd4a6956a'5c863e0f_u128},
- {Sign::NEG, -152, 0xe6d4c9ab'909eeed1'1462ef19'2f547877_u128},
- {Sign::NEG, -152, 0xcfbf8254'19be4ca6'45819d2f'1d72eb8b_u128},
- {Sign::NEG, -152, 0xb8aa3afb'318935c8'3d742790'eedbe719_u128},
- {Sign::NEG, -152, 0xa194f3a0'd7ffaa08'd1ac0d7b'70d74492_u128},
- {Sign::NEG, -152, 0x8a7fac45'0d21a939'd79ac583'75f83d0c_u128},
- {Sign::NEG, -153, 0xe6d4c9cf'a1de665a'49637b2b'ac367e87_u128},
- {Sign::NEG, -153, 0xb8aa3b12'46d08f69'1cc4b5ee'dcc78b35_u128},
- {Sign::NEG, -153, 0x8a7fac52'0919cd43'd43bf48a'42745836_u128},
- {Sign::NEG, -154, 0xb8aa3b1d'd1743f1c'3557bdcf'592619eb_u128},
- {Sign::NEG, -155, 0xb8aa3b23'96c617ae'6bdc2e83'd3ebb0c4_u128},
- {Sign::POS, 0, 0_u128},
- {Sign::POS, -155, 0xb8aa3b2f'2169ca44'2d5b4005'0e44e8ab_u128},
- {Sign::POS, -154, 0xb8aa3b34'e6bba447'b8560371'b8f04afe_u128},
- {Sign::POS, -153, 0x8a7fac6c'010a1f14'c79a43cc'c70459cc_u128},
- {Sign::POS, -153, 0xb8aa3b40'715f59c0'22c25632'f519f77f_u128},
- {Sign::POS, -153, 0xe6d4ca17'c45d8282'42c10a31'4e35fb9e_u128},
- {Sign::POS, -152, 0x8a7fac78'fd024cdb'be5a212e'd7b949e4_u128},
- {Sign::POS, -152, 0xa194f3e7'892a4fde'12dcf94e'f5c5b918_u128},
- {Sign::POS, -152, 0xb8aa3b57'86a6ca76'49781013'e57110ce_u128},
- {Sign::POS, -152, 0xcfbf82c8'f577bcd2'8cba70c0'85c12cb3_u128},
- {Sign::POS, -152, 0xe6d4ca3b'd59d2721'07332f3f'b09328b8_u128},
- {Sign::POS, -152, 0xfdea11b0'2717098f'e3716824'3a9d8b14_u128},
- {Sign::POS, -151, 0x8a7fac92'f4f2b226'a6022054'79b93722_u128},
- {Sign::POS, -151, 0x960a504e'8f041bc3'b5bd7358'52c0d583_u128},
- {Sign::POS, -151, 0xa194f40a'e1bfc1b6'36324863'0b0d812d_u128},
- {Sign::POS, -151, 0xad1f97c7'ed25a415'3ca83f0e'02b823c0_u128},
- {Sign::POS, -151, 0xb8aa3b85'b135c2f7'de66fb46'974bc4fd_u128},
- {Sign::POS, -151, 0xc434df44'2df01e75'30b6254e'23c69fc2_u128},
- {Sign::POS, -151, 0xcfbf8303'6354b6a4'48dd69ba'009b370c_u128},
- {Sign::POS, -151, 0xdb4a26c3'51638b9c'3c247973'83b16af5_u128},
- {Sign::POS, -151, 0xe6d4ca83'f81c9d74'1fd309b8'00678db7_u128},
- {Sign::POS, -151, 0xf25f6e45'577fec43'0930d418'c79378a3_u128},
- {Sign::POS, -151, 0xfdea1207'6f8d7820'0d85967b'2783a12c_u128},
- {Sign::POS, -150, 0x84ba5ae5'2022a091'210c898c'360016ed_u128},
- {Sign::POS, -150, 0x8a7facc6'e4d3a3b0'5e19883e'ef2605ab_u128},
- {Sign::POS, -150, 0x9044fea9'05d9c579'488dacc6'629300ae_u128},
- {Sign::POS, -150, 0x960a508b'833505f7'6b0cdebd'3264e3e3_u128},
- {Sign::POS, -150, 0x9bcfa26e'5ce56536'503b07e7'ff788dc2_u128},
- {Sign::POS, -150, 0xa194f451'92eae341'82bc1435'696a69d1_u128},
- {Sign::POS, -150, 0xa75a4635'25458024'8d33f1be'0e96fb1f_u128},
- {Sign::POS, -150, 0xad1f9819'13f53bea'fa4690c4'8c1b66c9_u128},
- {Sign::POS, -150, 0xb2e4e9fd'5efa16a0'5497e3b5'7dd5fe75_u128},
- {Sign::POS, -150, 0xb8aa3be2'06541050'26cbdf27'7e66cad5_u128},
- {Sign::POS, -150, 0xbe6f8dc7'0a032905'fb8679db'27301625_u128},
- {Sign::POS, -150, 0xc434dfac'6a0760cd'5d6bacbb'1056f6aa_u128},
- {Sign::POS, -150, 0xc9fa3192'2660b7b1'd71f72db'd0c3d936_u128},
- {Sign::POS, -150, 0xcfbf8378'3f0f2dbe'f345c97b'fe230ba2_u128},
- {Sign::POS, -150, 0xd584d55e'b412c300'3c82b004'2ce54751_u128},
- {Sign::POS, -150, 0xdb4a2745'856b7781'3d7a2806'f0403bae_u128},
- {Sign::POS, -150, 0xe10f792c'b3194b4d'80d03540'da2f18ae_u128},
- {Sign::POS, -150, 0xe6d4cb14'3d1c3e70'9128dd98'7b73194f_u128},
- {Sign::POS, -150, 0xec9a1cfc'237450f5'f928291e'63940e14_u128},
- {Sign::POS, -150, 0xf25f6ee4'662182e9'4372220d'20e0e78a_u128},
- {Sign::POS, -150, 0xf824c0cd'0523d455'faaad4c9'407040c7_u128},
- {Sign::POS, -150, 0xfdea12b6'007b4547'a9764fe1'4e20e9e4_u128},
- {Sign::POS, -149, 0x81d7b24f'ac13eae4'ed3c5206'ea4d3942_u128},
- {Sign::POS, -149, 0x84ba5b44'8614c2f4'0c2af218'aea6da27_u128},
- {Sign::POS, -149, 0x879d0439'8e402ad6'f6d912ac'383aaeba_u128},
- {Sign::POS, -149, 0x8a7fad2e'c4962293'7298bf5c'ca8b3d95_u128},
- {Sign::POS, -149, 0x8d625624'2916aa2f'44bc04da'a8808214_u128},
- {Sign::POS, -149, 0x9044ff19'bbc1c1b0'3294f0eb'14683198_u128},
- {Sign::POS, -149, 0x9327a80f'7c97691c'01759268'4ff600c3_u128},
- {Sign::POS, -149, 0x960a5105'6b97a078'76aff941'9c43e8b9_u128},
- {Sign::POS, -149, 0x98ecf9fb'88c267cb'5796367b'39d26c63_u128},
- {Sign::POS, -149, 0x9bcfa2f1'd417bf1a'697a5c2e'6888ddaa_u128},
- {Sign::POS, -149, 0x9eb24be8'4d97a66b'71ae7d89'67b5a2b7_u128},
- {Sign::POS, -149, 0xa194f4de'f5421dc4'3584aecf'760e7b39_u128},
- {Sign::POS, -149, 0xa4779dd5'cb17252a'7a4f0558'd1b0c59e_u128},
- {Sign::POS, -149, 0xa75a46cc'cf16bca4'055f9792'b821c455_u128},
- {Sign::POS, -149, 0xaa3cefc4'0140e436'9c087cff'664ee311_u128},
- {Sign::POS, -149, 0xad1f98bb'61959be8'039bce36'188dfc04_u128},
- {Sign::POS, -149, 0xb00241b2'f014e3be'016ba4e3'0a9d9d21_u128},
- {Sign::POS, -149, 0xb2e4eaaa'acbebbbe'5aca1bc7'77a54d5e_u128},
- {Sign::POS, -149, 0xb5c793a2'979323ee'd5094eb9'9a35d1f0_u128},
- {Sign::POS, -149, 0xb8aa3c9a'b0921c55'357b5aa4'ac49738d_u128},
- }};
-
-// > P = fpminimax(log2(1 + x)/x, 3, [|128...|], [-0x1.0002143p-29 , 0x1p-29]);
-// > P;
-// > dirtyinfnorm(log2(1 + x)/x - P, [-0x1.0002143p-29 , 0x1p-29]);
-// 0x1.27ad5...p-121
-constexpr Float128 BIG_COEFFS[4]{
- {Sign::NEG, -129, 0xb8aa3b29'5c2b21e3'3eccf694'0d66bbcc_u128},
- {Sign::POS, -129, 0xf6384ee1'd01febc9'ee39a6d6'49394bb1_u128},
- {Sign::NEG, -128, 0xb8aa3b29'5c17f0bb'be87fed0'67ea2ad5_u128},
- {Sign::POS, -127, 0xb8aa3b29'5c17f0bb'be87fed0'691d3e3f_u128},
-};
-
-// Reuse the output of the fast pass range reduction.
-// -2^-8 <= m_x < 2^-7
-double log2_accurate(int e_x, int index, double m_x) {
-
- Float128 sum(static_cast<float>(e_x));
- sum = fputil::quick_add(sum, LOG2_TABLE.step_1[index]);
-
- Float128 v_f128 = log_range_reduction(m_x, LOG2_TABLE, sum);
-
- // Polynomial approximation
- Float128 p = fputil::quick_mul(v_f128, BIG_COEFFS[0]);
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[1]));
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[2]));
- p = fputil::quick_mul(v_f128, fputil::quick_add(p, BIG_COEFFS[3]));
-
- Float128 r = fputil::quick_add(sum, p);
-
- return static_cast<double>(r);
-}
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-} // namespace
-
-LLVM_LIBC_FUNCTION(double, log2, (double x)) {
- using namespace common_constants_internal;
- using FPBits_t = typename fputil::FPBits<double>;
-
- FPBits_t xbits(x);
- uint64_t x_u = xbits.uintval();
-
- int x_e = -FPBits_t::EXP_BIAS;
-
- if (LIBC_UNLIKELY(xbits == FPBits_t::one())) {
- // log2(1.0) = +0.0
- return 0.0;
- }
-
- if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
- xbits.uintval() > FPBits_t::max_normal().uintval())) {
- if (x == 0.0) {
- // return -Inf and raise FE_DIVBYZERO.
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits_t::inf(Sign::NEG).get_val();
- }
- if (xbits.is_neg() && !xbits.is_nan()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits_t::quiet_nan().get_val();
- }
- if (xbits.is_inf_or_nan()) {
- return x;
- }
- // Normalize denormal inputs.
- xbits = FPBits_t(x * 0x1.0p52);
- x_e -= 52;
- x_u = xbits.uintval();
- }
-
- // log2(x) = log2(2^x_e * x_m)
- // = x_e + log2(x_m)
- // Range reduction for log2(x_m):
- // For each x_m, we would like to find r such that:
- // -2^-8 <= r * x_m - 1 < 2^-7
- int shifted = static_cast<int>(x_u >> 45);
- int index = shifted & 0x7F;
- double r = RD[index];
-
- // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
- // all 1's.
- x_e += static_cast<int>((x_u + (1ULL << 45)) >> 52);
- double e_x = static_cast<double>(x_e);
-
- // Set m = 1.mantissa.
- uint64_t x_m = (x_u & 0x000F'FFFF'FFFF'FFFFULL) | 0x3FF0'0000'0000'0000ULL;
- double m = FPBits_t(x_m).get_val();
-
- double u, u_sq;
- fputil::DoubleDouble r1;
-
- // Perform exact range reduction
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- u = fputil::multiply_add(r, m, -1.0); // exact
-#else
- uint64_t c_m = x_m & 0x3FFF'E000'0000'0000ULL;
- double c = FPBits_t(c_m).get_val();
- u = fputil::multiply_add(r, m - c, CD[index]); // exact
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
- // Exact sum:
- // r1.hi + r1.lo = e_x * log(2)_hi - log(r)_hi + u
- r1 = fputil::exact_add(LOG_R1[index].hi, u);
-
- // Error of u_sq = ulp(u^2);
- u_sq = u * u;
- // Degree-7 minimax polynomial
- double p0 = fputil::multiply_add(u, LOG_COEFFS[1], LOG_COEFFS[0]);
- double p1 = fputil::multiply_add(u, LOG_COEFFS[3], LOG_COEFFS[2]);
- double p2 = fputil::multiply_add(u, LOG_COEFFS[5], LOG_COEFFS[4]);
- double p = fputil::polyeval(u_sq, LOG_R1[index].lo, p0, p1, p2);
-
- r1.lo += p;
-
- // Quick double-double multiplication:
- // r2.hi + r2.lo ~ r1 * log2(e),
- // with error bounded by:
- // 4*ulp( ulp(r2.hi) )
- fputil::DoubleDouble r2 = fputil::quick_mult(r1, LOG2_E);
- fputil::DoubleDouble r3 = fputil::exact_add(e_x, r2.hi);
- r3.lo += r2.lo;
-
- // Overall, if we choose sufficiently large constant C, the total error is
- // bounded by (C * ulp(u^2)).
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- return r3.hi + r3.lo;
-#else
- // Total error is bounded by ~ C * ulp(u^2).
- double err = u_sq * P_ERR;
- // Lower bound from the result
- double left = r3.hi + (r3.lo - err);
- // Upper bound from the result
- double right = r3.hi + (r3.lo + err);
-
- // Ziv's test if fast pass is accurate enough.
- if (left == right)
- return left;
-
- return log2_accurate(x_e, index, u);
-#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-}
+LLVM_LIBC_FUNCTION(double, log2, (double x)) { return math::log2(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/logbf.cpp b/libc/src/math/generic/logbf.cpp
index 0dc0251..e319736 100644
--- a/libc/src/math/generic/logbf.cpp
+++ b/libc/src/math/generic/logbf.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/logbf.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/logbf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, logbf, (float x)) { return fputil::logb(x); }
+LLVM_LIBC_FUNCTION(float, logbf, (float x)) { return math::logbf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/logbf128.cpp b/libc/src/math/generic/logbf128.cpp
index af83487..e70a04c 100644
--- a/libc/src/math/generic/logbf128.cpp
+++ b/libc/src/math/generic/logbf128.cpp
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "src/math/logbf128.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/logbf128.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float128, logbf128, (float128 x)) { return fputil::logb(x); }
+LLVM_LIBC_FUNCTION(float128, logbf128, (float128 x)) {
+ return math::logbf128(x);
+}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/logbf16.cpp b/libc/src/math/generic/logbf16.cpp
index 6e286a2..bf4bf258 100644
--- a/libc/src/math/generic/logbf16.cpp
+++ b/libc/src/math/generic/logbf16.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/logbf16.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/logbf16.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float16, logbf16, (float16 x)) { return fputil::logb(x); }
+LLVM_LIBC_FUNCTION(float16, logbf16, (float16 x)) { return math::logbf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 4d2947d..863a9378 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -7,16 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/math/logf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/macros/properties/cpu_features.h"
-#include "src/__support/math/common_constants.h" // Lookup table for (1/f) and log(f)
+#include "src/__support/math/logf.h" // Lookup table for (1/f) and log(f)
// This is an algorithm for log(x) in single precision which is correctly
// rounded for all rounding modes, based on the implementation of log(x) from
@@ -52,133 +43,6 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, logf, (float x)) {
- using namespace common_constants_internal;
- constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
- using FPBits = typename fputil::FPBits<float>;
-
- FPBits xbits(x);
- uint32_t x_u = xbits.uintval();
-
- int m = -FPBits::EXP_BIAS;
-
- using fputil::round_result_slightly_down;
- using fputil::round_result_slightly_up;
-
- // Small inputs
- if (x_u < 0x4c5d65a5U) {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Hard-to-round cases.
- switch (x_u) {
- case 0x3f7f4d6fU: // x = 0x1.fe9adep-1f
- return round_result_slightly_up(-0x1.659ec8p-9f);
- case 0x41178febU: // x = 0x1.2f1fd6p+3f
- return round_result_slightly_up(0x1.1fcbcep+1f);
-#ifdef LIBC_TARGET_CPU_HAS_FMA
- case 0x3f800000U: // x = 1.0f
- return 0.0f;
-#else
- case 0x1e88452dU: // x = 0x1.108a5ap-66f
- return round_result_slightly_up(-0x1.6d7b18p+5f);
-#endif // LIBC_TARGET_CPU_HAS_FMA
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Subnormal inputs.
- if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
- if (x == 0.0f) {
- // Return -inf and raise FE_DIVBYZERO
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits::inf(Sign::NEG).get_val();
- }
- // Normalize denormal inputs.
- xbits = FPBits(xbits.get_val() * 0x1.0p23f);
- m -= 23;
- x_u = xbits.uintval();
- }
- } else {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Hard-to-round cases.
- switch (x_u) {
- case 0x4c5d65a5U: // x = 0x1.bacb4ap+25f
- return round_result_slightly_down(0x1.1e0696p+4f);
- case 0x65d890d3U: // x = 0x1.b121a6p+76f
- return round_result_slightly_down(0x1.a9a3f2p+5f);
- case 0x6f31a8ecU: // x = 0x1.6351d8p+95f
- return round_result_slightly_down(0x1.08b512p+6f);
- case 0x7a17f30aU: // x = 0x1.2fe614p+117f
- return round_result_slightly_up(0x1.451436p+6f);
-#ifndef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- case 0x500ffb03U: // x = 0x1.1ff606p+33f
- return round_result_slightly_up(0x1.6fdd34p+4f);
- case 0x5cd69e88U: // x = 0x1.ad3d1p+58f
- return round_result_slightly_up(0x1.45c146p+5f);
- case 0x5ee8984eU: // x = 0x1.d1309cp+62f;
- return round_result_slightly_up(0x1.5c9442p+5f);
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Exceptional inputs.
- if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
- if (x_u == 0x8000'0000U) {
- // Return -inf and raise FE_DIVBYZERO
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits::inf(Sign::NEG).get_val();
- }
- if (xbits.is_neg() && !xbits.is_nan()) {
- // Return NaN and raise FE_INVALID
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- // x is +inf or nan
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- return x;
- }
- }
-
-#ifndef LIBC_TARGET_CPU_HAS_FMA
- // Returning the correct +0 when x = 1.0 for non-FMA targets with FE_DOWNWARD
- // rounding mode.
- if (LIBC_UNLIKELY((x_u & 0x007f'ffffU) == 0))
- return static_cast<float>(
- static_cast<double>(m + xbits.get_biased_exponent()) * LOG_2);
-#endif // LIBC_TARGET_CPU_HAS_FMA
-
- uint32_t mant = xbits.get_mantissa();
- // Extract 7 leading fractional bits of the mantissa
- int index = mant >> 16;
- // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are
- // all 1's.
- m += static_cast<int>((x_u + (1 << 16)) >> 23);
-
- // Set bits to 1.m
- xbits.set_biased_exponent(0x7F);
-
- float u = xbits.get_val();
- double v;
-#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
- v = static_cast<double>(fputil::multiply_add(u, R[index], -1.0f)); // Exact.
-#else
- v = fputil::multiply_add(static_cast<double>(u), RD[index], -1.0); // Exact
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
-
- // Degree-5 polynomial approximation of log generated by Sollya with:
- // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]);
- constexpr double COEFFS[4] = {-0x1.000000000fe63p-1, 0x1.555556e963c16p-2,
- -0x1.000028dedf986p-2, 0x1.966681bfda7f7p-3};
- double v2 = v * v; // Exact
- double p2 = fputil::multiply_add(v, COEFFS[3], COEFFS[2]);
- double p1 = fputil::multiply_add(v, COEFFS[1], COEFFS[0]);
- double p0 = LOG_R[index] + v;
- double r = fputil::multiply_add(static_cast<double>(m), LOG_2,
- fputil::polyeval(v2, p0, p1, p2));
- return static_cast<float>(r);
-}
+LLVM_LIBC_FUNCTION(float, logf, (float x)) { return math::logf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/logf16.cpp b/libc/src/math/generic/logf16.cpp
index 22e0dc8..7149081 100644
--- a/libc/src/math/generic/logf16.cpp
+++ b/libc/src/math/generic/logf16.cpp
@@ -7,156 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/logf16.h"
-#include "hdr/errno_macros.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
-#include "src/__support/macros/properties/cpu_features.h"
-#include "src/__support/math/expxf16_utils.h"
+#include "src/__support/math/logf16.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
-static constexpr size_t N_LOGF16_EXCEPTS = 5;
-#else
-static constexpr size_t N_LOGF16_EXCEPTS = 11;
-#endif
-
-static constexpr fputil::ExceptValues<float16, N_LOGF16_EXCEPTS>
- LOGF16_EXCEPTS = {{
-// (input, RZ output, RU offset, RD offset, RN offset)
-#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
- // x = 0x1.61cp-13, logf16(x) = -0x1.16p+3 (RZ)
- {0x0987U, 0xc858U, 0U, 1U, 0U},
- // x = 0x1.f2p-12, logf16(x) = -0x1.e98p+2 (RZ)
- {0x0fc8U, 0xc7a6U, 0U, 1U, 1U},
-#endif
- // x = 0x1.4d4p-9, logf16(x) = -0x1.7e4p+2 (RZ)
- {0x1935U, 0xc5f9U, 0U, 1U, 0U},
- // x = 0x1.5ep-8, logf16(x) = -0x1.4ecp+2 (RZ)
- {0x1d78U, 0xc53bU, 0U, 1U, 0U},
-#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
- // x = 0x1.fdp-1, logf16(x) = -0x1.81p-8 (RZ)
- {0x3bf4U, 0x9e04U, 0U, 1U, 1U},
- // x = 0x1.fep-1, logf16(x) = -0x1.008p-8 (RZ)
- {0x3bf8U, 0x9c02U, 0U, 1U, 0U},
-#endif
- // x = 0x1.ffp-1, logf16(x) = -0x1.004p-9 (RZ)
- {0x3bfcU, 0x9801U, 0U, 1U, 0U},
- // x = 0x1.ff8p-1, logf16(x) = -0x1p-10 (RZ)
- {0x3bfeU, 0x9400U, 0U, 1U, 1U},
-#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
- // x = 0x1.4c4p+1, logf16(x) = 0x1.e84p-1 (RZ)
- {0x4131U, 0x3ba1U, 1U, 0U, 1U},
-#else
- // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
- {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
- // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
- {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
- // x = 0x1.d5p+9, logf16(x) = 0x1.b5cp+2 (RZ)
- {0x6354U, 0x46d7U, 1U, 0U, 1U},
-#endif
- }};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) {
- using namespace math::expxf16_internal;
- using FPBits = fputil::FPBits<float16>;
- FPBits x_bits(x);
-
- uint16_t x_u = x_bits.uintval();
-
- // If x <= 0, or x is 1, or x is +inf, or x is NaN.
- if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) {
- // log(NaN) = NaN
- if (x_bits.is_nan()) {
- if (x_bits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- return x;
- }
-
- // log(+/-0) = −inf
- if ((x_u & 0x7fffU) == 0U) {
- fputil::raise_except_if_required(FE_DIVBYZERO);
- return FPBits::inf(Sign::NEG).get_val();
- }
-
- if (x_u == 0x3c00U)
- return FPBits::zero().get_val();
-
- // When x < 0.
- if (x_u > 0x8000U) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- // log(+inf) = +inf
- return FPBits::inf().get_val();
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- if (auto r = LOGF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // To compute log(x), we perform the following range reduction:
- // x = 2^m * 1.mant,
- // log(x) = m * log(2) + log(1.mant).
- // To compute log(1.mant), let f be the highest 6 bits including the hidden
- // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of
- // the mantissa, then:
- // log(1.mant) = log(f) + log(1.mant / f)
- // = log(f) + log(1 + d/f)
- // since d/f is sufficiently small.
- // We store log(f) and 1/f in the lookup tables LOGF_F and ONE_OVER_F_F
- // respectively.
-
- int m = -FPBits::EXP_BIAS;
-
- // When x is subnormal, normalize it.
- if ((x_u & FPBits::EXP_MASK) == 0U) {
- // Can't pass an integer to fputil::cast directly.
- constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
- x_bits = FPBits(x_bits.get_val() * fputil::cast<float16>(NORMALIZE_EXP));
- x_u = x_bits.uintval();
- m -= FPBits::FRACTION_LEN;
- }
-
- uint16_t mant = x_bits.get_mantissa();
- // Leading 10 - 5 = 5 bits of the mantissa.
- int f = mant >> 5;
- // Unbiased exponent.
- m += x_u >> FPBits::FRACTION_LEN;
-
- // Set bits to 1.mant instead of 2^m * 1.mant.
- x_bits.set_biased_exponent(FPBits::EXP_BIAS);
- float mant_f = x_bits.get_val();
- // v = 1.mant * 1/f - 1 = d/f
- float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f);
-
- // Degree-3 minimax polynomial generated by Sollya with the following
- // commands:
- // > display = hexadecimal;
- // > P = fpminimax(log(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
- // > x * P;
- float log1p_d_over_f =
- v * fputil::polyeval(v, 0x1p+0f, -0x1.001804p-1f, 0x1.557ef6p-2f);
- // log(1.mant) = log(f) + log(1 + d/f)
- float log_1_mant = LOGF_F[f] + log1p_d_over_f;
- return fputil::cast<float16>(
- fputil::multiply_add(static_cast<float>(m), LOGF_2, log_1_mant));
-}
+LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) { return math::logf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp
index c362628..648d57b 100644
--- a/libc/src/math/generic/sinf.cpp
+++ b/libc/src/math/generic/sinf.cpp
@@ -7,176 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/sinf.h"
-#include "src/__support/FPUtil/BasicOperations.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-
-#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) && \
- defined(LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT) && \
- defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
-
-#include "src/__support/math/sincosf_float_eval.h"
+#include "src/__support/math/sinf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
- return math::sincosf_float_eval::sincosf_eval</*IS_SIN*/ true>(x);
-}
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#else // !LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
-
-#include "src/__support/math/sincosf_utils.h"
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-#include "src/__support/math/range_reduction_fma.h"
-#else // !LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-#include "src/__support/math/range_reduction.h"
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
- FPBits xbits(x);
-
- uint32_t x_u = xbits.uintval();
- uint32_t x_abs = x_u & 0x7fff'ffffU;
- double xd = static_cast<double>(x);
-
- // Range reduction:
- // For |x| > pi/32, we perform range reduction as follows:
- // Find k and y such that:
- // x = (k + y) * pi/32
- // k is an integer
- // |y| < 0.5
- // For small range (|x| < 2^45 when FMA instructions are available, 2^22
- // otherwise), this is done by performing:
- // k = round(x * 32/pi)
- // y = x * 32/pi - k
- // For large range, we will omit all the higher parts of 32/pi such that the
- // least significant bits of their full products with x are larger than 63,
- // since sin((k + y + 64*i) * pi/32) = sin(x + i * 2pi) = sin(x).
- //
- // When FMA instructions are not available, we store the digits of 32/pi in
- // chunks of 28-bit precision. This will make sure that the products:
- // x * THIRTYTWO_OVER_PI_28[i] are all exact.
- // When FMA instructions are available, we simply store the digits of 32/pi in
- // chunks of doubles (53-bit of precision).
- // So when multiplying by the largest values of single precision, the
- // resulting output should be correct up to 2^(-208 + 128) ~ 2^-80. By the
- // worst-case analysis of range reduction, |y| >= 2^-38, so this should give
- // us more than 40 bits of accuracy. For the worst-case estimation of range
- // reduction, see for instances:
- // Elementary Functions by J-M. Muller, Chapter 11,
- // Handbook of Floating-Point Arithmetic by J-M. Muller et. al.,
- // Chapter 10.2.
- //
- // Once k and y are computed, we then deduce the answer by the sine of sum
- // formula:
- // sin(x) = sin((k + y)*pi/32)
- // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
- // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed
- // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
- // computed using degree-7 and degree-6 minimax polynomials generated by
- // Sollya respectively.
-
- // |x| <= pi/16
- if (LIBC_UNLIKELY(x_abs <= 0x3e49'0fdbU)) {
-
- // |x| < 0x1.d12ed2p-12f
- if (LIBC_UNLIKELY(x_abs < 0x39e8'9769U)) {
- if (LIBC_UNLIKELY(x_abs == 0U)) {
- // For signed zeros.
- return x;
- }
- // When |x| < 2^-12, the relative error of the approximation sin(x) ~ x
- // is:
- // |sin(x) - x| / |sin(x)| < |x^3| / (6|x|)
- // = x^2 / 6
- // < 2^-25
- // < epsilon(1)/2.
- // So the correctly rounded values of sin(x) are:
- // = x - sign(x)*eps(x) if rounding mode = FE_TOWARDZERO,
- // or (rounding mode = FE_UPWARD and x is
- // negative),
- // = x otherwise.
- // To simplify the rounding decision and make it more efficient, we use
- // fma(x, -2^-25, x) instead.
- // An exhaustive test shows that this formula work correctly for all
- // rounding modes up to |x| < 0x1.c555dep-11f.
- // Note: to use the formula x - 2^-25*x to decide the correct rounding, we
- // do need fma(x, -2^-25, x) to prevent underflow caused by -2^-25*x when
- // |x| < 2^-125. For targets without FMA instructions, we simply use
- // double for intermediate results as it is more efficient than using an
- // emulated version of FMA.
-#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
- return fputil::multiply_add(x, -0x1.0p-25f, x);
-#else
- return static_cast<float>(fputil::multiply_add(xd, -0x1.0p-25, xd));
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
- }
-
- // |x| < pi/16.
- double xsq = xd * xd;
-
- // Degree-9 polynomial approximation:
- // sin(x) ~ x + a_3 x^3 + a_5 x^5 + a_7 x^7 + a_9 x^9
- // = x (1 + a_3 x^2 + ... + a_9 x^8)
- // = x * P(x^2)
- // generated by Sollya with the following commands:
- // > display = hexadecimal;
- // > Q = fpminimax(sin(x)/x, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/16]);
- double result =
- fputil::polyeval(xsq, 1.0, -0x1.55555555554c6p-3, 0x1.1111111085e65p-7,
- -0x1.a019f70fb4d4fp-13, 0x1.718d179815e74p-19);
- return static_cast<float>(xd * result);
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
- float r = -0x1.63f4bap-2f;
- int rounding = fputil::quick_get_round();
- if ((rounding == FE_DOWNWARD && xbits.is_pos()) ||
- (rounding == FE_UPWARD && xbits.is_neg()))
- r = -0x1.63f4bcp-2f;
- return xbits.is_neg() ? -r : r;
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- if (x_abs == 0x7f80'0000U) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- }
- return x + FPBits::quiet_nan().get_val();
- }
-
- // Combine the results with the sine of sum formula:
- // sin(x) = sin((k + y)*pi/32)
- // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
- // = sin_y * cos_k + (1 + cosm1_y) * sin_k
- // = sin_y * cos_k + (cosm1_y * sin_k + sin_k)
- double sin_k, cos_k, sin_y, cosm1_y;
-
- sincosf_eval(xd, x_abs, sin_k, cos_k, sin_y, cosm1_y);
-
- return static_cast<float>(fputil::multiply_add(
- sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
-}
+LLVM_LIBC_FUNCTION(float, sinf, (float x)) { return math::sinf(x); }
} // namespace LIBC_NAMESPACE_DECL
-#endif // LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
diff --git a/libc/src/math/generic/sinf16.cpp b/libc/src/math/generic/sinf16.cpp
index 2b57920..6118970 100644
--- a/libc/src/math/generic/sinf16.cpp
+++ b/libc/src/math/generic/sinf16.cpp
@@ -7,110 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/sinf16.h"
-#include "hdr/errno_macros.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/macros/optimization.h"
-#include "src/__support/math/sincosf16_utils.h"
+#include "src/__support/math/sinf16.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-constexpr size_t N_EXCEPTS = 4;
-
-constexpr fputil::ExceptValues<float16, N_EXCEPTS> SINF16_EXCEPTS{{
- // (input, RZ output, RU offset, RD offset, RN offset)
- {0x2b45, 0x2b43, 1, 0, 1},
- {0x585c, 0x3ba3, 1, 0, 1},
- {0x5cb0, 0xbbff, 0, 1, 0},
- {0x51f5, 0xb80f, 0, 1, 0},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
- using namespace sincosf16_internal;
- using FPBits = fputil::FPBits<float16>;
- FPBits xbits(x);
-
- uint16_t x_u = xbits.uintval();
- uint16_t x_abs = x_u & 0x7fff;
- float xf = x;
-
- // Range reduction:
- // For |x| > pi/32, we perform range reduction as follows:
- // Find k and y such that:
- // x = (k + y) * pi/32
- // k is an integer, |y| < 0.5
- //
- // This is done by performing:
- // k = round(x * 32/pi)
- // y = x * 32/pi - k
- //
- // Once k and y are computed, we then deduce the answer by the sine of sum
- // formula:
- // sin(x) = sin((k + y) * pi/32)
- // = sin(k * pi/32) * cos(y * pi/32) +
- // sin(y * pi/32) * cos(k * pi/32)
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Handle exceptional values
- bool x_sign = x_u >> 15;
-
- if (auto r = SINF16_EXCEPTS.lookup_odd(x_abs, x_sign);
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- int rounding = fputil::quick_get_round();
-
- // Exhaustive tests show that for |x| <= 0x1.f4p-11, 1ULP rounding errors
- // occur. To fix this, the following apply:
- if (LIBC_UNLIKELY(x_abs <= 0x13d0)) {
- // sin(+/-0) = +/-0
- if (LIBC_UNLIKELY(x_abs == 0U))
- return x;
-
- // When x > 0, and rounding upward, sin(x) == x.
- // When x < 0, and rounding downward, sin(x) == x.
- if ((rounding == FE_UPWARD && xbits.is_pos()) ||
- (rounding == FE_DOWNWARD && xbits.is_neg()))
- return x;
-
- // When x < 0, and rounding upward, sin(x) == (x - 1ULP)
- if (rounding == FE_UPWARD && xbits.is_neg()) {
- x_u--;
- return FPBits(x_u).get_val();
- }
- }
-
- if (xbits.is_inf_or_nan()) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- if (xbits.is_inf()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- }
-
- return x + FPBits::quiet_nan().get_val();
- }
-
- float sin_k, cos_k, sin_y, cosm1_y;
- sincosf16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
-
- if (LIBC_UNLIKELY(sin_y == 0 && sin_k == 0))
- return FPBits::zero(xbits.sign()).get_val();
-
- // Since, cosm1_y = cos_y - 1, therefore:
- // sin(x) = cos_k * sin_y + sin_k + (cosm1_y * sin_k)
- return fputil::cast<float16>(fputil::multiply_add(
- sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
-}
+LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) { return math::sinf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp
index 5f2d0b5..a8f8c71 100644
--- a/libc/src/math/generic/sinhf.cpp
+++ b/libc/src/math/generic/sinhf.cpp
@@ -7,74 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/sinhf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/math/sinhfcoshf_utils.h"
+#include "src/__support/math/sinhf.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
- FPBits xbits(x);
- uint32_t x_abs = xbits.abs().uintval();
-
- // When |x| >= 90, or x is inf or nan
- if (LIBC_UNLIKELY(x_abs >= 0x42b4'0000U || x_abs <= 0x3da0'0000U)) {
- // |x| <= 0.078125
- if (x_abs <= 0x3da0'0000U) {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // |x| = 0.0005589424981735646724700927734375
- if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
- if (fputil::fenv_is_round_to_nearest())
- return x;
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // |x| <= 2^-26
- if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
- return static_cast<float>(
- LIBC_UNLIKELY(x_abs == 0) ? x : (x + 0.25 * x * x * x));
- }
-
- double xdbl = x;
- double x2 = xdbl * xdbl;
- // Sollya: fpminimax(sinh(x),[|3,5,7|],[|D...|],[-1/16-1/64;1/16+1/64],x);
- // Sollya output: x * (0x1p0 + x^0x1p1 * (0x1.5555555556583p-3 + x^0x1p1
- // * (0x1.111110d239f1fp-7
- // + x^0x1p1 * 0x1.a02b5a284013cp-13)))
- // Therefore, output of Sollya = x * pe;
- double pe = fputil::polyeval(x2, 0.0, 0x1.5555555556583p-3,
- 0x1.111110d239f1fp-7, 0x1.a02b5a284013cp-13);
- return static_cast<float>(fputil::multiply_add(xdbl, pe, xdbl));
- }
-
- if (xbits.is_nan())
- return x + 1.0f; // sNaN to qNaN + signal
-
- if (xbits.is_inf())
- return x;
-
- int rounding = fputil::quick_get_round();
- if (xbits.is_neg()) {
- if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
- return -FPBits::max_normal().get_val();
- } else {
- if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
- return FPBits::max_normal().get_val();
- }
-
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_OVERFLOW);
-
- return x + FPBits::inf(xbits.sign()).get_val();
- }
-
- // sinh(x) = (e^x - e^(-x)) / 2.
- return static_cast<float>(
- math::sinhfcoshf_internal::exp_pm_eval</*is_sinh*/ true>(x));
-}
+LLVM_LIBC_FUNCTION(float, sinhf, (float x)) { return math::sinhf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sinhf16.cpp b/libc/src/math/generic/sinhf16.cpp
index f6b5c9b..1dd1501 100644
--- a/libc/src/math/generic/sinhf16.cpp
+++ b/libc/src/math/generic/sinhf16.cpp
@@ -7,147 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/sinhf16.h"
-#include "hdr/errno_macros.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
-#include "src/__support/math/expxf16_utils.h"
+#include "src/__support/math/sinhf16.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr fputil::ExceptValues<float16, 17> SINHF16_EXCEPTS_POS = {{
- // x = 0x1.714p-5, sinhf16(x) = 0x1.714p-5 (RZ)
- {0x29c5U, 0x29c5U, 1U, 0U, 1U},
- // x = 0x1.25p-4, sinhf16(x) = 0x1.25p-4 (RZ)
- {0x2c94U, 0x2c94U, 1U, 0U, 1U},
- // x = 0x1.f5p-4, sinhf16(x) = 0x1.f64p-4 (RZ)
- {0x2fd4U, 0x2fd9U, 1U, 0U, 0U},
- // x = 0x1.b1cp-3, sinhf16(x) = 0x1.b4cp-3 (RZ)
- {0x32c7U, 0x32d3U, 1U, 0U, 1U},
- // x = 0x1.6e8p-2, sinhf16(x) = 0x1.764p-2 (RZ)
- {0x35baU, 0x35d9U, 1U, 0U, 1U},
- // x = 0x1.6b4p-1, sinhf16(x) = 0x1.8a4p-1 (RZ)
- {0x39adU, 0x3a29U, 1U, 0U, 1U},
- // x = 0x1.a58p-1, sinhf16(x) = 0x1.d68p-1 (RZ)
- {0x3a96U, 0x3b5aU, 1U, 0U, 1U},
- // x = 0x1.574p+0, sinhf16(x) = 0x1.c78p+0 (RZ)
- {0x3d5dU, 0x3f1eU, 1U, 0U, 1U},
- // x = 0x1.648p+1, sinhf16(x) = 0x1.024p+3 (RZ)
- {0x4192U, 0x4809U, 1U, 0U, 0U},
- // x = 0x1.cdcp+1, sinhf16(x) = 0x1.26cp+4 (RZ)
- {0x4337U, 0x4c9bU, 1U, 0U, 0U},
- // x = 0x1.d0cp+1, sinhf16(x) = 0x1.2d8p+4 (RZ)
- {0x4343U, 0x4cb6U, 1U, 0U, 1U},
- // x = 0x1.018p+2, sinhf16(x) = 0x1.bfp+4 (RZ)
- {0x4406U, 0x4efcU, 1U, 0U, 0U},
- // x = 0x1.2fcp+2, sinhf16(x) = 0x1.cc4p+5 (RZ)
- {0x44bfU, 0x5331U, 1U, 0U, 1U},
- // x = 0x1.4ecp+2, sinhf16(x) = 0x1.75cp+6 (RZ)
- {0x453bU, 0x55d7U, 1U, 0U, 0U},
- // x = 0x1.8a4p+2, sinhf16(x) = 0x1.d94p+7 (RZ)
- {0x4629U, 0x5b65U, 1U, 0U, 1U},
- // x = 0x1.5fp+3, sinhf16(x) = 0x1.c54p+14 (RZ)
- {0x497cU, 0x7715U, 1U, 0U, 1U},
- // x = 0x1.3c8p+1, sinhf16(x) = 0x1.78ap+2 (RZ)
- {0x40f2U, 0x45e2U, 1U, 0U, 1U},
-}};
-
-static constexpr fputil::ExceptValues<float16, 13> SINHF16_EXCEPTS_NEG = {{
- // x = -0x1.714p-5, sinhf16(x) = -0x1.714p-5 (RZ)
- {0xa9c5U, 0xa9c5U, 0U, 1U, 1U},
- // x = -0x1.25p-4, sinhf16(x) = -0x1.25p-4 (RZ)
- {0xac94U, 0xac94U, 0U, 1U, 1U},
- // x = -0x1.f5p-4, sinhf16(x) = -0x1.f64p-4 (RZ)
- {0xafd4U, 0xafd9U, 0U, 1U, 0U},
- // x = -0x1.6e8p-2, sinhf16(x) = -0x1.764p-2 (RZ)
- {0xb5baU, 0xb5d9U, 0U, 1U, 1U},
- // x = -0x1.a58p-1, sinhf16(x) = -0x1.d68p-1 (RZ)
- {0xba96U, 0xbb5aU, 0U, 1U, 1U},
- // x = -0x1.cdcp+1, sinhf16(x) = -0x1.26cp+4 (RZ)
- {0xc337U, 0xcc9bU, 0U, 1U, 0U},
- // x = -0x1.d0cp+1, sinhf16(x) = -0x1.2d8p+4 (RZ)
- {0xc343U, 0xccb6U, 0U, 1U, 1U},
- // x = -0x1.018p+2, sinhf16(x) = -0x1.bfp+4 (RZ)
- {0xc406U, 0xcefcU, 0U, 1U, 0U},
- // x = -0x1.2fcp+2, sinhf16(x) = -0x1.cc4p+5 (RZ)
- {0xc4bfU, 0xd331U, 0U, 1U, 1U},
- // x = -0x1.4ecp+2, sinhf16(x) = -0x1.75cp+6 (RZ)
- {0xc53bU, 0xd5d7U, 0U, 1U, 0U},
- // x = -0x1.8a4p+2, sinhf16(x) = -0x1.d94p+7 (RZ)
- {0xc629U, 0xdb65U, 0U, 1U, 1U},
- // x = -0x1.5fp+3, sinhf16(x) = -0x1.c54p+14 (RZ)
- {0xc97cU, 0xf715U, 0U, 1U, 1U},
- // x = -0x1.3c8p+1, sinhf16(x) = -0x1.78ap+2 (RZ)
- {0xc0f2U, 0xc5e2U, 0U, 1U, 1U},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) {
- using namespace math::expxf16_internal;
- using FPBits = fputil::FPBits<float16>;
- FPBits x_bits(x);
-
- uint16_t x_u = x_bits.uintval();
- uint16_t x_abs = x_u & 0x7fffU;
-
- // When |x| = 0, or -2^(-14) <= x <= -2^(-9), or |x| >= asinh(2^16), or x is
- // NaN.
- if (LIBC_UNLIKELY(x_abs == 0U || (x_u >= 0x8400U && x_u <= 0xa400U) ||
- x_abs >= 0x49e5U)) {
- // sinh(NaN) = NaN
- if (x_bits.is_nan()) {
- if (x_bits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- return x;
- }
-
- // sinh(+/-0) = sinh(+/-0)
- if (x_abs == 0U)
- return FPBits::zero(x_bits.sign()).get_val();
-
- // When |x| >= asinh(2^16).
- if (x_abs >= 0x49e5U) {
- // sinh(+/-inf) = +/-inf
- if (x_bits.is_inf())
- return FPBits::inf(x_bits.sign()).get_val();
-
- int rounding_mode = fputil::quick_get_round();
- if (rounding_mode == FE_TONEAREST ||
- (x_bits.is_pos() && rounding_mode == FE_UPWARD) ||
- (x_bits.is_neg() && rounding_mode == FE_DOWNWARD)) {
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
- return FPBits::inf(x_bits.sign()).get_val();
- }
- return FPBits::max_normal(x_bits.sign()).get_val();
- }
-
- // When -2^(-14) <= x <= -2^(-9).
- if (fputil::fenv_is_round_down())
- return FPBits(static_cast<uint16_t>(x_u + 1)).get_val();
- return FPBits(static_cast<uint16_t>(x_u)).get_val();
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- if (x_bits.is_pos()) {
- if (auto r = SINHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
- } else {
- if (auto r = SINHF16_EXCEPTS_NEG.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- return eval_sinh_or_cosh</*IsSinh=*/true>(x);
-}
+LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) { return math::sinhf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sinpif.cpp b/libc/src/math/generic/sinpif.cpp
index f3383f1..67e44a7 100644
--- a/libc/src/math/generic/sinpif.cpp
+++ b/libc/src/math/generic/sinpif.cpp
@@ -7,111 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/sinpif.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/math/sincosf_utils.h"
+#include "src/__support/math/sinpif.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float, sinpif, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
- FPBits xbits(x);
-
- uint32_t x_u = xbits.uintval();
- uint32_t x_abs = x_u & 0x7fff'ffffU;
- double xd = static_cast<double>(x);
-
- // Range reduction:
- // For |x| > 1/32, we perform range reduction as follows:
- // Find k and y such that:
- // x = (k + y) * 1/32
- // k is an integer
- // |y| < 0.5
- //
- // This is done by performing:
- // k = round(x * 32)
- // y = x * 32 - k
- //
- // Once k and y are computed, we then deduce the answer by the sine of sum
- // formula:
- // sin(x * pi) = sin((k + y)*pi/32)
- // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
- // The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..31 are precomputed
- // and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
- // computed using degree-7 and degree-6 minimax polynomials generated by
- // Sollya respectively.
-
- // |x| <= 1/16
- if (LIBC_UNLIKELY(x_abs <= 0x3d80'0000U)) {
-
- if (LIBC_UNLIKELY(x_abs < 0x33CD'01D7U)) {
- if (LIBC_UNLIKELY(x_abs == 0U)) {
- // For signed zeros.
- return x;
- }
-
- // For very small values we can approximate sinpi(x) with x * pi
- // An exhaustive test shows that this is accurate for |x| < 9.546391 ×
- // 10-8
- double xdpi = xd * 0x1.921fb54442d18p1;
- return static_cast<float>(xdpi);
- }
-
- // |x| < 1/16.
- double xsq = xd * xd;
-
- // Degree-9 polynomial approximation:
- // sinpi(x) ~ x + a_3 x^3 + a_5 x^5 + a_7 x^7 + a_9 x^9
- // = x (1 + a_3 x^2 + ... + a_9 x^8)
- // = x * P(x^2)
- // generated by Sollya with the following commands:
- // > display = hexadecimal;
- // > Q = fpminimax(sin(pi * x)/x, [|0, 2, 4, 6, 8|], [|D...|], [0, 1/16]);
- double result = fputil::polyeval(
- xsq, 0x1.921fb54442d18p1, -0x1.4abbce625bbf2p2, 0x1.466bc675e116ap1,
- -0x1.32d2c0b62d41cp-1, 0x1.501ec4497cb7dp-4);
- return static_cast<float>(xd * result);
- }
-
- // Numbers greater or equal to 2^23 are always integers or NaN
- if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
-
- // check for NaN values
- if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- if (x_abs == 0x7f80'0000U) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- }
-
- return x + FPBits::quiet_nan().get_val();
- }
-
- return FPBits::zero(xbits.sign()).get_val();
- }
-
- // Combine the results with the sine of sum formula:
- // sin(x * pi) = sin((k + y)*pi/32)
- // = sin(y*pi/32) * cos(k*pi/32) + cos(y*pi/32) * sin(k*pi/32)
- // = sin_y * cos_k + (1 + cosm1_y) * sin_k
- // = sin_y * cos_k + (cosm1_y * sin_k + sin_k)
- double sin_k, cos_k, sin_y, cosm1_y;
- sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
-
- if (LIBC_UNLIKELY(sin_y == 0 && sin_k == 0))
- return FPBits::zero(xbits.sign()).get_val();
-
- return static_cast<float>(fputil::multiply_add(
- sin_y, cos_k, fputil::multiply_add(cosm1_y, sin_k, sin_k)));
-}
-
+LLVM_LIBC_FUNCTION(float, sinpif, (float x)) { return math::sinpif(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sqrt.cpp b/libc/src/math/generic/sqrt.cpp
index 791975e..05717d1 100644
--- a/libc/src/math/generic/sqrt.cpp
+++ b/libc/src/math/generic/sqrt.cpp
@@ -7,12 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/sqrt.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/sqrt.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(double, sqrt, (double x)) { return fputil::sqrt<double>(x); }
+LLVM_LIBC_FUNCTION(double, sqrt, (double x)) { return math::sqrt(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/sqrtf16.cpp b/libc/src/math/generic/sqrtf16.cpp
index 0aa4a20..d175f69f 100644
--- a/libc/src/math/generic/sqrtf16.cpp
+++ b/libc/src/math/generic/sqrtf16.cpp
@@ -7,14 +7,9 @@
//===----------------------------------------------------------------------===//
#include "src/math/sqrtf16.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/math/sqrtf16.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(float16, sqrtf16, (float16 x)) {
- return fputil::sqrt<float16>(x);
-}
-
+LLVM_LIBC_FUNCTION(float16, sqrtf16, (float16 x)) { return math::sqrtf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/tan.cpp b/libc/src/math/generic/tan.cpp
index 7ea40c9..2e9f809 100644
--- a/libc/src/math/generic/tan.cpp
+++ b/libc/src/math/generic/tan.cpp
@@ -7,290 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/tan.h"
-#include "hdr/errno_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/double_double.h"
-#include "src/__support/FPUtil/dyadic_float.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-#include "src/__support/math/range_reduction_double_common.h"
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-#include "src/__support/math/range_reduction_double_fma.h"
-#else
-#include "src/__support/math/range_reduction_double_nofma.h"
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+#include "src/__support/math/tan.h"
namespace LIBC_NAMESPACE_DECL {
-using DoubleDouble = fputil::DoubleDouble;
-using Float128 = typename fputil::DyadicFloat<128>;
-
-namespace {
-
-LIBC_INLINE double tan_eval(const DoubleDouble &u, DoubleDouble &result) {
- // Evaluate tan(y) = tan(x - k * (pi/128))
- // We use the degree-9 Taylor approximation:
- // tan(y) ~ P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835
- // Then the error is bounded by:
- // |tan(y) - P(y)| < 2^-6 * |y|^11 < 2^-6 * 2^-66 = 2^-72.
- // For y ~ u_hi + u_lo, fully expanding the polynomial and drop any terms
- // < ulp(u_hi^3) gives us:
- // P(y) = y + y^3/3 + 2*y^5/15 + 17*y^7/315 + 62*y^9/2835 = ...
- // ~ u_hi + u_hi^3 * (1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 +
- // + u_hi^2 * 62/2835))) +
- // + u_lo (1 + u_hi^2 * (1 + u_hi^2 * 2/3))
- double u_hi_sq = u.hi * u.hi; // Error < ulp(u_hi^2) < 2^(-6 - 52) = 2^-58.
- // p1 ~ 17/315 + u_hi^2 62 / 2835.
- double p1 =
- fputil::multiply_add(u_hi_sq, 0x1.664f4882c10fap-6, 0x1.ba1ba1ba1ba1cp-5);
- // p2 ~ 1/3 + u_hi^2 2 / 15.
- double p2 =
- fputil::multiply_add(u_hi_sq, 0x1.1111111111111p-3, 0x1.5555555555555p-2);
- // q1 ~ 1 + u_hi^2 * 2/3.
- double q1 = fputil::multiply_add(u_hi_sq, 0x1.5555555555555p-1, 1.0);
- double u_hi_3 = u_hi_sq * u.hi;
- double u_hi_4 = u_hi_sq * u_hi_sq;
- // p3 ~ 1/3 + u_hi^2 * (2/15 + u_hi^2 * (17/315 + u_hi^2 * 62/2835))
- double p3 = fputil::multiply_add(u_hi_4, p1, p2);
- // q2 ~ 1 + u_hi^2 * (1 + u_hi^2 * 2/3)
- double q2 = fputil::multiply_add(u_hi_sq, q1, 1.0);
- double tan_lo = fputil::multiply_add(u_hi_3, p3, u.lo * q2);
- // Overall, |tan(y) - (u_hi + tan_lo)| < ulp(u_hi^3) <= 2^-71.
- // And the relative errors is:
- // |(tan(y) - (u_hi + tan_lo)) / tan(y) | <= 2*ulp(u_hi^2) < 2^-64
- result = fputil::exact_add(u.hi, tan_lo);
- return fputil::multiply_add(fputil::FPBits<double>(u_hi_3).abs().get_val(),
- 0x1.0p-51, 0x1.0p-102);
-}
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-// Accurate evaluation of tan for small u.
-[[maybe_unused]] Float128 tan_eval(const Float128 &u) {
- Float128 u_sq = fputil::quick_mul(u, u);
-
- // tan(x) ~ x + x^3/3 + x^5 * 2/15 + x^7 * 17/315 + x^9 * 62/2835 +
- // + x^11 * 1382/155925 + x^13 * 21844/6081075 +
- // + x^15 * 929569/638512875 + x^17 * 6404582/10854718875
- // Relative errors < 2^-127 for |u| < pi/256.
- constexpr Float128 TAN_COEFFS[] = {
- {Sign::POS, -127, 0x80000000'00000000'00000000'00000000_u128}, // 1
- {Sign::POS, -129, 0xaaaaaaaa'aaaaaaaa'aaaaaaaa'aaaaaaab_u128}, // 1
- {Sign::POS, -130, 0x88888888'88888888'88888888'88888889_u128}, // 2/15
- {Sign::POS, -132, 0xdd0dd0dd'0dd0dd0d'd0dd0dd0'dd0dd0dd_u128}, // 17/315
- {Sign::POS, -133, 0xb327a441'6087cf99'6b5dd24e'ec0b327a_u128}, // 62/2835
- {Sign::POS, -134,
- 0x91371aaf'3611e47a'da8e1cba'7d900eca_u128}, // 1382/155925
- {Sign::POS, -136,
- 0xeb69e870'abeefdaf'e606d2e4'd1e65fbc_u128}, // 21844/6081075
- {Sign::POS, -137,
- 0xbed1b229'5baf15b5'0ec9af45'a2619971_u128}, // 929569/638512875
- {Sign::POS, -138,
- 0x9aac1240'1b3a2291'1b2ac7e3'e4627d0a_u128}, // 6404582/10854718875
- };
-
- return fputil::quick_mul(
- u, fputil::polyeval(u_sq, TAN_COEFFS[0], TAN_COEFFS[1], TAN_COEFFS[2],
- TAN_COEFFS[3], TAN_COEFFS[4], TAN_COEFFS[5],
- TAN_COEFFS[6], TAN_COEFFS[7], TAN_COEFFS[8]));
-}
-
-// Calculation a / b = a * (1/b) for Float128.
-// Using the initial approximation of q ~ (1/b), then apply 2 Newton-Raphson
-// iterations, before multiplying by a.
-[[maybe_unused]] Float128 newton_raphson_div(const Float128 &a, Float128 b,
- double q) {
- Float128 q0(q);
- constexpr Float128 TWO(2.0);
- b.sign = (b.sign == Sign::POS) ? Sign::NEG : Sign::POS;
- Float128 q1 =
- fputil::quick_mul(q0, fputil::quick_add(TWO, fputil::quick_mul(b, q0)));
- Float128 q2 =
- fputil::quick_mul(q1, fputil::quick_add(TWO, fputil::quick_mul(b, q1)));
- return fputil::quick_mul(a, q2);
-}
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-} // anonymous namespace
-
-LLVM_LIBC_FUNCTION(double, tan, (double x)) {
- using namespace math::range_reduction_double_internal;
- using FPBits = typename fputil::FPBits<double>;
- FPBits xbits(x);
-
- uint16_t x_e = xbits.get_biased_exponent();
-
- DoubleDouble y;
- unsigned k;
- LargeRangeReduction range_reduction_large{};
-
- // |x| < 2^16
- if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT)) {
- // |x| < 2^-7
- if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 7)) {
- // |x| < 2^-27, |tan(x) - x| < ulp(x)/2.
- if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 27)) {
- // Signed zeros.
- if (LIBC_UNLIKELY(x == 0.0))
- return x + x; // Make sure it works with FTZ/DAZ.
-
-#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- return fputil::multiply_add(x, 0x1.0p-54, x);
-#else
- if (LIBC_UNLIKELY(x_e < 4)) {
- int rounding_mode = fputil::quick_get_round();
- if ((xbits.sign() == Sign::POS && rounding_mode == FE_UPWARD) ||
- (xbits.sign() == Sign::NEG && rounding_mode == FE_DOWNWARD))
- return FPBits(xbits.uintval() + 1).get_val();
- }
- return fputil::multiply_add(x, 0x1.0p-54, x);
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
- }
- // No range reduction needed.
- k = 0;
- y.lo = 0.0;
- y.hi = x;
- } else {
- // Small range reduction.
- k = range_reduction_small(x, y);
- }
- } else {
- // Inf or NaN
- if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- // tan(+-Inf) = NaN
- if (xbits.get_mantissa() == 0) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- }
- return x + FPBits::quiet_nan().get_val();
- }
-
- // Large range reduction.
- k = range_reduction_large.fast(x, y);
- }
-
- DoubleDouble tan_y;
- [[maybe_unused]] double err = tan_eval(y, tan_y);
-
- // Look up sin(k * pi/128) and cos(k * pi/128)
-#ifdef LIBC_MATH_HAS_SMALL_TABLES
- // Memory saving versions. Use 65-entry table:
- auto get_idx_dd = [](unsigned kk) -> DoubleDouble {
- unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63);
- DoubleDouble ans = SIN_K_PI_OVER_128[idx];
- if (kk & 128) {
- ans.hi = -ans.hi;
- ans.lo = -ans.lo;
- }
- return ans;
- };
- DoubleDouble msin_k = get_idx_dd(k + 128);
- DoubleDouble cos_k = get_idx_dd(k + 64);
-#else
- // Fast look up version, but needs 256-entry table.
- // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128).
- DoubleDouble msin_k = SIN_K_PI_OVER_128[(k + 128) & 255];
- DoubleDouble cos_k = SIN_K_PI_OVER_128[(k + 64) & 255];
-#endif // LIBC_MATH_HAS_SMALL_TABLES
-
- // After range reduction, k = round(x * 128 / pi) and y = x - k * (pi / 128).
- // So k is an integer and -pi / 256 <= y <= pi / 256.
- // Then tan(x) = sin(x) / cos(x)
- // = sin((k * pi/128 + y) / cos((k * pi/128 + y)
- // = (cos(y) * sin(k*pi/128) + sin(y) * cos(k*pi/128)) /
- // / (cos(y) * cos(k*pi/128) - sin(y) * sin(k*pi/128))
- // = (sin(k*pi/128) + tan(y) * cos(k*pi/128)) /
- // / (cos(k*pi/128) - tan(y) * sin(k*pi/128))
- DoubleDouble cos_k_tan_y = fputil::quick_mult(tan_y, cos_k);
- DoubleDouble msin_k_tan_y = fputil::quick_mult(tan_y, msin_k);
-
- // num_dd = sin(k*pi/128) + tan(y) * cos(k*pi/128)
- DoubleDouble num_dd = fputil::exact_add<false>(cos_k_tan_y.hi, -msin_k.hi);
- // den_dd = cos(k*pi/128) - tan(y) * sin(k*pi/128)
- DoubleDouble den_dd = fputil::exact_add<false>(msin_k_tan_y.hi, cos_k.hi);
- num_dd.lo += cos_k_tan_y.lo - msin_k.lo;
- den_dd.lo += msin_k_tan_y.lo + cos_k.lo;
-
-#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- double tan_x = (num_dd.hi + num_dd.lo) / (den_dd.hi + den_dd.lo);
- return tan_x;
-#else
- // Accurate test and pass for correctly rounded implementation.
-
- // Accurate double-double division
- DoubleDouble tan_x = fputil::div(num_dd, den_dd);
-
- // Simple error bound: |1 / den_dd| < 2^(1 + floor(-log2(den_dd)))).
- uint64_t den_inv = (static_cast<uint64_t>(FPBits::EXP_BIAS + 1)
- << (FPBits::FRACTION_LEN + 1)) -
- (FPBits(den_dd.hi).uintval() & FPBits::EXP_MASK);
-
- // For tan_x = (num_dd + err) / (den_dd + err), the error is bounded by:
- // | tan_x - num_dd / den_dd | <= err * ( 1 + | tan_x * den_dd | ).
- double tan_err =
- err * fputil::multiply_add(FPBits(den_inv).get_val(),
- FPBits(tan_x.hi).abs().get_val(), 1.0);
-
- double err_higher = tan_x.lo + tan_err;
- double err_lower = tan_x.lo - tan_err;
-
- double tan_upper = tan_x.hi + err_higher;
- double tan_lower = tan_x.hi + err_lower;
-
- // Ziv's rounding test.
- if (LIBC_LIKELY(tan_upper == tan_lower))
- return tan_upper;
-
- Float128 u_f128;
- if (LIBC_LIKELY(x_e < FPBits::EXP_BIAS + FAST_PASS_EXPONENT))
- u_f128 = range_reduction_small_f128(x);
- else
- u_f128 = range_reduction_large.accurate();
-
- Float128 tan_u = tan_eval(u_f128);
-
- auto get_sin_k = [](unsigned kk) -> Float128 {
- unsigned idx = (kk & 64) ? 64 - (kk & 63) : (kk & 63);
- Float128 ans = SIN_K_PI_OVER_128_F128[idx];
- if (kk & 128)
- ans.sign = Sign::NEG;
- return ans;
- };
-
- // cos(k * pi/128) = sin(k * pi/128 + pi/2) = sin((k + 64) * pi/128).
- Float128 sin_k_f128 = get_sin_k(k);
- Float128 cos_k_f128 = get_sin_k(k + 64);
- Float128 msin_k_f128 = get_sin_k(k + 128);
-
- // num_f128 = sin(k*pi/128) + tan(y) * cos(k*pi/128)
- Float128 num_f128 =
- fputil::quick_add(sin_k_f128, fputil::quick_mul(cos_k_f128, tan_u));
- // den_f128 = cos(k*pi/128) - tan(y) * sin(k*pi/128)
- Float128 den_f128 =
- fputil::quick_add(cos_k_f128, fputil::quick_mul(msin_k_f128, tan_u));
-
- // tan(x) = (sin(k*pi/128) + tan(y) * cos(k*pi/128)) /
- // / (cos(k*pi/128) - tan(y) * sin(k*pi/128))
- // TODO: The initial seed 1.0/den_dd.hi for Newton-Raphson reciprocal can be
- // reused from DoubleDouble fputil::div in the fast pass.
- Float128 result = newton_raphson_div(num_f128, den_f128, 1.0 / den_dd.hi);
-
- // TODO: Add assertion if Ziv's accuracy tests fail in debug mode.
- // https://github.com/llvm/llvm-project/issues/96452.
- return static_cast<double>(result);
-
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-}
+LLVM_LIBC_FUNCTION(double, tan, (double x)) { return math::tan(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp
index a8c557b..aee5a6c 100644
--- a/libc/src/math/generic/tanf.cpp
+++ b/libc/src/math/generic/tanf.cpp
@@ -7,146 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/math/tanf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/nearest_integer.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
-#include "src/__support/math/sincosf_utils.h"
+#include "src/__support/math/tanf.h"
namespace LIBC_NAMESPACE_DECL {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-// Exceptional cases for tanf.
-constexpr size_t N_EXCEPTS = 6;
-
-constexpr fputil::ExceptValues<float, N_EXCEPTS> TANF_EXCEPTS{{
- // (inputs, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.ada6aap27, tan(x) = 0x1.e80304p-3 (RZ)
- {0x4d56d355, 0x3e740182, 1, 0, 0},
- // x = 0x1.862064p33, tan(x) = -0x1.8dee56p-3 (RZ)
- {0x50431032, 0xbe46f72b, 0, 1, 1},
- // x = 0x1.af61dap48, tan(x) = 0x1.60d1c6p-2 (RZ)
- {0x57d7b0ed, 0x3eb068e3, 1, 0, 1},
- // x = 0x1.0088bcp52, tan(x) = 0x1.ca1edp0 (RZ)
- {0x5980445e, 0x3fe50f68, 1, 0, 0},
- // x = 0x1.f90dfcp72, tan(x) = 0x1.597f9cp-1 (RZ)
- {0x63fc86fe, 0x3f2cbfce, 1, 0, 0},
- // x = 0x1.a6ce12p86, tan(x) = -0x1.c5612ep-1 (RZ)
- {0x6ad36709, 0xbf62b097, 0, 1, 0},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
- using FPBits = typename fputil::FPBits<float>;
- FPBits xbits(x);
- uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU;
-
- // |x| < pi/32
- if (LIBC_UNLIKELY(x_abs <= 0x3dc9'0fdbU)) {
- double xd = static_cast<double>(x);
-
- // |x| < 0x1.0p-12f
- if (LIBC_UNLIKELY(x_abs < 0x3980'0000U)) {
- if (LIBC_UNLIKELY(x_abs == 0U)) {
- // For signed zeros.
- return x;
- }
- // When |x| < 2^-12, the relative error of the approximation tan(x) ~ x
- // is:
- // |tan(x) - x| / |tan(x)| < |x^3| / (3|x|)
- // = x^2 / 3
- // < 2^-25
- // < epsilon(1)/2.
- // So the correctly rounded values of tan(x) are:
- // = x + sign(x)*eps(x) if rounding mode = FE_UPWARD and x is positive,
- // or (rounding mode = FE_DOWNWARD and x is
- // negative),
- // = x otherwise.
- // To simplify the rounding decision and make it more efficient, we use
- // fma(x, 2^-25, x) instead.
- // Note: to use the formula x + 2^-25*x to decide the correct rounding, we
- // do need fma(x, 2^-25, x) to prevent underflow caused by 2^-25*x when
- // |x| < 2^-125. For targets without FMA instructions, we simply use
- // double for intermediate results as it is more efficient than using an
- // emulated version of FMA.
-#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
- return fputil::multiply_add(x, 0x1.0p-25f, x);
-#else
- return static_cast<float>(fputil::multiply_add(xd, 0x1.0p-25, xd));
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
- }
-
- // |x| < pi/32
- double xsq = xd * xd;
-
- // Degree-9 minimax odd polynomial of tan(x) generated by Sollya with:
- // > P = fpminimax(tan(x)/x, [|0, 2, 4, 6, 8|], [|1, D...|], [0, pi/32]);
- double result =
- fputil::polyeval(xsq, 1.0, 0x1.555555553d022p-2, 0x1.111111ce442c1p-3,
- 0x1.ba180a6bbdecdp-5, 0x1.69c0a88a0b71fp-6);
- return static_cast<float>(xd * result);
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- bool x_sign = xbits.uintval() >> 31;
- // Check for exceptional values
- if (LIBC_UNLIKELY(x_abs == 0x3f8a1f62U)) {
- // |x| = 0x1.143ec4p0
- float sign = x_sign ? -1.0f : 1.0f;
-
- // volatile is used to prevent compiler (gcc) from optimizing the
- // computation, making the results incorrect in different rounding modes.
- volatile float tmp = 0x1.ddf9f4p0f;
- tmp = fputil::multiply_add(sign, tmp, sign * 0x1.1p-24f);
-
- return tmp;
- }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- // |x| > 0x1.ada6a8p+27f
- if (LIBC_UNLIKELY(x_abs > 0x4d56'd354U)) {
- // Inf or NaN
- if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- if (x_abs == 0x7f80'0000U) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- }
- return x + FPBits::quiet_nan().get_val();
- }
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- // Other large exceptional values
- if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign);
- LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- }
-
- // For |x| >= pi/32, we use the definition of tan(x) function:
- // tan(x) = sin(x) / cos(x)
- // The we follow the same computations of sin(x) and cos(x) as sinf, cosf,
- // and sincosf.
-
- double xd = static_cast<double>(x);
- double sin_k, cos_k, sin_y, cosm1_y;
-
- sincosf_eval(xd, x_abs, sin_k, cos_k, sin_y, cosm1_y);
- // tan(x) = sin(x) / cos(x)
- // = (sin_y * cos_k + cos_y * sin_k) / (cos_y * cos_k - sin_y * sin_k)
- using fputil::multiply_add;
- return static_cast<float>(
- multiply_add(sin_y, cos_k, multiply_add(cosm1_y, sin_k, sin_k)) /
- multiply_add(sin_y, -sin_k, multiply_add(cosm1_y, cos_k, cos_k)));
-}
+LLVM_LIBC_FUNCTION(float, tanf, (float x)) { return math::tanf(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pthread/pthread_getattr_np.h b/libc/src/pthread/pthread_getattr_np.h
new file mode 100644
index 0000000..7dada95
--- /dev/null
+++ b/libc/src/pthread/pthread_getattr_np.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for pthread_getattr_np function -*- 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_PTHREAD_PTHREAD_GETATTR_NP_H
+#define LLVM_LIBC_SRC_PTHREAD_PTHREAD_GETATTR_NP_H
+
+#include "src/__support/macros/config.h"
+#include <pthread.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int pthread_getattr_np(pthread_t, pthread_attr_t *);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_GETATTR_NP_H
diff --git a/libc/src/spawn/linux/posix_spawn.cpp b/libc/src/spawn/linux/posix_spawn.cpp
index fe82ba2..f058158 100644
--- a/libc/src/spawn/linux/posix_spawn.cpp
+++ b/libc/src/spawn/linux/posix_spawn.cpp
@@ -44,7 +44,7 @@ cpp::optional<int> open(const char *path, int oflags, mode_t mode) {
int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_openat, AT_FDCWD, path, oflags,
mode);
#endif
- if (fd > 0)
+ if (fd >= 0)
return fd;
// The open function is called as part of the child process' preparatory
// steps. If an open fails, the child process just exits. So, unlike
diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 624129b..ae93cc75 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -43,6 +43,22 @@ if(NOT TARGET ${target_error_mapper})
set(target_error_mapper libc.src.stdio.printf_core.generic.error_mapper)
endif()
+if(LIBC_CONF_PRINTF_DISABLE_WIDE)
+ set(wchar_deps "")
+ set(parser_wchar_deps "")
+else()
+ set(wchar_deps
+ libc.hdr.types.wchar_t
+ libc.hdr.types.wint_t
+ libc.hdr.wchar_macros
+ libc.src.__support.wchar.wcrtomb
+ libc.src.__support.wchar.mbstate
+ )
+ set(parser_wchar_deps
+ libc.hdr.types.wint_t
+ )
+endif()
+
add_header_library(
printf_config
HDRS
@@ -76,6 +92,7 @@ add_header_library(
libc.src.__support.CPP.string_view
libc.src.__support.CPP.type_traits
libc.src.__support.common
+ ${parser_wchar_deps}
)
add_header_library(
@@ -111,6 +128,7 @@ add_header_library(
.printf_config
.writer
libc.include.inttypes
+ libc.hdr.limits_macros
libc.src.__support.big_int
libc.src.__support.common
libc.src.__support.CPP.limits
@@ -125,6 +143,7 @@ add_header_library(
libc.src.__support.uint128
libc.src.__support.StringUtil.error_to_string
libc.src.string.memory_utils.inline_memcpy
+ ${wchar_deps}
)
add_header_library(
diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h
index fd2eb25..e4792c3 100644
--- a/libc/src/stdio/printf_core/char_converter.h
+++ b/libc/src/stdio/printf_core/char_converter.h
@@ -1,4 +1,4 @@
-//===-- String Converter for printf -----------------------------*- C++ -*-===//
+//===-- Character Converter for printf --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -9,6 +9,15 @@
#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CHAR_CONVERTER_H
#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CHAR_CONVERTER_H
+#ifndef LIBC_COPT_PRINTF_DISABLE_WIDE
+#include "hdr/types/wchar_t.h"
+#include "hdr/types/wint_t.h"
+#include "hdr/wchar_macros.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/wcrtomb.h"
+#endif // LIBC_COPT_PRINTF_DISABLE_WIDE
+
+#include "hdr/limits_macros.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/converter_utils.h"
#include "src/stdio/printf_core/core_structs.h"
@@ -20,12 +29,41 @@ namespace printf_core {
template <WriteMode write_mode>
LIBC_INLINE int convert_char(Writer<write_mode> *writer,
const FormatSection &to_conv) {
- char c = static_cast<char>(to_conv.conv_val_raw);
- constexpr int STRING_LEN = 1;
+ char buffer[MB_LEN_MAX];
+ size_t write_size = 0;
+
+ if (to_conv.length_modifier == LengthModifier::l) {
+#ifndef LIBC_COPT_PRINTF_DISABLE_WIDE
+ wint_t wi = static_cast<wint_t>(to_conv.conv_val_raw);
+
+ if (wi == WEOF) {
+ return ILLEGAL_WIDE_CHAR;
+ }
+
+ internal::mbstate mbstate;
+ wchar_t wc = static_cast<wchar_t>(wi);
+ auto ret = internal::wcrtomb(buffer, wc, &mbstate);
+
+ if (!ret.has_value()) {
+ return MB_CONVERSION_ERROR;
+ }
+
+ write_size = ret.value();
+#else
+ // If wide characters are disabled, treat the 'l' modifier as a no-op.
+ buffer[0] = static_cast<char>(to_conv.conv_val_raw);
+ write_size = 1;
+
+#endif // LIBC_COPT_PRINTF_DISABLE_WIDE
+ } else {
+ buffer[0] = static_cast<char>(to_conv.conv_val_raw);
+ write_size = 1;
+ }
- size_t padding_spaces =
- to_conv.min_width > STRING_LEN ? to_conv.min_width - STRING_LEN : 0;
+ size_t padding_spaces = to_conv.min_width > static_cast<int>(write_size)
+ ? to_conv.min_width - static_cast<int>(write_size)
+ : 0;
// If the padding is on the left side, write the spaces first.
if (padding_spaces > 0 &&
@@ -33,7 +71,7 @@ LIBC_INLINE int convert_char(Writer<write_mode> *writer,
RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_spaces));
}
- RET_IF_RESULT_NEGATIVE(writer->write(c));
+ RET_IF_RESULT_NEGATIVE(writer->write({buffer, write_size}));
// If the padding is on the right side, write the spaces last.
if (padding_spaces > 0 &&
diff --git a/libc/src/stdio/printf_core/core_structs.h b/libc/src/stdio/printf_core/core_structs.h
index 0d41f22..d93fa96 100644
--- a/libc/src/stdio/printf_core/core_structs.h
+++ b/libc/src/stdio/printf_core/core_structs.h
@@ -142,6 +142,8 @@ constexpr int INT_CONVERSION_ERROR = -1004;
constexpr int FIXED_POINT_CONVERSION_ERROR = -1005;
constexpr int ALLOCATION_ERROR = -1006;
constexpr int OVERFLOW_ERROR = -1007;
+constexpr int ILLEGAL_WIDE_CHAR = -1008;
+constexpr int MB_CONVERSION_ERROR = -1009;
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/linux/error_mapper.h b/libc/src/stdio/printf_core/linux/error_mapper.h
index 3c2fe66..3449f12 100644
--- a/libc/src/stdio/printf_core/linux/error_mapper.h
+++ b/libc/src/stdio/printf_core/linux/error_mapper.h
@@ -40,6 +40,9 @@ LIBC_INLINE static int internal_error_to_errno(int internal_error) {
return ENOMEM;
case OVERFLOW_ERROR:
return EOVERFLOW;
+ case ILLEGAL_WIDE_CHAR:
+ case MB_CONVERSION_ERROR:
+ return EILSEQ;
default:
LIBC_ASSERT(
false &&
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index cef9b1a..a3b6299 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -27,6 +27,9 @@
#ifndef LIBC_COPT_PRINTF_DISABLE_STRERROR
#include "src/__support/libc_errno.h"
#endif // LIBC_COPT_PRINTF_DISABLE_STRERROR
+#ifndef LIBC_COPT_PRINTF_DISABLE_WIDE
+#include "hdr/types/wint_t.h"
+#endif // LIBC_COPT_PRINTF_DISABLE_WIDE
namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
@@ -73,9 +76,9 @@ template <typename ArgProvider> class Parser {
ArgProvider args_cur;
#ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
- // args_start stores the start of the va_args, which is allows getting the
- // value of arguments that have already been passed. args_index is tracked so
- // that we know which argument args_cur is on.
+ // args_start stores the start of the va_args, which helps in getting the
+ // number of arguments that have already been passed. args_index is tracked
+ // so that we know which argument args_cur is on.
ArgProvider args_start;
size_t args_index = 1;
@@ -173,7 +176,17 @@ public:
section.has_conv = true;
break;
case ('c'):
- WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, int, conv_index);
+ if (section.length_modifier == LengthModifier::l) {
+#ifdef LIBC_COPT_PRINTF_DISABLE_WIDE
+ using WideCharArgType = int;
+#else
+ using WideCharArgType = wint_t;
+#endif // LIBC_COPT_PRINTF_DISABLE_WIDE
+ WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, WideCharArgType,
+ conv_index);
+ } else {
+ WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, int, conv_index);
+ }
break;
case ('d'):
case ('i'):
@@ -574,7 +587,16 @@ private:
conv_size = type_desc_from_type<void>();
break;
case ('c'):
- conv_size = type_desc_from_type<int>();
+ if (lm == LengthModifier::l) {
+#ifdef LIBC_COPT_PRINTF_DISABLE_WIDE
+ using WideCharArgType = int;
+#else
+ using WideCharArgType = wint_t;
+#endif // LIBC_COPT_PRINTF_DISABLE_WIDE
+ conv_size = type_desc_from_type<WideCharArgType>();
+ } else {
+ conv_size = type_desc_from_type<int>();
+ }
break;
case ('d'):
case ('i'):
diff --git a/libc/src/string/memory_utils/inline_memcpy.h b/libc/src/string/memory_utils/inline_memcpy.h
index 13975e6..931d282 100644
--- a/libc/src/string/memory_utils/inline_memcpy.h
+++ b/libc/src/string/memory_utils/inline_memcpy.h
@@ -31,7 +31,7 @@
#elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
#include "src/string/memory_utils/riscv/inline_memcpy.h"
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY inline_memcpy_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_GPU)
+#elif defined(LIBC_TARGET_ARCH_IS_GPU) || defined(LIBC_TARGET_ARCH_IS_WASM)
#include "src/string/memory_utils/generic/builtin.h"
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY inline_memcpy_builtin
#else
diff --git a/libc/src/string/memory_utils/inline_memmove.h b/libc/src/string/memory_utils/inline_memmove.h
index 71a28c32..3162766 100644
--- a/libc/src/string/memory_utils/inline_memmove.h
+++ b/libc/src/string/memory_utils/inline_memmove.h
@@ -29,7 +29,7 @@
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_SMALL_SIZE \
inline_memmove_no_small_size
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_FOLLOW_UP inline_memmove_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_GPU)
+#elif defined(LIBC_TARGET_ARCH_IS_GPU) || defined(LIBC_TARGET_ARCH_IS_WASM)
#include "src/string/memory_utils/generic/builtin.h"
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_SMALL_SIZE \
inline_memmove_no_small_size
diff --git a/libc/src/string/memory_utils/inline_memset.h b/libc/src/string/memory_utils/inline_memset.h
index e41bdb6..da85f09 100644
--- a/libc/src/string/memory_utils/inline_memset.h
+++ b/libc/src/string/memory_utils/inline_memset.h
@@ -27,7 +27,7 @@
#elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
#include "src/string/memory_utils/riscv/inline_memset.h"
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_GPU)
+#elif defined(LIBC_TARGET_ARCH_IS_GPU) || defined(LIBC_TARGET_ARCH_IS_WASM)
#include "src/string/memory_utils/generic/builtin.h"
#define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_builtin
#else