Skip to content

Commit 60f802b

Browse files
committed
[libc][math][c23] Add f16sqrt C23 math function
1 parent eabe091 commit 60f802b

File tree

16 files changed

+156
-122
lines changed

16 files changed

+156
-122
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
507507
libc.src.math.copysignf16
508508
libc.src.math.f16divf
509509
libc.src.math.f16fmaf
510+
libc.src.math.f16sqrt
510511
libc.src.math.f16sqrtf
511512
libc.src.math.fabsf16
512513
libc.src.math.fdimf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
538538
libc.src.math.copysignf16
539539
libc.src.math.f16divf
540540
libc.src.math.f16fmaf
541+
libc.src.math.f16sqrt
541542
libc.src.math.f16sqrtf
542543
libc.src.math.fabsf16
543544
libc.src.math.fdimf16

libc/docs/math/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ Higher Math Functions
292292
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
293293
| fma | |check| | |check| | | | | 7.12.13.1 | F.10.10.1 |
294294
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
295-
| f16sqrt | |check| | | | N/A | | 7.12.14.6 | F.10.11 |
295+
| f16sqrt | |check| | |check| | | N/A | | 7.12.14.6 | F.10.11 |
296296
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
297297
| fsqrt | N/A | | | N/A | | 7.12.14.6 | F.10.11 |
298298
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/spec/stdc.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ def StdC : StandardSpec<"stdc"> {
728728

729729
GuardedFunctionSpec<"f16divf", RetValSpec<Float16Type>, [ArgSpec<FloatType>, ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
730730

731+
GuardedFunctionSpec<"f16sqrt", RetValSpec<Float16Type>, [ArgSpec<DoubleType>], "LIBC_TYPES_HAS_FLOAT16">,
731732
GuardedFunctionSpec<"f16sqrtf", RetValSpec<Float16Type>, [ArgSpec<FloatType>], "LIBC_TYPES_HAS_FLOAT16">,
732733
]
733734
>;

libc/src/__support/FPUtil/generic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_header_library(
88
libc.src.__support.common
99
libc.src.__support.CPP.bit
1010
libc.src.__support.CPP.type_traits
11+
libc.src.__support.FPUtil.dyadic_float
1112
libc.src.__support.FPUtil.fenv_impl
1213
libc.src.__support.FPUtil.fp_bits
1314
libc.src.__support.FPUtil.rounding_mode

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

Lines changed: 14 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "src/__support/CPP/type_traits.h"
1515
#include "src/__support/FPUtil/FEnvImpl.h"
1616
#include "src/__support/FPUtil/FPBits.h"
17-
#include "src/__support/FPUtil/rounding_mode.h"
17+
#include "src/__support/FPUtil/dyadic_float.h"
1818
#include "src/__support/common.h"
1919
#include "src/__support/uint128.h"
2020

@@ -78,16 +78,14 @@ sqrt(InType x) {
7878
return x86::sqrt(x);
7979
} else {
8080
// IEEE floating points formats.
81-
using OutFPBits = typename fputil::FPBits<OutType>;
82-
using OutStorageType = typename OutFPBits::StorageType;
83-
using InFPBits = typename fputil::FPBits<InType>;
81+
using OutFPBits = FPBits<OutType>;
82+
using InFPBits = FPBits<InType>;
8483
using InStorageType = typename InFPBits::StorageType;
84+
using DyadicFloat =
85+
DyadicFloat<cpp::bit_ceil(static_cast<size_t>(InFPBits::STORAGE_LEN))>;
86+
8587
constexpr InStorageType ONE = InStorageType(1) << InFPBits::FRACTION_LEN;
8688
constexpr auto FLT_NAN = OutFPBits::quiet_nan().get_val();
87-
constexpr int EXTRA_FRACTION_LEN =
88-
InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
89-
constexpr InStorageType EXTRA_FRACTION_MASK =
90-
(InStorageType(1) << EXTRA_FRACTION_LEN) - 1;
9189

9290
InFPBits bits(x);
9391

@@ -146,91 +144,19 @@ sqrt(InType x) {
146144
}
147145

148146
// We compute one more iteration in order to round correctly.
149-
bool lsb = (y & (InStorageType(1) << EXTRA_FRACTION_LEN)) !=
150-
0; // Least significant bit
151-
bool rb = false; // Round bit
152147
r <<= 2;
153-
InStorageType tmp = (y << 2) + 1;
148+
y <<= 2;
149+
InStorageType tmp = y + 1;
154150
if (r >= tmp) {
155151
r -= tmp;
156-
rb = true;
157-
}
158-
159-
bool sticky = false;
160-
161-
if constexpr (EXTRA_FRACTION_LEN > 0) {
162-
sticky = rb || (y & EXTRA_FRACTION_MASK) != 0;
163-
rb = (y & (InStorageType(1) << (EXTRA_FRACTION_LEN - 1))) != 0;
164-
}
165-
166-
// Remove hidden bit and append the exponent field.
167-
x_exp = ((x_exp >> 1) + OutFPBits::EXP_BIAS);
168-
169-
OutStorageType y_out = static_cast<OutStorageType>(
170-
((y - ONE) >> EXTRA_FRACTION_LEN) |
171-
(static_cast<OutStorageType>(x_exp) << OutFPBits::FRACTION_LEN));
172-
173-
if constexpr (EXTRA_FRACTION_LEN > 0) {
174-
if (x_exp >= OutFPBits::MAX_BIASED_EXPONENT) {
175-
switch (quick_get_round()) {
176-
case FE_TONEAREST:
177-
case FE_UPWARD:
178-
return OutFPBits::inf().get_val();
179-
default:
180-
return OutFPBits::max_normal().get_val();
181-
}
182-
}
183-
184-
if (x_exp <
185-
-OutFPBits::EXP_BIAS - OutFPBits::SIG_LEN + EXTRA_FRACTION_LEN) {
186-
switch (quick_get_round()) {
187-
case FE_UPWARD:
188-
return OutFPBits::min_subnormal().get_val();
189-
default:
190-
return OutType(0.0);
191-
}
192-
}
193-
194-
if (x_exp <= 0) {
195-
int underflow_extra_fraction_len = EXTRA_FRACTION_LEN - x_exp + 1;
196-
InStorageType underflow_extra_fraction_mask =
197-
(InStorageType(1) << underflow_extra_fraction_len) - 1;
198-
199-
rb = (y & (InStorageType(1) << (underflow_extra_fraction_len - 1))) !=
200-
0;
201-
OutStorageType subnormal_mant =
202-
static_cast<OutStorageType>(y >> underflow_extra_fraction_len);
203-
lsb = (subnormal_mant & 1) != 0;
204-
sticky = sticky || (y & underflow_extra_fraction_mask) != 0;
205-
206-
switch (quick_get_round()) {
207-
case FE_TONEAREST:
208-
if (rb && (lsb || sticky))
209-
++subnormal_mant;
210-
break;
211-
case FE_UPWARD:
212-
if (rb || sticky)
213-
++subnormal_mant;
214-
break;
215-
}
216-
217-
return cpp::bit_cast<OutType>(subnormal_mant);
218-
}
219-
}
220-
221-
switch (quick_get_round()) {
222-
case FE_TONEAREST:
223-
// Round to nearest, ties to even
224-
if (rb && (lsb || (r != 0)))
225-
++y_out;
226-
break;
227-
case FE_UPWARD:
228-
if (rb || (r != 0) || sticky)
229-
++y_out;
230-
break;
152+
// Rounding bit.
153+
y |= 1 << 1;
231154
}
155+
// Sticky bit.
156+
y |= r != 0;
232157

233-
return cpp::bit_cast<OutType>(y_out);
158+
DyadicFloat yd(Sign::POS, (x_exp >> 1) - 2 - InFPBits::FRACTION_LEN, y);
159+
return yd.template as<OutType, /*ShouldSignalExceptions=*/true>();
234160
}
235161
}
236162
}

