1ca6b3542SSiva Chandra Reddy //===-- Utilities for double precision trigonometric functions ------------===//
2ca6b3542SSiva Chandra Reddy //
3ca6b3542SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ca6b3542SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5ca6b3542SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ca6b3542SSiva Chandra Reddy //
7ca6b3542SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8ca6b3542SSiva Chandra Reddy 
9ca6b3542SSiva Chandra Reddy #include "src/__support/FPUtil/FPBits.h"
10ca6b3542SSiva Chandra Reddy #include "src/__support/FPUtil/ManipulationFunctions.h"
11ca6b3542SSiva Chandra Reddy #include "src/__support/FPUtil/UInt.h"
12ca6b3542SSiva Chandra Reddy #include "src/__support/FPUtil/XFloat.h"
13ca6b3542SSiva Chandra Reddy 
14ca6b3542SSiva Chandra Reddy using FPBits = __llvm_libc::fputil::FPBits<double>;
15ca6b3542SSiva Chandra Reddy 
16ca6b3542SSiva Chandra Reddy namespace __llvm_libc {
17ca6b3542SSiva Chandra Reddy 
18ca6b3542SSiva Chandra Reddy // Implementation is based on the Payne and Hanek range reduction algorithm.
19ca6b3542SSiva Chandra Reddy // The caller should ensure that x is positive.
20ca6b3542SSiva Chandra Reddy // Consider:
21ca6b3542SSiva Chandra Reddy //   x/y = x * 1/y = I + F
22ca6b3542SSiva Chandra Reddy // I is the integral part and F the fractional part of the result of the
23ca6b3542SSiva Chandra Reddy // division operation. Then M = mod(x, y) = F * y. In order to compute M, we
24ca6b3542SSiva Chandra Reddy // first compute F. We do it by dropping bits from 1/y which would only
25ca6b3542SSiva Chandra Reddy // contribute integral results in the operation x * 1/y. This helps us get
26ca6b3542SSiva Chandra Reddy // accurate values of F even when x is a very large number.
27ca6b3542SSiva Chandra Reddy //
28ca6b3542SSiva Chandra Reddy // Internal operations are performed at 192 bits of precision.
mod_impl(double x,const uint64_t y_bits[3],const uint64_t inv_y_bits[20],int y_exponent,int inv_y_exponent)29ca6b3542SSiva Chandra Reddy static double mod_impl(double x, const uint64_t y_bits[3],
30ca6b3542SSiva Chandra Reddy                        const uint64_t inv_y_bits[20], int y_exponent,
31ca6b3542SSiva Chandra Reddy                        int inv_y_exponent) {
32ca6b3542SSiva Chandra Reddy   FPBits bits(x);
33*1c92911eSMichael Jones   int exponent = bits.get_exponent();
34ca6b3542SSiva Chandra Reddy   int bit_drop = (exponent - 52) + inv_y_exponent + 1;
35ca6b3542SSiva Chandra Reddy   bit_drop = bit_drop >= 0 ? bit_drop : 0;
36ca6b3542SSiva Chandra Reddy   int word_drop = bit_drop / 64;
37ca6b3542SSiva Chandra Reddy   bit_drop %= 64;
38ca6b3542SSiva Chandra Reddy   fputil::UInt<256> man4;
39ca6b3542SSiva Chandra Reddy   for (size_t i = 0; i < 4; ++i) {
40ca6b3542SSiva Chandra Reddy     man4[3 - i] = inv_y_bits[word_drop + i];
41ca6b3542SSiva Chandra Reddy   }
42ca6b3542SSiva Chandra Reddy   man4.shift_left(bit_drop);
43ca6b3542SSiva Chandra Reddy   fputil::UInt<192> man_bits;
44ca6b3542SSiva Chandra Reddy   for (size_t i = 0; i < 3; ++i)
45ca6b3542SSiva Chandra Reddy     man_bits[i] = man4[i + 1];
46ca6b3542SSiva Chandra Reddy   fputil::XFloat<192> result(inv_y_exponent - word_drop * 64 - bit_drop,
47ca6b3542SSiva Chandra Reddy                              man_bits);
48ca6b3542SSiva Chandra Reddy   result.mul(x);
49ca6b3542SSiva Chandra Reddy   result.drop_int(); // |result| now holds fractional part of x/y.
50ca6b3542SSiva Chandra Reddy 
51ca6b3542SSiva Chandra Reddy   fputil::UInt<192> y_man;
52ca6b3542SSiva Chandra Reddy   for (size_t i = 0; i < 3; ++i)
53ca6b3542SSiva Chandra Reddy     y_man[i] = y_bits[2 - i];
54ca6b3542SSiva Chandra Reddy   fputil::XFloat<192> y_192(y_exponent, y_man);
55ca6b3542SSiva Chandra Reddy   return result.mul(y_192);
56ca6b3542SSiva Chandra Reddy }
57ca6b3542SSiva Chandra Reddy 
58ca6b3542SSiva Chandra Reddy static constexpr int TwoPIExponent = 2;
59ca6b3542SSiva Chandra Reddy 
60ca6b3542SSiva Chandra Reddy // The mantissa bits of 2 * PI.
61ca6b3542SSiva Chandra Reddy // The most signification bits are in the first uint64_t word
62ca6b3542SSiva Chandra Reddy // and the least signification bits are in the last word. The
63ca6b3542SSiva Chandra Reddy // first word includes the implicit '1' bit.
64ca6b3542SSiva Chandra Reddy static constexpr uint64_t TwoPI[] = {0xc90fdaa22168c234, 0xc4c6628b80dc1cd1,
65ca6b3542SSiva Chandra Reddy                                      0x29024e088a67cc74};
66ca6b3542SSiva Chandra Reddy 
67ca6b3542SSiva Chandra Reddy static constexpr int InvTwoPIExponent = -3;
68ca6b3542SSiva Chandra Reddy 
69ca6b3542SSiva Chandra Reddy // The mantissa bits of 1/(2 * PI).
70ca6b3542SSiva Chandra Reddy // The most signification bits are in the first uint64_t word
71ca6b3542SSiva Chandra Reddy // and the least signification bits are in the last word. The
72ca6b3542SSiva Chandra Reddy // first word includes the implicit '1' bit.
73ca6b3542SSiva Chandra Reddy static constexpr uint64_t InvTwoPI[] = {
74ca6b3542SSiva Chandra Reddy     0xa2f9836e4e441529, 0xfc2757d1f534ddc0, 0xdb6295993c439041,
75ca6b3542SSiva Chandra Reddy     0xfe5163abdebbc561, 0xb7246e3a424dd2e0, 0x6492eea09d1921c,
76ca6b3542SSiva Chandra Reddy     0xfe1deb1cb129a73e, 0xe88235f52ebb4484, 0xe99c7026b45f7e41,
77ca6b3542SSiva Chandra Reddy     0x3991d639835339f4, 0x9c845f8bbdf9283b, 0x1ff897ffde05980f,
78ca6b3542SSiva Chandra Reddy     0xef2f118b5a0a6d1f, 0x6d367ecf27cb09b7, 0x4f463f669e5fea2d,
79ca6b3542SSiva Chandra Reddy     0x7527bac7ebe5f17b, 0x3d0739f78a5292ea, 0x6bfb5fb11f8d5d08,
80ca6b3542SSiva Chandra Reddy     0x56033046fc7b6bab, 0xf0cfbc209af4361e};
81ca6b3542SSiva Chandra Reddy 
mod_2pi(double x)82ca6b3542SSiva Chandra Reddy double mod_2pi(double x) {
83ca6b3542SSiva Chandra Reddy   static constexpr double _2pi = 6.283185307179586;
84ca6b3542SSiva Chandra Reddy   if (x < _2pi)
85ca6b3542SSiva Chandra Reddy     return x;
86ca6b3542SSiva Chandra Reddy   return mod_impl(x, TwoPI, InvTwoPI, TwoPIExponent, InvTwoPIExponent);
87ca6b3542SSiva Chandra Reddy }
88ca6b3542SSiva Chandra Reddy 
89ca6b3542SSiva Chandra Reddy // Returns mod(x, pi/2)
mod_pi_over_2(double x)90ca6b3542SSiva Chandra Reddy double mod_pi_over_2(double x) {
91ca6b3542SSiva Chandra Reddy   static constexpr double pi_over_2 = 1.5707963267948966;
92ca6b3542SSiva Chandra Reddy   if (x < pi_over_2)
93ca6b3542SSiva Chandra Reddy     return x;
94ca6b3542SSiva Chandra Reddy   return mod_impl(x, TwoPI, InvTwoPI, TwoPIExponent - 2, InvTwoPIExponent + 2);
95ca6b3542SSiva Chandra Reddy }
96ca6b3542SSiva Chandra Reddy 
97ca6b3542SSiva Chandra Reddy // Returns mod(x, pi/4)
mod_pi_over_4(double x)98ca6b3542SSiva Chandra Reddy double mod_pi_over_4(double x) {
99ca6b3542SSiva Chandra Reddy   static constexpr double pi_over_4 = 0.7853981633974483;
100ca6b3542SSiva Chandra Reddy   if (x < pi_over_4)
101ca6b3542SSiva Chandra Reddy     return x;
102ca6b3542SSiva Chandra Reddy   return mod_impl(x, TwoPI, InvTwoPI, TwoPIExponent - 3, InvTwoPIExponent + 3);
103ca6b3542SSiva Chandra Reddy }
104ca6b3542SSiva Chandra Reddy 
105ca6b3542SSiva Chandra Reddy } // namespace __llvm_libc
106