Skip to content

Commit 0cdb0b7

Browse files
authored
[libc][math][c23] Add fmodf16 C23 math function (#94629)
Part of #93566.
1 parent 06e12b4 commit 0cdb0b7

File tree

16 files changed

+193
-46
lines changed

16 files changed

+193
-46
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
515515
libc.src.math.fminimum_magf16
516516
libc.src.math.fminimum_mag_numf16
517517
libc.src.math.fminimum_numf16
518+
libc.src.math.fmodf16
518519
libc.src.math.fromfpf16
519520
libc.src.math.fromfpxf16
520521
libc.src.math.llrintf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
547547
libc.src.math.fminimum_magf16
548548
libc.src.math.fminimum_mag_numf16
549549
libc.src.math.fminimum_numf16
550+
libc.src.math.fmodf16
550551
libc.src.math.fromfpf16
551552
libc.src.math.fromfpxf16
552553
libc.src.math.llrintf16

libc/docs/math/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ Basic Operations
156156
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
157157
| fminimum_num | |check| | |check| | |check| | |check| | |check| | 7.12.12.9 | F.10.9.5 |
158158
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
159-
| fmod | |check| | |check| | |check| | | |check| | 7.12.10.1 | F.10.7.1 |
159+
| fmod | |check| | |check| | |check| | |check| | |check| | 7.12.10.1 | F.10.7.1 |
160160
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
161161
| fmul | N/A | | | N/A | | 7.12.14.3 | F.10.11 |
162162
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/spec/stdc.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ def StdC : StandardSpec<"stdc"> {
478478
FunctionSpec<"fmod", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
479479
FunctionSpec<"fmodf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
480480
FunctionSpec<"fmodl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
481+
GuardedFunctionSpec<"fmodf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
481482
GuardedFunctionSpec<"fmodf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,
482483

483484
FunctionSpec<"frexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntPtr>]>,

libc/src/__support/FPUtil/FPBits.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
744744
if (LIBC_LIKELY(ep >= 0)) {
745745
// Implicit number bit will be removed by mask
746746
result.set_significand(number);
747-
result.set_biased_exponent(ep + 1);
747+
result.set_biased_exponent(static_cast<StorageType>(ep + 1));
748748
} else {
749749
result.set_significand(number >> -ep);
750750
}

libc/src/__support/FPUtil/generic/FMod.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ class FMod {
210210
e_x - e_y <= int(FPB::EXP_LEN))) {
211211
StorageType m_x = sx.get_explicit_mantissa();
212212
StorageType m_y = sy.get_explicit_mantissa();
213-
StorageType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y;
213+
StorageType d = (e_x == e_y)
214+
? (m_x - m_y)
215+
: static_cast<StorageType>(m_x << (e_x - e_y)) % m_y;
214216
if (d == 0)
215217
return FPB::zero();
216218
// iy - 1 because of "zero power" for number with power 1

libc/src/math/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ add_math_entrypoint_object(fminimum_mag_numf128)
183183
add_math_entrypoint_object(fmod)
184184
add_math_entrypoint_object(fmodf)
185185
add_math_entrypoint_object(fmodl)
186+
add_math_entrypoint_object(fmodf16)
186187
add_math_entrypoint_object(fmodf128)
187188

188189
add_math_entrypoint_object(frexp)

libc/src/math/fmodf16.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for fmodf16 -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_MATH_FMODF16_H
10+
#define LLVM_LIBC_SRC_MATH_FMODF16_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 fmodf16(float16 x, float16 y);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_FMODF16_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,6 +2887,19 @@ add_entrypoint_object(
28872887
-O3
28882888
)
28892889

2890+
add_entrypoint_object(
2891+
fmodf16
2892+
SRCS
2893+
fmodf16.cpp
2894+
HDRS
2895+
../fmodf16.h
2896+
DEPENDS
2897+
libc.src.__support.macros.properties.types
2898+
libc.src.__support.FPUtil.generic.fmod
2899+
COMPILE_OPTIONS
2900+
-O3
2901+
)
2902+
28902903
add_entrypoint_object(
28912904
fmodf128
28922905
SRCS

libc/src/math/generic/fmodf16.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of fmodf16 function --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/math/fmodf16.h"
10+
#include "src/__support/FPUtil/generic/FMod.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, fmodf16, (float16 x, float16 y)) {
16+
return fputil::generic::FMod<float16, uint32_t>::eval(x, y);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "src/__support/FPUtil/FPBits.h"
1010
#include "test/src/math/performance_testing/Timer.h"
1111

12+
#include <cstddef>
1213
#include <fstream>
1314

1415
namespace LIBC_NAMESPACE {
@@ -25,21 +26,26 @@ template <typename T> class BinaryOpSingleOutputPerf {
2526

2627
static void run_perf_in_range(Func myFunc, Func otherFunc,
2728
StorageType startingBit, StorageType endingBit,
28-
StorageType N, std::ofstream &log) {
29+
size_t N, size_t rounds, std::ofstream &log) {
30+
if (endingBit - startingBit < N)
31+
N = endingBit - startingBit;
32+
2933
auto runner = [=](Func func) {
3034
volatile T result;
3135
if (endingBit < startingBit) {
3236
return;
3337
}
3438

3539
StorageType step = (endingBit - startingBit) / N;
36-
for (StorageType bitsX = startingBit, bitsY = endingBit;;
37-
bitsX += step, bitsY -= step) {
38-
T x = FPBits(bitsX).get_val();
39-
T y = FPBits(bitsY).get_val();
40-
result = func(x, y);
41-
if (endingBit - bitsX < step) {
42-
break;
40+
for (size_t i = 0; i < rounds; i++) {
41+
for (StorageType bitsX = startingBit, bitsY = endingBit;;
42+
bitsX += step, bitsY -= step) {
43+
T x = FPBits(bitsX).get_val();
44+
T y = FPBits(bitsY).get_val();
45+
result = func(x, y);
46+
if (endingBit - bitsX < step) {
47+
break;
48+
}
4349
}
4450
}
4551
};
@@ -49,7 +55,7 @@ template <typename T> class BinaryOpSingleOutputPerf {
4955
runner(myFunc);
5056
timer.stop();
5157

52-
double my_average = static_cast<double>(timer.nanoseconds()) / N;
58+
double my_average = static_cast<double>(timer.nanoseconds()) / N / rounds;
5359
log << "-- My function --\n";
5460
log << " Total time : " << timer.nanoseconds() << " ns \n";
5561
log << " Average runtime : " << my_average << " ns/op \n";
@@ -60,7 +66,8 @@ template <typename T> class BinaryOpSingleOutputPerf {
6066
runner(otherFunc);
6167
timer.stop();
6268

63-
double other_average = static_cast<double>(timer.nanoseconds()) / N;
69+
double other_average =
70+
static_cast<double>(timer.nanoseconds()) / N / rounds;
6471
log << "-- Other function --\n";
6572
log << " Total time : " << timer.nanoseconds() << " ns \n";
6673
log << " Average runtime : " << other_average << " ns/op \n";
@@ -71,22 +78,24 @@ template <typename T> class BinaryOpSingleOutputPerf {
7178
log << " Mine / Other's : " << my_average / other_average << " \n";
7279
}
7380

74-
static void run_perf(Func myFunc, Func otherFunc, const char *logFile) {
81+
static void run_perf(Func myFunc, Func otherFunc, int rounds,
82+
const char *logFile) {
7583
std::ofstream log(logFile);
7684
log << " Performance tests with inputs in denormal range:\n";
7785
run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0),
7886
/* endingBit= */ FPBits::max_subnormal().uintval(),
79-
10'000'001, log);
87+
1'000'001, rounds, log);
8088
log << "\n Performance tests with inputs in normal range:\n";
8189
run_perf_in_range(myFunc, otherFunc,
8290
/* startingBit= */ FPBits::min_normal().uintval(),
8391
/* endingBit= */ FPBits::max_normal().uintval(),
84-
10'000'001, log);
92+
1'000'001, rounds, log);
8593
log << "\n Performance tests with inputs in normal range with exponents "
8694
"close to each other:\n";
87-
run_perf_in_range(
88-
myFunc, otherFunc, /* startingBit= */ FPBits(T(0x1.0p-10)).uintval(),
89-
/* endingBit= */ FPBits(T(0x1.0p+10)).uintval(), 1'001'001, log);
95+
run_perf_in_range(myFunc, otherFunc,
96+
/* startingBit= */ FPBits(T(0x1.0p-10)).uintval(),
97+
/* endingBit= */ FPBits(T(0x1.0p+10)).uintval(),
98+
1'000'001, rounds, log);
9099
}
91100

92101
static void run_diff(Func myFunc, Func otherFunc, const char *logFile) {
@@ -117,6 +126,15 @@ template <typename T> class BinaryOpSingleOutputPerf {
117126
#define BINARY_OP_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \
118127
int main() { \
119128
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf<T>::run_perf( \
120-
&myFunc, &otherFunc, filename); \
129+
&myFunc, &otherFunc, 1, filename); \
121130
return 0; \
122131
}
132+
133+
#define BINARY_OP_SINGLE_OUTPUT_PERF_EX(T, myFunc, otherFunc, rounds, \
134+
filename) \
135+
{ \
136+
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf<T>::run_perf( \
137+
&myFunc, &otherFunc, rounds, filename); \
138+
LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf<T>::run_perf( \
139+
&myFunc, &otherFunc, rounds, filename); \
140+
}

libc/test/src/math/performance_testing/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ add_header_library(
8888
binary_op_single_output_diff
8989
HDRS
9090
BinaryOpSingleOutputPerf.h
91+
DEPENDS
92+
libc.src.__support.FPUtil.fp_bits
9193
)
9294

9395
add_perf_binary(
@@ -343,6 +345,17 @@ add_perf_binary(
343345
-fno-builtin
344346
)
345347

348+
add_perf_binary(
349+
fmodf16_perf
350+
SRCS
351+
fmodf16_perf.cpp
352+
DEPENDS
353+
.binary_op_single_output_diff
354+
libc.src.math.fmodf16
355+
libc.src.__support.FPUtil.generic.fmod
356+
libc.src.__support.macros.properties.types
357+
)
358+
346359
add_perf_binary(
347360
fmodf128_perf
348361
SRCS
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Performance test for fmodf16 --------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "BinaryOpSingleOutputPerf.h"
10+
11+
#include "src/__support/FPUtil/generic/FMod.h"
12+
#include "src/__support/macros/properties/types.h"
13+
14+
#include <stdint.h>
15+
16+
#define FMOD_FUNC(U) (LIBC_NAMESPACE::fputil::generic::FMod<float16, U>::eval)
17+
18+
int main() {
19+
BINARY_OP_SINGLE_OUTPUT_PERF_EX(float16, FMOD_FUNC(uint16_t),
20+
FMOD_FUNC(uint32_t), 5000,
21+
"fmodf16_u16_vs_u32_perf.log")
22+
23+
BINARY_OP_SINGLE_OUTPUT_PERF_EX(float16, FMOD_FUNC(uint16_t),
24+
FMOD_FUNC(uint64_t), 5000,
25+
"fmodf16_u16_vs_u64_perf.log")
26+
return 0;
27+
}

libc/test/src/math/smoke/CMakeLists.txt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3111,10 +3111,10 @@ add_fp_unittest(
31113111
HDRS
31123112
FModTest.h
31133113
DEPENDS
3114+
libc.hdr.fenv_macros
31143115
libc.src.errno.errno
31153116
libc.src.math.fmodf
3116-
libc.src.__support.FPUtil.basic_operations
3117-
libc.src.__support.FPUtil.nearest_integer_operations
3117+
libc.src.__support.FPUtil.fenv_impl
31183118
# FIXME: Currently fails on the GPU build.
31193119
UNIT_TEST_ONLY
31203120
)
@@ -3128,10 +3128,10 @@ add_fp_unittest(
31283128
HDRS
31293129
FModTest.h
31303130
DEPENDS
3131+
libc.hdr.fenv_macros
31313132
libc.src.errno.errno
31323133
libc.src.math.fmod
3133-
libc.src.__support.FPUtil.basic_operations
3134-
libc.src.__support.FPUtil.nearest_integer_operations
3134+
libc.src.__support.FPUtil.fenv_impl
31353135
# FIXME: Currently fails on the GPU build.
31363136
UNIT_TEST_ONLY
31373137
)
@@ -3145,10 +3145,27 @@ add_fp_unittest(
31453145
HDRS
31463146
FModTest.h
31473147
DEPENDS
3148+
libc.hdr.fenv_macros
31483149
libc.src.errno.errno
31493150
libc.src.math.fmodl
3150-
libc.src.__support.FPUtil.basic_operations
3151-
libc.src.__support.FPUtil.nearest_integer_operations
3151+
libc.src.__support.FPUtil.fenv_impl
3152+
# FIXME: Currently fails on the GPU build.
3153+
UNIT_TEST_ONLY
3154+
)
3155+
3156+
add_fp_unittest(
3157+
fmodf16_test
3158+
SUITE
3159+
libc-math-smoke-tests
3160+
SRCS
3161+
fmodf16_test.cpp
3162+
HDRS
3163+
FModTest.h
3164+
DEPENDS
3165+
libc.hdr.fenv_macros
3166+
libc.src.errno.errno
3167+
libc.src.math.fmodf16
3168+
libc.src.__support.FPUtil.fenv_impl
31523169
# FIXME: Currently fails on the GPU build.
31533170
UNIT_TEST_ONLY
31543171
)
@@ -3162,10 +3179,10 @@ add_fp_unittest(
31623179
HDRS
31633180
FModTest.h
31643181
DEPENDS
3182+
libc.hdr.fenv_macros
31653183
libc.src.errno.errno
31663184
libc.src.math.fmodf128
3167-
libc.src.__support.FPUtil.basic_operations
3168-
libc.src.__support.FPUtil.nearest_integer_operations
3185+
libc.src.__support.FPUtil.fenv_impl
31693186
# FIXME: Currently fails on the GPU build.
31703187
UNIT_TEST_ONLY
31713188
)

0 commit comments

Comments
 (0)