use crate::astro::DEG_TO_RAD;
#[inline]
pub fn batch_sin_4(angles_deg: &[f64; 4]) -> [f64; 4] {
#[cfg(target_arch = "aarch64")]
{
[
(angles_deg[0] * DEG_TO_RAD).sin(),
(angles_deg[1] * DEG_TO_RAD).sin(),
(angles_deg[2] * DEG_TO_RAD).sin(),
(angles_deg[3] * DEG_TO_RAD).sin(),
]
}
#[cfg(not(target_arch = "aarch64"))]
{
[
(angles_deg[0] * DEG_TO_RAD).sin(),
(angles_deg[1] * DEG_TO_RAD).sin(),
(angles_deg[2] * DEG_TO_RAD).sin(),
(angles_deg[3] * DEG_TO_RAD).sin(),
]
}
}
#[inline]
pub fn batch_cos_4(angles_deg: &[f64; 4]) -> [f64; 4] {
#[cfg(target_arch = "aarch64")]
{
[
(angles_deg[0] * DEG_TO_RAD).cos(),
(angles_deg[1] * DEG_TO_RAD).cos(),
(angles_deg[2] * DEG_TO_RAD).cos(),
(angles_deg[3] * DEG_TO_RAD).cos(),
]
}
#[cfg(not(target_arch = "aarch64"))]
{
[
(angles_deg[0] * DEG_TO_RAD).cos(),
(angles_deg[1] * DEG_TO_RAD).cos(),
(angles_deg[2] * DEG_TO_RAD).cos(),
(angles_deg[3] * DEG_TO_RAD).cos(),
]
}
}
#[inline]
pub fn batch_sin_cos_4(angles_deg: &[f64; 4]) -> ([f64; 4], [f64; 4]) {
let sines = batch_sin_4(angles_deg);
let cosines = batch_cos_4(angles_deg);
(sines, cosines)
}
#[inline]
pub fn batch_atan2_4(y: &[f64; 4], x: &[f64; 4]) -> [f64; 4] {
[
y[0].atan2(x[0]),
y[1].atan2(x[1]),
y[2].atan2(x[2]),
y[3].atan2(x[3]),
]
}
#[inline]
pub fn batch_normalize_degrees_4(angles: &[f64; 4]) -> [f64; 4] {
const DEG_360: f64 = 360.0;
[
{
let mut a = angles[0] % DEG_360;
if a < 0.0 {
a += DEG_360;
}
a
},
{
let mut a = angles[1] % DEG_360;
if a < 0.0 {
a += DEG_360;
}
a
},
{
let mut a = angles[2] % DEG_360;
if a < 0.0 {
a += DEG_360;
}
a
},
{
let mut a = angles[3] % DEG_360;
if a < 0.0 {
a += DEG_360;
}
a
},
]
}
#[inline]
pub fn batch_altitude_4(
latitude_rad: f64,
declination_rad: &[f64; 4],
hour_angle_rad: &[f64; 4],
) -> [f64; 4] {
let sin_lat = latitude_rad.sin();
let cos_lat = latitude_rad.cos();
let sin_dec = [
declination_rad[0].sin(),
declination_rad[1].sin(),
declination_rad[2].sin(),
declination_rad[3].sin(),
];
let cos_dec = [
declination_rad[0].cos(),
declination_rad[1].cos(),
declination_rad[2].cos(),
declination_rad[3].cos(),
];
let cos_ha = [
hour_angle_rad[0].cos(),
hour_angle_rad[1].cos(),
hour_angle_rad[2].cos(),
hour_angle_rad[3].cos(),
];
[
(sin_lat * sin_dec[0] + cos_lat * cos_dec[0] * cos_ha[0]).asin(),
(sin_lat * sin_dec[1] + cos_lat * cos_dec[1] * cos_ha[1]).asin(),
(sin_lat * sin_dec[2] + cos_lat * cos_dec[2] * cos_ha[2]).asin(),
(sin_lat * sin_dec[3] + cos_lat * cos_dec[3] * cos_ha[3]).asin(),
]
}
#[inline]
pub fn batch_crosses_threshold_4(altitudes: &[f64; 4], threshold: f64) -> [bool; 4] {
[
altitudes[0] >= threshold,
altitudes[1] >= threshold,
altitudes[2] >= threshold,
altitudes[3] >= threshold,
]
}
#[inline]
pub fn batch_mul_4(a: &[f64; 4], b: &[f64; 4]) -> [f64; 4] {
[a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]]
}
#[inline]
pub fn batch_add_4(a: &[f64; 4], b: &[f64; 4]) -> [f64; 4] {
[a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_batch_sin_cos() {
let angles = [0.0, 90.0, 180.0, 270.0];
let (sines, cosines) = batch_sin_cos_4(&angles);
assert!((sines[0] - 0.0).abs() < 1e-10); assert!((sines[1] - 1.0).abs() < 1e-10); assert!((sines[2] - 0.0).abs() < 1e-10); assert!((sines[3] - (-1.0)).abs() < 1e-10);
assert!((cosines[0] - 1.0).abs() < 1e-10); assert!((cosines[1] - 0.0).abs() < 1e-10); assert!((cosines[2] - (-1.0)).abs() < 1e-10); assert!((cosines[3] - 0.0).abs() < 1e-10); }
#[test]
fn test_batch_normalize_degrees() {
let angles = [450.0, -90.0, 720.0, 270.0];
let normalized = batch_normalize_degrees_4(&angles);
assert_eq!(normalized[0], 90.0);
assert_eq!(normalized[1], 270.0);
assert_eq!(normalized[2], 0.0);
assert_eq!(normalized[3], 270.0);
}
#[test]
fn test_batch_atan2() {
let y = [1.0, 0.0, -1.0, 0.0];
let x = [0.0, 1.0, 0.0, -1.0];
let results = batch_atan2_4(&y, &x);
assert!((results[0] - std::f64::consts::PI / 2.0).abs() < 1e-10);
assert!(results[1].abs() < 1e-10);
assert!((results[2] - (-std::f64::consts::PI / 2.0)).abs() < 1e-10);
assert!((results[3].abs() - std::f64::consts::PI).abs() < 1e-10);
}
}