1 //===-- Unittests for sincosf ---------------------------------------------===//
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 "include/math.h"
10 #include "src/errno/llvmlibc_errno.h"
11 #include "src/math/math_utils.h"
12 #include "src/math/sincosf.h"
13 #include "test/src/math/float.h"
14 #include "test/src/math/sdcomp26094.h"
15 #include "utils/CPP/Array.h"
16 #include "utils/MPFRWrapper/MPFRUtils.h"
17 #include "utils/UnitTest/Test.h"
18 
19 #include <stdint.h>
20 
21 using __llvm_libc::as_float;
22 using __llvm_libc::as_uint32_bits;
23 
24 using __llvm_libc::testing::FloatBits;
25 using __llvm_libc::testing::sdcomp26094Values;
26 
27 namespace mpfr = __llvm_libc::testing::mpfr;
28 // 12 additional bits of precision over the base precision of a |float|
29 // value.
30 static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::floatPrecision, 12,
31                                            3 * 0x1000 / 4};
32 
33 TEST(SinCosfTest, SpecialNumbers) {
34   llvmlibc_errno = 0;
35   float sin, cos;
36 
37   __llvm_libc::sincosf(as_float(FloatBits::QNan), &sin, &cos);
38   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(cos)));
39   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(sin)));
40   EXPECT_EQ(llvmlibc_errno, 0);
41 
42   __llvm_libc::sincosf(as_float(FloatBits::NegQNan), &sin, &cos);
43   EXPECT_TRUE(FloatBits::isNegQNan(as_uint32_bits(cos)));
44   EXPECT_TRUE(FloatBits::isNegQNan(as_uint32_bits(sin)));
45   EXPECT_EQ(llvmlibc_errno, 0);
46 
47   __llvm_libc::sincosf(as_float(FloatBits::SNan), &sin, &cos);
48   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(cos)));
49   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(sin)));
50   EXPECT_EQ(llvmlibc_errno, 0);
51 
52   __llvm_libc::sincosf(as_float(FloatBits::NegSNan), &sin, &cos);
53   EXPECT_TRUE(FloatBits::isNegQNan(as_uint32_bits(cos)));
54   EXPECT_TRUE(FloatBits::isNegQNan(as_uint32_bits(sin)));
55   EXPECT_EQ(llvmlibc_errno, 0);
56 
57   __llvm_libc::sincosf(as_float(FloatBits::Zero), &sin, &cos);
58   EXPECT_EQ(FloatBits::One, as_uint32_bits(cos));
59   EXPECT_EQ(FloatBits::Zero, as_uint32_bits(sin));
60   EXPECT_EQ(llvmlibc_errno, 0);
61 
62   __llvm_libc::sincosf(as_float(FloatBits::NegZero), &sin, &cos);
63   EXPECT_EQ(FloatBits::One, as_uint32_bits(cos));
64   EXPECT_EQ(FloatBits::NegZero, as_uint32_bits(sin));
65   EXPECT_EQ(llvmlibc_errno, 0);
66 
67   llvmlibc_errno = 0;
68   __llvm_libc::sincosf(as_float(FloatBits::Inf), &sin, &cos);
69   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(cos)));
70   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(sin)));
71   EXPECT_EQ(llvmlibc_errno, EDOM);
72 
73   llvmlibc_errno = 0;
74   __llvm_libc::sincosf(as_float(FloatBits::NegInf), &sin, &cos);
75   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(cos)));
76   EXPECT_TRUE(FloatBits::isQNan(as_uint32_bits(sin)));
77   EXPECT_EQ(llvmlibc_errno, EDOM);
78 }
79 
80 TEST(SinCosfTest, InFloatRange) {
81   constexpr uint32_t count = 1000000;
82   constexpr uint32_t step = UINT32_MAX / count;
83   for (uint32_t i = 0, v = 0; i <= count; ++i, v += step) {
84     float x = as_float(v);
85     if (isnan(x) || isinf(x))
86       continue;
87 
88     float sin, cos;
89     __llvm_libc::sincosf(x, &sin, &cos);
90     ASSERT_MPFR_MATCH(mpfr::OP_Cos, x, cos, tolerance);
91     ASSERT_MPFR_MATCH(mpfr::OP_Sin, x, sin, tolerance);
92   }
93 }
94 
95 // For small values, cos(x) is 1 and sin(x) is x.
96 TEST(SinCosfTest, SmallValues) {
97   uint32_t bits = 0x17800000;
98   float x = as_float(bits);
99   float result_cos, result_sin;
100   __llvm_libc::sincosf(x, &result_sin, &result_cos);
101   EXPECT_MPFR_MATCH(mpfr::OP_Cos, x, result_cos, tolerance);
102   EXPECT_MPFR_MATCH(mpfr::OP_Sin, x, result_sin, tolerance);
103   EXPECT_EQ(FloatBits::One, as_uint32_bits(result_cos));
104   EXPECT_EQ(bits, as_uint32_bits(result_sin));
105 
106   bits = 0x00400000;
107   x = as_float(bits);
108   __llvm_libc::sincosf(x, &result_sin, &result_cos);
109   EXPECT_MPFR_MATCH(mpfr::OP_Cos, x, result_cos, tolerance);
110   EXPECT_MPFR_MATCH(mpfr::OP_Sin, x, result_sin, tolerance);
111   EXPECT_EQ(FloatBits::One, as_uint32_bits(result_cos));
112   EXPECT_EQ(bits, as_uint32_bits(result_sin));
113 }
114 
115 // SDCOMP-26094: check sinf in the cases for which the range reducer
116 // returns values furthest beyond its nominal upper bound of pi/4.
117 TEST(SinCosfTest, SDCOMP_26094) {
118   for (uint32_t v : sdcomp26094Values) {
119     float x = as_float(v);
120     float sin, cos;
121     __llvm_libc::sincosf(x, &sin, &cos);
122     EXPECT_MPFR_MATCH(mpfr::OP_Cos, x, cos, tolerance);
123     EXPECT_MPFR_MATCH(mpfr::OP_Sin, x, sin, tolerance);
124   }
125 }
126