libc/src/math/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ add_math_entrypoint_object(f16divf)
103103

104104
add_math_entrypoint_object(f16fmaf)
105105

106+
add_math_entrypoint_object(f16sqrt)
106107
add_math_entrypoint_object(f16sqrtf)
107108

108109
add_math_entrypoint_object(fabs)

libc/src/math/f16sqrt.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for f16sqrt -----------------------*- 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_F16SQRT_H
10+
#define LLVM_LIBC_SRC_MATH_F16SQRT_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 f16sqrt(double x);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_F16SQRT_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3757,6 +3757,19 @@ add_entrypoint_object(
37573757
-O3
37583758
)
37593759

3760+
add_entrypoint_object(
3761+
f16sqrt
3762+
SRCS
3763+
f16sqrt.cpp
3764+
HDRS
3765+
../f16sqrt.h
3766+
DEPENDS
3767+
libc.src.__support.macros.properties.types
3768+
libc.src.__support.FPUtil.sqrt
3769+
COMPILE_OPTIONS
3770+
-O3
3771+
)
3772+
37603773
add_entrypoint_object(
37613774
f16sqrtf
37623775
SRCS

libc/src/math/generic/f16sqrt.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of f16sqrt 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/f16sqrt.h"
10+
#include "src/__support/FPUtil/sqrt.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, f16sqrt, (double x)) {
16+
return fputil::sqrt<float16>(x);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/test/src/math/CMakeLists.txt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,9 +1247,10 @@ add_fp_unittest(
12471247
libc-math-unittests
12481248
SRCS
12491249
sqrtf_test.cpp
1250+
HDRS
1251+
SqrtTest.h
12501252
DEPENDS
12511253
libc.src.math.sqrtf
1252-
libc.src.__support.FPUtil.fp_bits
12531254
)
12541255

12551256
add_fp_unittest(
@@ -1259,9 +1260,10 @@ add_fp_unittest(
12591260
libc-math-unittests
12601261
SRCS
12611262
sqrt_test.cpp
1263+
HDRS
1264+
SqrtTest.h
12621265
DEPENDS
12631266
libc.src.math.sqrt
1264-
libc.src.__support.FPUtil.fp_bits
12651267
)
12661268

12671269
add_fp_unittest(
@@ -1271,9 +1273,10 @@ add_fp_unittest(
12711273
libc-math-unittests
12721274
SRCS
12731275
sqrtl_test.cpp
1276+
HDRS
1277+
SqrtTest.h
12741278
DEPENDS
12751279
libc.src.math.sqrtl
1276-
libc.src.__support.FPUtil.fp_bits
12771280
)
12781281

12791282
add_fp_unittest(
@@ -1283,9 +1286,10 @@ add_fp_unittest(
12831286
libc-math-unittests
12841287
SRCS
12851288
generic_sqrtf_test.cpp
1289+
HDRS
1290+
SqrtTest.h
12861291
DEPENDS
12871292
libc.src.math.sqrtf
1288-
libc.src.__support.FPUtil.fp_bits
12891293
libc.src.__support.FPUtil.generic.sqrt
12901294
COMPILE_OPTIONS
12911295
-O3
@@ -1298,9 +1302,10 @@ add_fp_unittest(
12981302
libc-math-unittests
12991303
SRCS
13001304
generic_sqrt_test.cpp
1305+
HDRS
1306+
SqrtTest.h
13011307
DEPENDS
13021308
libc.src.math.sqrt
1303-
libc.src.__support.FPUtil.fp_bits
13041309
libc.src.__support.FPUtil.generic.sqrt
13051310
COMPILE_OPTIONS
13061311
-O3
@@ -1313,9 +1318,10 @@ add_fp_unittest(
13131318
libc-math-unittests
13141319
SRCS
13151320
generic_sqrtl_test.cpp
1321+
HDRS
1322+
SqrtTest.h
13161323
DEPENDS
13171324
libc.src.math.sqrtl
1318-
libc.src.__support.FPUtil.fp_bits
13191325
libc.src.__support.FPUtil.generic.sqrt
13201326
COMPILE_OPTIONS
13211327
-O3
@@ -1903,6 +1909,19 @@ add_fp_unittest(
19031909
libc.src.math.f16divf
19041910
)
19051911

1912+
add_fp_unittest(
1913+
f16sqrt_test
1914+
NEED_MPFR
1915+
SUITE
1916+
libc-math-unittests
1917+
SRCS
1918+
f16sqrt_test.cpp
1919+
HDRS
1920+
SqrtTest.h
1921+
DEPENDS
1922+
libc.src.math.f16sqrt
1923+
)
1924+
19061925
add_fp_unittest(
19071926
f16fmaf_test
19081927
NEED_MPFR

0 commit comments

Comments
 (0)