#[allow(unused_imports)]
#[cfg(feature = "libm")]
use crate::math::F64Math;
use crate::{
generated_sinh_approximator::SINH_5, keplers_equation, keplers_equation_derivative,
keplers_equation_second_derivative, sinhcosh, solve_monotone_cubic, B, NUMERIC_MAX_ITERS,
N_F64, N_U32,
};
use core::f64::consts::{PI, TAU};
pub(crate) fn get_approx_hyperbolic_eccentric_anomaly(eccentricity: f64, mean_anomaly: f64) -> f64 {
let sign = mean_anomaly.signum();
let mean_anomaly = mean_anomaly.abs();
sign * if mean_anomaly < eccentricity * SINH_5 - 5.0 {
use crate::generated_sinh_approximator::get_sinh_approx_params;
let params = get_sinh_approx_params(mean_anomaly);
let mean_anom_plus_a = mean_anomaly + params.a;
let coeff_a = eccentricity * params.p_3 - params.q_2;
let coeff_b = eccentricity * params.p_2 - mean_anom_plus_a * params.q_2 - params.q_1;
let coeff_c = eccentricity * params.p_1 - mean_anom_plus_a * params.q_1 - 1.0;
let coeff_d = eccentricity * params.s - mean_anomaly - params.a;
let u = solve_monotone_cubic(coeff_a, coeff_b, coeff_c, coeff_d);
u + params.a
} else {
let rough_guess = (2.0 * mean_anomaly / eccentricity).ln();
let (c_a, s_a) = {
let left = 2.0 * mean_anomaly / eccentricity;
let right = eccentricity / (2.0 * mean_anomaly);
(0.5 * (left + right), 0.5 * (left - right))
};
let alpha = eccentricity * eccentricity / (4.0 * mean_anomaly) + rough_guess;
let beta = (eccentricity * c_a - 1.0).recip();
let gamma = alpha * beta;
let gamma_sq = gamma * gamma;
let delta = (6.0 * alpha * beta + 3.0 * (eccentricity * s_a * beta) * gamma_sq)
/ (6.0
+ 6.0 * (eccentricity * s_a * beta) * gamma
+ (eccentricity * c_a * beta) * gamma_sq);
rough_guess + delta
}
}
pub(crate) fn get_hyperbolic_eccentric_anomaly(eccentricity: f64, mean_anomaly: f64) -> f64 {
let mut ecc_anom = get_approx_hyperbolic_eccentric_anomaly(eccentricity, mean_anomaly);
for _ in 0..NUMERIC_MAX_ITERS {
let (sinh_eca, cosh_eca) = sinhcosh(ecc_anom);
let hppp = eccentricity * cosh_eca;
let hp = hppp - 1.0;
let hpp = eccentricity * sinh_eca;
let h = hpp - ecc_anom - mean_anomaly;
let h_sq = h * h;
let r = hp.recip();
let r_sq = r * r;
let r_cub = r_sq * r;
let denominator = 6.0 - 6.0 * h * hpp * r_sq + h_sq * hppp * r_cub;
if denominator.abs() < 1e-30 || !denominator.is_finite() {
break;
}
let numerator = 6.0 * h * r - 3.0 * h_sq * hpp * r_cub;
let delta = numerator / denominator;
ecc_anom -= delta;
if delta.abs() < 1e-12 {
break;
}
}
ecc_anom
}
pub(crate) fn get_elliptic_eccentric_anomaly(eccentricity: f64, mut mean_anomaly: f64) -> f64 {
let mut sign = 1.0;
mean_anomaly %= TAU;
if mean_anomaly > PI {
mean_anomaly -= TAU;
}
if mean_anomaly < 0.0 {
mean_anomaly = -mean_anomaly;
sign = -1.0;
}
let mut eccentric_anomaly = mean_anomaly
+ (4.0 * eccentricity * B * mean_anomaly * (PI - mean_anomaly))
/ (8.0 * eccentricity * mean_anomaly
+ 4.0 * eccentricity * (eccentricity - PI)
+ (PI * PI));
for _ in 2..N_U32 {
let f = keplers_equation(mean_anomaly, eccentric_anomaly, eccentricity);
let fp = keplers_equation_derivative(eccentric_anomaly, eccentricity);
let fpp = keplers_equation_second_derivative(eccentric_anomaly, eccentricity);
let n = N_F64;
let n_minus_1 = n - 1.0;
let d = ((n_minus_1 * n_minus_1) * fp * fp - n * n_minus_1 * f * fpp)
.abs()
.sqrt()
.copysign(fp);
let denominator = n * f / (fp + d.max(1e-30));
eccentric_anomaly -= denominator;
if denominator.abs() < 1e-30 || !denominator.is_finite() {
break;
}
}
eccentric_anomaly * sign
}