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