1use crate::acospi::{INV_PI_DD, INV_PI_F128};
30use crate::common::f_fmla;
31use crate::double_double::DoubleDouble;
32use crate::dyadic_float::DyadicFloat128;
33use crate::round::RoundFinite;
34use crate::tangent::atan2::{ATAN_I, atan_eval, atan2_hard};
35
36#[cold]
39fn atan2pi_big_exp_difference_hard(
40 num: f64,
41 den: f64,
42 x_sign: usize,
43 y_sign: usize,
44 recip: bool,
45 final_sign: f64,
46) -> f64 {
47 const ZERO: DoubleDouble = DoubleDouble::new(0.0, 0.0);
48 const MZERO: DoubleDouble = DoubleDouble::new(-0.0, -0.0);
49 static CONST_ADJ_INV_PI: [[[DoubleDouble; 2]; 2]; 2] = [
50 [
51 [ZERO, DoubleDouble::new(0., -1. / 2.)],
52 [MZERO, DoubleDouble::new(0., -1. / 2.)],
53 ],
54 [
55 [DoubleDouble::new(0., -1.), DoubleDouble::new(0., 1. / 2.)],
56 [DoubleDouble::new(0., -1.), DoubleDouble::new(0., 1. / 2.)],
57 ],
58 ];
59 let const_term = CONST_ADJ_INV_PI[x_sign][y_sign][recip as usize];
60 let scaled_div = DyadicFloat128::from_div_f64(num, den) * INV_PI_F128;
61 let sign_f128 = DyadicFloat128::new_from_f64(final_sign);
62 let p = DyadicFloat128::new_from_f64(const_term.hi * final_sign);
63 let p1 = sign_f128 * (DyadicFloat128::new_from_f64(const_term.lo) + scaled_div);
64 let r = p + p1;
65 r.fast_as_f64()
66}
67
68pub fn f_atan2pi(y: f64, x: f64) -> f64 {
72 static IS_NEG: [f64; 2] = [1.0, -1.0];
73 const ZERO: DoubleDouble = DoubleDouble::new(0.0, 0.0);
74 const MZERO: DoubleDouble = DoubleDouble::new(-0.0, -0.0);
75 const PI: DoubleDouble = DoubleDouble::new(
76 f64::from_bits(0x3ca1a62633145c07),
77 f64::from_bits(0x400921fb54442d18),
78 );
79 const MPI: DoubleDouble = DoubleDouble::new(
80 f64::from_bits(0xbca1a62633145c07),
81 f64::from_bits(0xc00921fb54442d18),
82 );
83 const PI_OVER_2: DoubleDouble = DoubleDouble::new(
84 f64::from_bits(0x3c91a62633145c07),
85 f64::from_bits(0x3ff921fb54442d18),
86 );
87 const MPI_OVER_2: DoubleDouble = DoubleDouble::new(
88 f64::from_bits(0xbc91a62633145c07),
89 f64::from_bits(0xbff921fb54442d18),
90 );
91 const PI_OVER_4: DoubleDouble = DoubleDouble::new(
92 f64::from_bits(0x3c81a62633145c07),
93 f64::from_bits(0x3fe921fb54442d18),
94 );
95 const THREE_PI_OVER_4: DoubleDouble = DoubleDouble::new(
96 f64::from_bits(0x3c9a79394c9e8a0a),
97 f64::from_bits(0x4002d97c7f3321d2),
98 );
99
100 static CONST_ADJ: [[[DoubleDouble; 2]; 2]; 2] = [
103 [[ZERO, MPI_OVER_2], [MZERO, MPI_OVER_2]],
104 [[MPI, PI_OVER_2], [MPI, PI_OVER_2]],
105 ];
106
107 let x_sign = x.is_sign_negative() as usize;
108 let y_sign = y.is_sign_negative() as usize;
109 let x_bits = x.to_bits() & 0x7fff_ffff_ffff_ffff;
110 let y_bits = y.to_bits() & 0x7fff_ffff_ffff_ffff;
111 let x_abs = x_bits;
112 let y_abs = y_bits;
113 let recip = x_abs < y_abs;
114 let mut min_abs = if recip { x_abs } else { y_abs };
115 let mut max_abs = if !recip { x_abs } else { y_abs };
116 let mut min_exp = min_abs.wrapping_shr(52);
117 let mut max_exp = max_abs.wrapping_shr(52);
118
119 let mut num = f64::from_bits(min_abs);
120 let mut den = f64::from_bits(max_abs);
121
122 if max_exp > 0x7ffu64 - 128u64 || min_exp < 128u64 {
125 if x.is_nan() || y.is_nan() {
126 return f64::NAN;
127 }
128 let x_except = if x == 0.0 {
129 0
130 } else if x.is_infinite() {
131 2
132 } else {
133 1
134 };
135 let y_except = if y == 0.0 {
136 0
137 } else if y.is_infinite() {
138 2
139 } else {
140 1
141 };
142
143 static EXCEPTS: [[[DoubleDouble; 2]; 3]; 3] = [
150 [[ZERO, PI], [ZERO, PI], [ZERO, PI]],
151 [[PI_OVER_2, PI_OVER_2], [ZERO, ZERO], [ZERO, PI]],
152 [
153 [PI_OVER_2, PI_OVER_2],
154 [PI_OVER_2, PI_OVER_2],
155 [PI_OVER_4, THREE_PI_OVER_4],
156 ],
157 ];
158
159 if (x_except != 1) || (y_except != 1) {
160 let mut r = EXCEPTS[y_except][x_except][x_sign];
161 r = DoubleDouble::quick_mult(r, INV_PI_DD);
162 return f_fmla(IS_NEG[y_sign], r.hi, IS_NEG[y_sign] * r.lo);
163 }
164 let scale_up = min_exp < 128u64;
165 let scale_down = max_exp > 0x7ffu64 - 128u64;
166 if scale_up {
169 num *= f64::from_bits(0x43f0000000000000);
170 if !scale_down {
171 den *= f64::from_bits(0x43f0000000000000);
172 }
173 } else if scale_down {
174 den *= f64::from_bits(0x3bf0000000000000);
175 if !scale_up {
176 num *= f64::from_bits(0x3bf0000000000000);
177 }
178 }
179
180 min_abs = num.to_bits();
181 max_abs = den.to_bits();
182 min_exp = min_abs.wrapping_shr(52);
183 max_exp = max_abs.wrapping_shr(52);
184 }
185
186 let final_sign = IS_NEG[((x_sign != y_sign) != recip) as usize];
187 let const_term = CONST_ADJ[x_sign][y_sign][recip as usize];
188 let exp_diff = max_exp - min_exp;
189 if exp_diff > 54 {
192 if max_exp >= 1075 || min_exp < 970 {
193 return atan2pi_big_exp_difference_hard(num, den, x_sign, y_sign, recip, final_sign);
194 }
195 let z = DoubleDouble::from_exact_mult(final_sign, const_term.hi);
196 let mut divided = DoubleDouble::from_exact_div(num, den);
197 divided = DoubleDouble::f64_add(const_term.lo, divided);
198 divided = DoubleDouble::quick_mult_f64(divided, final_sign);
199 let r = DoubleDouble::add(z, divided);
200 let p = DoubleDouble::quick_mult(INV_PI_DD, r);
201 return p.to_f64();
202 }
203
204 let mut k = (64.0 * num / den).round_finite();
205 let idx = k as u64;
206 k *= f64::from_bits(0x3f90000000000000);
208
209 let num_k = DoubleDouble::from_exact_mult(num, k);
213 let den_k = DoubleDouble::from_exact_mult(den, k);
214
215 let num_dd = DoubleDouble::from_exact_add(num - den_k.hi, -den_k.lo);
217 let mut den_dd = DoubleDouble::from_exact_add(den, num_k.hi);
219 den_dd.lo += num_k.lo;
220
221 let q = DoubleDouble::div(num_dd, den_dd);
223 let p = atan_eval(q);
225
226 let vl = ATAN_I[idx as usize];
227 let vlo = DoubleDouble::from_bit_pair(vl);
228 let mut r = DoubleDouble::add(const_term, DoubleDouble::add(vlo, p));
229
230 r = DoubleDouble::quick_mult(r, INV_PI_DD);
231
232 let err = f_fmla(
233 p.hi,
234 f64::from_bits(0x3bd0000000000000),
235 f64::from_bits(0x3c00000000000000),
236 );
237
238 let ub = r.hi + (r.lo + err);
239 let lb = r.hi + (r.lo - err);
240
241 if ub == lb {
242 r.hi *= final_sign;
243 r.lo *= final_sign;
244
245 return r.to_f64();
246 }
247
248 (atan2_hard(y, x) * INV_PI_F128).fast_as_f64()
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn test_atan2pi() {
257 assert_eq!(
258 f_atan2pi(-0.000000000000010659658919444194, 2088960.4374061823),
259 -0.0000000000000000000016242886924270424
260 );
261 assert_eq!(f_atan2pi(-3.9999999981625933, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003577142133480227), -0.5);
262 assert_eq!(f_atan2pi(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000472842255026406,
263 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008045886150098693
264 ),1.8706499392673612e-162);
265 assert_eq!(f_atan2pi(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002670088630208647,
266 2.0000019071157054
267 ), 4.249573987697093e-307);
268 assert_eq!(f_atan2pi(-5., 2.), -0.3788810584091566);
269 assert_eq!(f_atan2pi(2., -5.), 0.8788810584091566);
270 }
271}