Skip to content

Commit 0f6d3ad

Browse files
authored
[libc][math] Refactor cosf16 implementation to header-only in src/__support/math folder. (#152871)
Part of #147386 in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450
1 parent 4cdc338 commit 0f6d3ad

File tree

15 files changed

+217
-129
lines changed

15 files changed

+217
-129
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "math/cbrtf.h"
3535
#include "math/cos.h"
3636
#include "math/cosf.h"
37+
#include "math/cosf16.h"
3738
#include "math/erff.h"
3839
#include "math/exp.h"
3940
#include "math/exp10.h"

libc/shared/math/cosf16.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===-- Shared cosf16 function ----------------------------------*- 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_SHARED_MATH_COSF16_H
10+
#define LLVM_LIBC_SHARED_MATH_COSF16_H
11+
12+
#include "shared/libc_common.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "src/__support/math/cosf16.h"
17+
18+
namespace LIBC_NAMESPACE_DECL {
19+
namespace shared {
20+
21+
using math::cosf16;
22+
23+
} // namespace shared
24+
} // namespace LIBC_NAMESPACE_DECL
25+
26+
#endif // LIBC_TYPES_HAS_FLOAT16
27+
28+
#endif // LLVM_LIBC_SHARED_MATH_COSF16_H

libc/src/__support/math/CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,23 @@ add_header_library(
390390
libc.src.__support.macros.optimization
391391
)
392392

393+
add_header_library(
394+
cosf16
395+
HDRS
396+
cosf16.h
397+
DEPENDS
398+
.sincosf16_utils
399+
libc.hdr.errno_macros
400+
libc.hdr.fenv_macros
401+
libc.src.__support.FPUtil.cast
402+
libc.src.__support.FPUtil.fenv_impl
403+
libc.src.__support.FPUtil.fp_bits
404+
libc.src.__support.FPUtil.except_value_utils
405+
libc.src.__support.FPUtil.multiply_add
406+
libc.src.__support.macros.optimization
407+
libc.src.__support.macros.properties.types
408+
)
409+
393410
add_header_library(
394411
erff
395412
HDRS
@@ -699,3 +716,13 @@ add_header_library(
699716
libc.src.__support.FPUtil.polyeval
700717
libc.src.__support.common
701718
)
719+
720+
add_header_library(
721+
sincosf16_utils
722+
HDRS
723+
sincosf16_utils.h
724+
DEPENDS
725+
libc.src.__support.FPUtil.polyeval
726+
libc.src.__support.FPUtil.nearest_integer
727+
libc.src.__support.common
728+
)

libc/src/__support/math/cosf16.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===-- Implementation header for cosf16 ------------------------*- 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___SUPPORT_MATH_COSF16_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_COSF16_H
11+
12+
#include "include/llvm-libc-macros/float16-macros.h"
13+
14+
#ifdef LIBC_TYPES_HAS_FLOAT16
15+
16+
#include "sincosf16_utils.h"
17+
#include "src/__support/FPUtil/FEnvImpl.h"
18+
#include "src/__support/FPUtil/FPBits.h"
19+
#include "src/__support/FPUtil/cast.h"
20+
#include "src/__support/FPUtil/except_value_utils.h"
21+
#include "src/__support/FPUtil/multiply_add.h"
22+
#include "src/__support/macros/optimization.h"
23+
24+
namespace LIBC_NAMESPACE_DECL {
25+
26+
namespace math {
27+
28+
LIBC_INLINE static constexpr float16 cosf16(float16 x) {
29+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
30+
constexpr size_t N_EXCEPTS = 4;
31+
32+
constexpr fputil::ExceptValues<float16, N_EXCEPTS> COSF16_EXCEPTS{{
33+
// (input, RZ output, RU offset, RD offset, RN offset)
34+
{0x2b7c, 0x3bfc, 1, 0, 1},
35+
{0x4ac1, 0x38b5, 1, 0, 0},
36+
{0x5c49, 0xb8c6, 0, 1, 0},
37+
{0x7acc, 0xa474, 0, 1, 0},
38+
}};
39+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
40+
41+
using namespace sincosf16_internal;
42+
using FPBits = fputil::FPBits<float16>;
43+
FPBits xbits(x);
44+
45+
uint16_t x_u = xbits.uintval();
46+
uint16_t x_abs = x_u & 0x7fff;
47+
float xf = x;
48+
49+
// Range reduction:
50+
// For |x| > pi/32, we perform range reduction as follows:
51+
// Find k and y such that:
52+
// x = (k + y) * pi/32
53+
// k is an integer, |y| < 0.5
54+
//
55+
// This is done by performing:
56+
// k = round(x * 32/pi)
57+
// y = x * 32/pi - k
58+
//
59+
// Once k and y are computed, we then deduce the answer by the cosine of sum
60+
// formula:
61+
// cos(x) = cos((k + y) * pi/32)
62+
// = cos(k * pi/32) * cos(y * pi/32) -
63+
// sin(k * pi/32) * sin(y * pi/32)
64+
65+
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
66+
// Handle exceptional values
67+
if (auto r = COSF16_EXCEPTS.lookup(x_abs); LIBC_UNLIKELY(r.has_value()))
68+
return r.value();
69+
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
70+
71+
// cos(+/-0) = 1
72+
if (LIBC_UNLIKELY(x_abs == 0U))
73+
return fputil::cast<float16>(1.0f);
74+
75+
// cos(+/-inf) = NaN, and cos(NaN) = NaN
76+
if (xbits.is_inf_or_nan()) {
77+
if (xbits.is_signaling_nan()) {
78+
fputil::raise_except_if_required(FE_INVALID);
79+
return FPBits::quiet_nan().get_val();
80+
}
81+
82+
if (xbits.is_inf()) {
83+
fputil::set_errno_if_required(EDOM);
84+
fputil::raise_except_if_required(FE_INVALID);
85+
}
86+
87+
return x + FPBits::quiet_nan().get_val();
88+
}
89+
90+
float sin_k = 0.0f, cos_k = 0.0f, sin_y = 0.0f, cosm1_y = 0.0f;
91+
sincosf16_eval(xf, sin_k, cos_k, sin_y, cosm1_y);
92+
// Since, cosm1_y = cos_y - 1, therefore:
93+
// cos(x) = cos_k * cos_y - sin_k * sin_y
94+
// = cos_k * (cos_y - 1 + 1) - sin_k * sin_y
95+
// = cos_k * cosm1_y - sin_k * sin_y + cos_k
96+
return fputil::cast<float16>(fputil::multiply_add(
97+
cos_k, cosm1_y, fputil::multiply_add(-sin_k, sin_y, cos_k)));
98+
}
99+
100+
} // namespace math
101+
102+
} // namespace LIBC_NAMESPACE_DECL
103+
104+
#endif // LIBC_TYPES_HAS_FLOAT16
105+
106+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSF16_H

libc/src/math/generic/sincosf16_utils.h renamed to libc/src/__support/math/sincosf16_utils.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
namespace LIBC_NAMESPACE_DECL {
1818

19+
namespace sincosf16_internal {
20+
1921
// Lookup table for sin(k * pi / 32) with k = 0, ..., 63.
2022
// Table is generated with Sollya as follows:
2123
// > display = hexadecimmal;
@@ -66,7 +68,7 @@ LIBC_INLINE int32_t range_reduction_sincosf16(float x, float &y) {
6668
return static_cast<int32_t>(kd);
6769
}
6870

69-
static LIBC_INLINE void sincosf16_poly_eval(int32_t k, float y, float &sin_k,
71+
LIBC_INLINE static void sincosf16_poly_eval(int32_t k, float y, float &sin_k,
7072
float &cos_k, float &sin_y,
7173
float &cosm1_y) {
7274

@@ -107,6 +109,8 @@ LIBC_INLINE void sincospif16_eval(float xf, float &sin_k, float &cos_k,
107109
sincosf16_poly_eval(k, y, sin_k, cos_k, sin_y, cosm1_y);
108110
}
109111

112+
} // namespace sincosf16_internal
113+
110114
} // namespace LIBC_NAMESPACE_DECL
111115

112116
#endif // LLVM_LIBC_SRC_MATH_GENERIC_SINCOSF16_UTILS_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -278,16 +278,6 @@ add_entrypoint_object(
278278
libc.src.__support.FPUtil.generic.add_sub
279279
)
280280

281-
add_header_library(
282-
sincosf16_utils
283-
HDRS
284-
sincosf16_utils.h
285-
DEPENDS
286-
libc.src.__support.FPUtil.polyeval
287-
libc.src.__support.FPUtil.nearest_integer
288-
libc.src.__support.common
289-
)
290-
291281
add_entrypoint_object(
292282
cos
293283
SRCS
@@ -315,16 +305,7 @@ add_entrypoint_object(
315305
HDRS
316306
../cosf16.h
317307
DEPENDS
318-
.sincosf16_utils
319-
libc.hdr.errno_macros
320-
libc.hdr.fenv_macros
321-
libc.src.__support.FPUtil.cast
322-
libc.src.__support.FPUtil.fenv_impl
323-
libc.src.__support.FPUtil.fp_bits
324-
libc.src.__support.FPUtil.except_value_utils
325-
libc.src.__support.FPUtil.multiply_add
326-
libc.src.__support.macros.optimization
327-
libc.src.__support.macros.properties.types
308+
libc.src.__support.math.cosf16
328309
)
329310

330311
add_entrypoint_object(
@@ -349,14 +330,14 @@ add_entrypoint_object(
349330
HDRS
350331
../cospif16.h
351332
DEPENDS
352-
.sincosf16_utils
353333
libc.hdr.errno_macros
354334
libc.hdr.fenv_macros
355335
libc.src.__support.FPUtil.cast
356336
libc.src.__support.FPUtil.fenv_impl
357337
libc.src.__support.FPUtil.fp_bits
358338
libc.src.__support.FPUtil.multiply_add
359339
libc.src.__support.macros.optimization
340+
libc.src.__support.math.sincosf16_utils
360341
)
361342

362343
add_entrypoint_object(
@@ -405,7 +386,6 @@ add_entrypoint_object(
405386
HDRS
406387
../sinf16.h
407388
DEPENDS
408-
.sincosf16_utils
409389
libc.hdr.errno_macros
410390
libc.hdr.fenv_macros
411391
libc.src.__support.FPUtil.cast
@@ -415,6 +395,7 @@ add_entrypoint_object(
415395
libc.src.__support.FPUtil.multiply_add
416396
libc.src.__support.macros.optimization
417397
libc.src.__support.macros.properties.types
398+
libc.src.__support.math.sincosf16_utils
418399
COMPILE_OPTIONS
419400
${libc_opt_high_flag}
420401
)
@@ -482,14 +463,14 @@ add_entrypoint_object(
482463
HDRS
483464
../sinpif16.h
484465
DEPENDS
485-
.sincosf16_utils
486466
libc.hdr.errno_macros
487467
libc.hdr.fenv_macros
488468
libc.src.__support.FPUtil.cast
489469
libc.src.__support.FPUtil.fenv_impl
490470
libc.src.__support.FPUtil.fp_bits
491471
libc.src.__support.FPUtil.multiply_add
492472
libc.src.__support.macros.optimization
473+
libc.src.__support.math.sincosf16_utils
493474
)
494475

495476
add_entrypoint_object(
@@ -538,7 +519,6 @@ add_entrypoint_object(
538519
HDRS
539520
../tanf16.h
540521
DEPENDS
541-
.sincosf16_utils
542522
libc.hdr.errno_macros
543523
libc.hdr.fenv_macros
544524
libc.src.__support.FPUtil.cast
@@ -548,6 +528,7 @@ add_entrypoint_object(
548528
libc.src.__support.FPUtil.multiply_add
549529
libc.src.__support.macros.optimization
550530
libc.src.__support.macros.properties.types
531+
libc.src.__support.math.sincosf16_utils
551532
)
552533

553534
add_entrypoint_object(
@@ -572,7 +553,6 @@ add_entrypoint_object(
572553
HDRS
573554
../tanpif16.h
574555
DEPENDS
575-
.sincosf16_utils
576556
libc.hdr.errno_macros
577557
libc.hdr.fenv_macros
578558
libc.src.__support.FPUtil.cast
@@ -581,6 +561,7 @@ add_entrypoint_object(
581561
libc.src.__support.FPUtil.except_value_utils
582562
libc.src.__support.FPUtil.multiply_add
583563
libc.src.__support.macros.optimization
564+
libc.src.__support.math.sincosf16_utils
584565
)
585566

586567
add_entrypoint_object(

0 commit comments

Comments
 (0)