Skip to content

Commit f3ee845

Browse files
committed
[libc][math] Refactor cospif implementation to header-only in src/__support/math folder.
1 parent 2c79dc1 commit f3ee845

File tree

9 files changed

+166
-101
lines changed

9 files changed

+166
-101
lines changed

libc/shared/math.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "math/cosf16.h"
3838
#include "math/coshf.h"
3939
#include "math/coshf16.h"
40+
#include "math/cospif.h"
4041
#include "math/erff.h"
4142
#include "math/exp.h"
4243
#include "math/exp10.h"

libc/shared/math/cospif.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Shared cospif 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_COSPIF_H
10+
#define LLVM_LIBC_SHARED_MATH_COSPIF_H
11+
12+
#include "shared/libc_common.h"
13+
#include "src/__support/math/cospif.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
namespace shared {
17+
18+
using math::cospif;
19+
20+
} // namespace shared
21+
} // namespace LIBC_NAMESPACE_DECL
22+
23+
#endif // LLVM_LIBC_SHARED_MATH_COSPIF_H

libc/src/__support/math/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,18 @@ add_header_library(
432432
libc.src.__support.macros.optimization
433433
)
434434

435+
add_header_library(
436+
cospif
437+
HDRS
438+
cospif.h
439+
DEPENDS
440+
.sincosf_utils
441+
libc.src.__support.FPUtil.fenv_impl
442+
libc.src.__support.FPUtil.fp_bits
443+
libc.src.__support.FPUtil.multiply_add
444+
libc.src.__support.macros.optimization
445+
)
446+
435447
add_header_library(
436448
erff
437449
HDRS

libc/src/__support/math/cospif.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//===-- Implementation header for cospif ------------------------*- 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_COSPIF_H
10+
#define LLVM_LIBC_SRC___SUPPORT_MATH_COSPIF_H
11+
12+
#include "sincosf_utils.h"
13+
#include "src/__support/FPUtil/FEnvImpl.h"
14+
#include "src/__support/FPUtil/FPBits.h"
15+
#include "src/__support/FPUtil/multiply_add.h"
16+
#include "src/__support/common.h"
17+
#include "src/__support/macros/config.h"
18+
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19+
#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
20+
21+
namespace LIBC_NAMESPACE_DECL {
22+
23+
namespace math {
24+
25+
LIBC_INLINE static constexpr float cospif(float x) {
26+
using FPBits = typename fputil::FPBits<float>;
27+
28+
FPBits xbits(x);
29+
xbits.set_sign(Sign::POS);
30+
31+
uint32_t x_abs = xbits.uintval();
32+
double xd = static_cast<double>(xbits.get_val());
33+
34+
// Range reduction:
35+
// For |x| > 1/32, we perform range reduction as follows:
36+
// Find k and y such that:
37+
// x = (k + y) * 1/32
38+
// k is an integer
39+
// |y| < 0.5
40+
//
41+
// This is done by performing:
42+
// k = round(x * 32)
43+
// y = x * 32 - k
44+
//
45+
// Once k and y are computed, we then deduce the answer by the cosine of sum
46+
// formula:
47+
// cospi(x) = cos((k + y)*pi/32)
48+
// = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
49+
// The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed
50+
// and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
51+
// computed using degree-7 and degree-6 minimax polynomials generated by
52+
// Sollya respectively.
53+
54+
// The exhautive test passes for smaller values
55+
if (LIBC_UNLIKELY(x_abs < 0x38A2'F984U)) {
56+
57+
#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
58+
return fputil::multiply_add(xbits.get_val(), -0x1.0p-25f, 1.0f);
59+
#else
60+
return static_cast<float>(fputil::multiply_add(xd, -0x1.0p-25, 1.0));
61+
#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
62+
}
63+
64+
// Numbers greater or equal to 2^23 are always integers or NaN
65+
if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
66+
67+
if (LIBC_UNLIKELY(x_abs < 0x4B80'0000)) {
68+
return (x_abs & 0x1) ? -1.0f : 1.0f;
69+
}
70+
71+
// x is inf or nan.
72+
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
73+
if (xbits.is_signaling_nan()) {
74+
fputil::raise_except_if_required(FE_INVALID);
75+
return FPBits::quiet_nan().get_val();
76+
}
77+
78+
if (x_abs == 0x7f80'0000U) {
79+
fputil::set_errno_if_required(EDOM);
80+
fputil::raise_except_if_required(FE_INVALID);
81+
}
82+
return x + FPBits::quiet_nan().get_val();
83+
}
84+
85+
return 1.0f;
86+
}
87+
88+
// Combine the results with the sine of sum formula:
89+
// cos(pi * x) = cos((k + y)*pi/32)
90+
// = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
91+
// = (cosm1_y + 1) * cos_k - sin_y * sin_k
92+
// = (cosm1_y * cos_k + cos_k) - sin_y * sin_k
93+
double sin_k = 0, cos_k = 0, sin_y = 0, cosm1_y = 0;
94+
95+
sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
96+
97+
if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) {
98+
return 0.0f;
99+
}
100+
101+
return static_cast<float>(fputil::multiply_add(
102+
sin_y, -sin_k, fputil::multiply_add(cosm1_y, cos_k, cos_k)));
103+
}
104+
105+
} // namespace math
106+
107+
} // namespace LIBC_NAMESPACE_DECL
108+
109+
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_COSHF_H

