Skip to content

Commit aa95aa6

Browse files
authored
[libc][math][c23] Add C23 math functions ilogbf128, logbf128, and llogb(f|l|f128). (#82144)
1 parent b50bcc7 commit aa95aa6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+674
-185
lines changed

libc/config/gpu/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ set(TARGET_LIBM_ENTRYPOINTS
239239
libc.src.math.ilogbf
240240
libc.src.math.ldexp
241241
libc.src.math.ldexpf
242+
libc.src.math.llogb
243+
libc.src.math.llogbf
242244
libc.src.math.llrint
243245
libc.src.math.llrintf
244246
libc.src.math.llround

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ set(TARGET_LIBM_ENTRYPOINTS
341341
libc.src.math.ilogb
342342
libc.src.math.ilogbf
343343
libc.src.math.ilogbl
344+
libc.src.math.llogb
345+
libc.src.math.llogbf
346+
libc.src.math.llogbl
344347
libc.src.math.llrint
345348
libc.src.math.llrintf
346349
libc.src.math.llrintl
@@ -422,7 +425,10 @@ if(LIBC_COMPILER_HAS_FLOAT128)
422425
libc.src.math.fmaxf128
423426
libc.src.math.fminf128
424427
libc.src.math.frexpf128
428+
libc.src.math.ilogbf128
425429
libc.src.math.ldexpf128
430+
libc.src.math.llogbf128
431+
libc.src.math.logbf128
426432
libc.src.math.roundf128
427433
libc.src.math.sqrtf128
428434
libc.src.math.truncf128

libc/config/linux/arm/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ set(TARGET_LIBM_ENTRYPOINTS
217217
libc.src.math.ldexp
218218
libc.src.math.ldexpf
219219
libc.src.math.ldexpl
220+
libc.src.math.llogb
221+
libc.src.math.llogbf
222+
libc.src.math.llogbl
220223
libc.src.math.llrint
221224
libc.src.math.llrintf
222225
libc.src.math.llrintl

libc/config/linux/riscv/entrypoints.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ set(TARGET_LIBM_ENTRYPOINTS
353353
libc.src.math.ldexp
354354
libc.src.math.ldexpf
355355
libc.src.math.ldexpl
356+
libc.src.math.llogb
357+
libc.src.math.llogbf
358+
libc.src.math.llogbl
356359
libc.src.math.llrint
357360
libc.src.math.llrintf
358361
libc.src.math.llrintl
@@ -431,7 +434,10 @@ if(LIBC_COMPILER_HAS_FLOAT128)
431434
libc.src.math.fmaxf128
432435
libc.src.math.fminf128
433436
libc.src.math.frexpf128
437+
libc.src.math.ilogbf128
434438
libc.src.math.ldexpf128
439+
libc.src.math.llogbf128
440+
libc.src.math.logbf128
435441
libc.src.math.roundf128
436442
libc.src.math.sqrtf128
437443
libc.src.math.truncf128

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ set(TARGET_LIBM_ENTRYPOINTS
365365
libc.src.math.ldexp
366366
libc.src.math.ldexpf
367367
libc.src.math.ldexpl
368+
libc.src.math.llogb
369+
libc.src.math.llogbf
370+
libc.src.math.llogbl
368371
libc.src.math.llrint
369372
libc.src.math.llrintf
370373
libc.src.math.llrintl
@@ -445,7 +448,10 @@ if(LIBC_COMPILER_HAS_FLOAT128)
445448
libc.src.math.fmaxf128
446449
libc.src.math.fminf128
447450
libc.src.math.frexpf128
451+
libc.src.math.ilogbf128
448452
libc.src.math.ldexpf128
453+
libc.src.math.llogbf128
454+
libc.src.math.logbf128
449455
libc.src.math.roundf128
450456
libc.src.math.sqrtf128
451457
libc.src.math.truncf128

libc/docs/math/index.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ Basic Operations
185185
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
186186
| ilogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
187187
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
188+
| ilogf128 | |check| | |check| | | |check| | | | | | | | | |
189+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
188190
| ldexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
189191
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
190192
| ldexpf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
@@ -193,6 +195,14 @@ Basic Operations
193195
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
194196
| ldexpf128 | |check| | |check| | | |check| | | | | | | | | |
195197
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
198+
| llogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
199+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
200+
| llogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
201+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
202+
| llogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
203+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
204+
| llogf128 | |check| | |check| | | |check| | | | | | | | | |
205+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
196206
| llrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
197207
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
198208
| llrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
@@ -211,6 +221,8 @@ Basic Operations
211221
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
212222
| logbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
213223
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
224+
| logf128 | |check| | |check| | | |check| | | | | | | | | |
225+
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
214226
| lrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
215227
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
216228
| lrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |

libc/include/llvm-libc-macros/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ add_macro_header(
8383
math_macros
8484
HDR
8585
math-macros.h
86+
DEPENDS
87+
.limits_macros
8688
)
8789

8890
add_macro_header(

libc/include/llvm-libc-macros/math-macros.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,28 @@
99
#ifndef __LLVM_LIBC_MACROS_MATH_MACROS_H
1010
#define __LLVM_LIBC_MACROS_MATH_MACROS_H
1111

12+
#include "limits-macros.h"
13+
1214
#define MATH_ERRNO 1
1315
#define MATH_ERREXCEPT 2
1416

1517
#define HUGE_VAL __builtin_huge_val()
1618
#define INFINITY __builtin_inf()
1719
#define NAN __builtin_nanf("")
1820

19-
#define FP_ILOGB0 (-__INT_MAX__ - 1)
20-
#define FP_ILOGBNAN __INT_MAX__
21+
#define FP_ILOGB0 (-INT_MAX - 1)
22+
#define FP_ILOGBNAN INT_MAX
23+
24+
#define FP_LLOGB0 (-LONG_MAX - 1)
25+
#define FP_LLOGBNAN LONG_MAX
2126

2227
#define isfinite(x) __builtin_isfinite(x)
2328
#define isinf(x) __builtin_isinf(x)
2429
#define isnan(x) __builtin_isnan(x)
2530

2631
#ifdef __FAST_MATH__
2732
#define math_errhandling 0
28-
#elif defined __NO_MATH_ERRNO__
33+
#elif defined(__NO_MATH_ERRNO__)
2934
#define math_errhandling (MATH_ERREXCEPT)
3035
#else
3136
#define math_errhandling (MATH_ERRNO | MATH_ERREXCEPT)

libc/spec/stdc.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,12 @@ def StdC : StandardSpec<"stdc"> {
414414
FunctionSpec<"ilogb", RetValSpec<IntType>, [ArgSpec<DoubleType>]>,
415415
FunctionSpec<"ilogbf", RetValSpec<IntType>, [ArgSpec<FloatType>]>,
416416
FunctionSpec<"ilogbl", RetValSpec<IntType>, [ArgSpec<LongDoubleType>]>,
417+
GuardedFunctionSpec<"ilogbf128", RetValSpec<IntType>, [ArgSpec<Float128Type>], "LIBC_COMPILER_HAS_FLOAT128">,
418+
419+
FunctionSpec<"llogb", RetValSpec<LongType>, [ArgSpec<DoubleType>]>,
420+
FunctionSpec<"llogbf", RetValSpec<LongType>, [ArgSpec<FloatType>]>,
421+
FunctionSpec<"llogbl", RetValSpec<LongType>, [ArgSpec<LongDoubleType>]>,
422+
GuardedFunctionSpec<"llogbf128", RetValSpec<LongType>, [ArgSpec<Float128Type>], "LIBC_COMPILER_HAS_FLOAT128">,
417423

418424
FunctionSpec<"ldexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
419425
FunctionSpec<"ldexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
@@ -435,6 +441,7 @@ def StdC : StandardSpec<"stdc"> {
435441
FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
436442
FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
437443
FunctionSpec<"logbl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
444+
GuardedFunctionSpec<"logbf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_COMPILER_HAS_FLOAT128">,
438445

439446
FunctionSpec<"modf", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoublePtr>]>,
440447
FunctionSpec<"modff", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatPtr>]>,

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -71,54 +71,80 @@ LIBC_INLINE T copysign(T x, T y) {
7171
return xbits.get_val();
7272
}
7373

74-
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
75-
LIBC_INLINE int ilogb(T x) {
76-
// TODO: Raise appropriate floating point exceptions and set errno to the
77-
// an appropriate error value wherever relevant.
78-
FPBits<T> bits(x);
79-
if (bits.is_zero()) {
80-
return FP_ILOGB0;
81-
} else if (bits.is_nan()) {
82-
return FP_ILOGBNAN;
83-
} else if (bits.is_inf()) {
84-
return INT_MAX;
74+
template <typename T> struct IntLogbConstants;
75+
76+
template <> struct IntLogbConstants<int> {
77+
LIBC_INLINE_VAR static constexpr int FP_LOGB0 = FP_ILOGB0;
78+
LIBC_INLINE_VAR static constexpr int FP_LOGBNAN = FP_ILOGBNAN;
79+
LIBC_INLINE_VAR static constexpr int T_MAX = INT_MAX;
80+
LIBC_INLINE_VAR static constexpr int T_MIN = INT_MIN;
81+
};
82+
83+
template <> struct IntLogbConstants<long> {
84+
LIBC_INLINE_VAR static constexpr long FP_LOGB0 = FP_ILOGB0;
85+
LIBC_INLINE_VAR static constexpr long FP_LOGBNAN = FP_ILOGBNAN;
86+
LIBC_INLINE_VAR static constexpr long T_MAX = LONG_MAX;
87+
LIBC_INLINE_VAR static constexpr long T_MIN = LONG_MIN;
88+
};
89+
90+
template <typename T, typename U>
91+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<U>, T>
92+
intlogb(U x) {
93+
FPBits<U> bits(x);
94+
if (LIBC_UNLIKELY(bits.is_zero() || bits.is_inf_or_nan())) {
95+
set_errno_if_required(EDOM);
96+
raise_except_if_required(FE_INVALID);
97+
98+
if (bits.is_zero())
99+
return IntLogbConstants<T>::FP_LOGB0;
100+
if (bits.is_nan())
101+
return IntLogbConstants<T>::FP_LOGBNAN;
102+
// bits is inf.
103+
return IntLogbConstants<T>::T_MAX;
85104
}
86105

87-
NormalFloat<T> normal(bits);
106+
DyadicFloat<FPBits<U>::STORAGE_LEN> normal(bits.get_val());
107+
int exponent = normal.get_unbiased_exponent();
88108
// The C standard does not specify the return value when an exponent is
89109
// out of int range. However, XSI conformance required that INT_MAX or
90110
// INT_MIN are returned.
91111
// NOTE: It is highly unlikely that exponent will be out of int range as
92112
// the exponent is only 15 bits wide even for the 128-bit floating point
93113
// format.
94-
if (normal.exponent > INT_MAX)
95-
return INT_MAX;
96-
else if (normal.exponent < INT_MIN)
97-
return INT_MIN;
98-
else
99-
return normal.exponent;
114+
if (LIBC_UNLIKELY(exponent > IntLogbConstants<T>::T_MAX ||
115+
exponent < IntLogbConstants<T>::T_MIN)) {
116+
set_errno_if_required(ERANGE);
117+
raise_except_if_required(FE_INVALID);
118+
return exponent > 0 ? IntLogbConstants<T>::T_MAX
119+
: IntLogbConstants<T>::T_MIN;
120+
}
121+
122+
return static_cast<T>(exponent);
100123
}
101124

102125
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
103-
LIBC_INLINE T logb(T x) {
126+
LIBC_INLINE constexpr T logb(T x) {
104127
FPBits<T> bits(x);
105-
if (bits.is_zero()) {
106-
// TODO(Floating point exception): Raise div-by-zero exception.
107-
// TODO(errno): POSIX requires setting errno to ERANGE.
108-
return FPBits<T>::inf(Sign::NEG).get_val();
109-
} else if (bits.is_nan()) {
110-
return x;
111-
} else if (bits.is_inf()) {
112-
// Return positive infinity.
128+
if (LIBC_UNLIKELY(bits.is_zero() || bits.is_inf_or_nan())) {
129+
if (bits.is_nan())
130+
return x;
131+
132+
raise_except_if_required(FE_DIVBYZERO);
133+
134+
if (bits.is_zero()) {
135+
set_errno_if_required(ERANGE);
136+
return FPBits<T>::inf(Sign::NEG).get_val();
137+
}
138+
// bits is inf.
113139
return FPBits<T>::inf().get_val();
114140
}
115141

116-
NormalFloat<T> normal(bits);
117-
return static_cast<T>(normal.exponent);
142+
DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());
143+
return static_cast<T>(normal.get_unbiased_exponent());
118144
}
119145

120146
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
121-
LIBC_INLINE T ldexp(T x, int exp) {
147+
LIBC_INLINE constexpr T ldexp(T x, int exp) {
122148
FPBits<T> bits(x);
123149
if (LIBC_UNLIKELY((exp == 0) || bits.is_zero() || bits.is_inf_or_nan()))
124150
return x;

libc/src/__support/FPUtil/dyadic_float.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ template <size_t Bits> struct DyadicFloat {
7979
return *this;
8080
}
8181

82+
// Assume that it is already normalized. Output the unbiased exponent.
83+
LIBC_INLINE constexpr int get_unbiased_exponent() const {
84+
return exponent + (Bits - 1);
85+
}
86+
8287
// Assume that it is already normalized.
8388
// Output is rounded correctly with respect to the current rounding mode.
8489
template <typename T,

libc/src/math/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ add_math_entrypoint_object(hypotf)
157157
add_math_entrypoint_object(ilogb)
158158
add_math_entrypoint_object(ilogbf)
159159
add_math_entrypoint_object(ilogbl)
160+
add_math_entrypoint_object(ilogbf128)
161+
162+
add_math_entrypoint_object(llogb)
163+
add_math_entrypoint_object(llogbf)
164+
add_math_entrypoint_object(llogbl)
165+
add_math_entrypoint_object(llogbf128)
160166

161167
add_math_entrypoint_object(ldexp)
162168
add_math_entrypoint_object(ldexpf)
@@ -178,6 +184,7 @@ add_math_entrypoint_object(logf)
178184
add_math_entrypoint_object(logb)
179185
add_math_entrypoint_object(logbf)
180186
add_math_entrypoint_object(logbl)
187+
add_math_entrypoint_object(logbf128)
181188

182189
add_math_entrypoint_object(llrint)
183190
add_math_entrypoint_object(llrintf)

0 commit comments

Comments
 (0)