libc/src/math/generic/CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,7 @@ add_entrypoint_object(
315315
HDRS
316316
../cospif.h
317317
DEPENDS
318-
libc.src.__support.math.sincosf_utils
319-
libc.src.__support.FPUtil.fenv_impl
320-
libc.src.__support.FPUtil.fp_bits
321-
libc.src.__support.FPUtil.fma
322-
libc.src.__support.FPUtil.multiply_add
323-
libc.src.__support.macros.optimization
318+
libc.src.__support.math.cospif
324319
)
325320

326321
add_entrypoint_object(

libc/src/math/generic/cospif.cpp

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -7,95 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/math/cospif.h"
10-
#include "src/__support/FPUtil/FEnvImpl.h"
11-
#include "src/__support/FPUtil/FPBits.h"
12-
#include "src/__support/FPUtil/multiply_add.h"
13-
#include "src/__support/common.h"
14-
#include "src/__support/macros/config.h"
15-
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
16-
#include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
17-
#include "src/__support/math/sincosf_utils.h"
10+
#include "src/__support/math/cospif.h"
1811

1912
namespace LIBC_NAMESPACE_DECL {
2013

21-
LLVM_LIBC_FUNCTION(float, cospif, (float x)) {
22-
using FPBits = typename fputil::FPBits<float>;
23-
24-
FPBits xbits(x);
25-
xbits.set_sign(Sign::POS);
26-
27-
uint32_t x_abs = xbits.uintval();
28-
double xd = static_cast<double>(xbits.get_val());
29-
30-
// Range reduction:
31-
// For |x| > 1/32, we perform range reduction as follows:
32-
// Find k and y such that:
33-
// x = (k + y) * 1/32
34-
// k is an integer
35-
// |y| < 0.5
36-
//
37-
// This is done by performing:
38-
// k = round(x * 32)
39-
// y = x * 32 - k
40-
//
41-
// Once k and y are computed, we then deduce the answer by the cosine of sum
42-
// formula:
43-
// cospi(x) = cos((k + y)*pi/32)
44-
// = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
45-
// The values of sin(k*pi/32) and cos(k*pi/32) for k = 0..63 are precomputed
46-
// and stored using a vector of 32 doubles. Sin(y*pi/32) and cos(y*pi/32) are
47-
// computed using degree-7 and degree-6 minimax polynomials generated by
48-
// Sollya respectively.
49-
50-
// The exhautive test passes for smaller values
51-
if (LIBC_UNLIKELY(x_abs < 0x38A2'F984U)) {
52-
53-
#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT)
54-
return fputil::multiply_add(xbits.get_val(), -0x1.0p-25f, 1.0f);
55-
#else
56-
return static_cast<float>(fputil::multiply_add(xd, -0x1.0p-25, 1.0));
57-
#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
58-
}
59-
60-
// Numbers greater or equal to 2^23 are always integers or NaN
61-
if (LIBC_UNLIKELY(x_abs >= 0x4B00'0000)) {
62-
63-
if (LIBC_UNLIKELY(x_abs < 0x4B80'0000)) {
64-
return (x_abs & 0x1) ? -1.0f : 1.0f;
65-
}
66-
67-
// x is inf or nan.
68-
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
69-
if (xbits.is_signaling_nan()) {
70-
fputil::raise_except_if_required(FE_INVALID);
71-
return FPBits::quiet_nan().get_val();
72-
}
73-
74-
if (x_abs == 0x7f80'0000U) {
75-
fputil::set_errno_if_required(EDOM);
76-
fputil::raise_except_if_required(FE_INVALID);
77-
}
78-
return x + FPBits::quiet_nan().get_val();
79-
}
80-
81-
return 1.0f;
82-
}
83-
84-
// Combine the results with the sine of sum formula:
85-
// cos(pi * x) = cos((k + y)*pi/32)
86-
// = cos(y*pi/32) * cos(k*pi/32) - sin(y*pi/32) * sin(k*pi/32)
87-
// = (cosm1_y + 1) * cos_k - sin_y * sin_k
88-
// = (cosm1_y * cos_k + cos_k) - sin_y * sin_k
89-
double sin_k, cos_k, sin_y, cosm1_y;
90-
91-
sincospif_eval(xd, sin_k, cos_k, sin_y, cosm1_y);
92-
93-
if (LIBC_UNLIKELY(sin_y == 0 && cos_k == 0)) {
94-
return 0.0f;
95-
}
96-
97-
return static_cast<float>(fputil::multiply_add(
98-
sin_y, -sin_k, fputil::multiply_add(cosm1_y, cos_k, cos_k)));
99-
}
14+
LLVM_LIBC_FUNCTION(float, cospif, (float x)) { return math::cospif(x); }
10015

10116
} // namespace LIBC_NAMESPACE_DECL

libc/test/shared/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ add_fp_unittest(
3333
libc.src.__support.math.cosf16
3434
libc.src.__support.math.coshf
3535
libc.src.__support.math.coshf16
36+
libc.src.__support.math.cospif
3637
libc.src.__support.math.erff
3738
libc.src.__support.math.exp
3839
libc.src.__support.math.exp10

libc/test/shared/shared_math_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
5353
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::cbrtf(0.0f));
5454
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::cosf(0.0f));
5555
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::coshf(0.0f));
56+
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::cospif(0.0f));
5657
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::erff(0.0f));
5758
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp10f(0.0f));
5859
EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::expf(0.0f));

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,6 +2392,21 @@ libc_support_library(
23922392
],
23932393
)
23942394

2395+
libc_support_library(
2396+
name = "__support_math_cospif",
2397+
hdrs = ["src/__support/math/cospif.h"],
2398+
deps = [
2399+
":__support_fputil_fma",
2400+
":__support_fputil_multiply_add",
2401+
":__support_fputil_nearest_integer",
2402+
":__support_fputil_polyeval",
2403+
":__support_fputil_rounding_mode",
2404+
":__support_macros_optimization",
2405+
":__support_sincosf_utils",
2406+
":common_constants",
2407+
],
2408+
)
2409+
23952410
libc_support_library(
23962411
name = "__support_math_erff",
23972412
hdrs = ["src/__support/math/erff.h"],
@@ -3220,14 +3235,7 @@ libc_math_function(
32203235
libc_math_function(
32213236
name = "cospif",
32223237
additional_deps = [
3223-
":__support_fputil_fma",
3224-
":__support_fputil_multiply_add",
3225-
":__support_fputil_nearest_integer",
3226-
":__support_fputil_polyeval",
3227-
":__support_fputil_rounding_mode",
3228-
":__support_macros_optimization",
3229-
":__support_sincosf_utils",
3230-
":common_constants",
3238+
":__support_math_cospif",
32313239
],
32323240
)
32333241

0 commit comments

Comments
 (0)