use crate::prelude::OnceLock;
#[cfg(not(feature = "std"))]
use crate::prelude::OnceLockExt;
#[repr(C, align(64))]
pub(super) struct AlignedF64<const N: usize>(pub [f64; N]);
#[repr(C, align(64))]
pub(super) struct AlignedF32<const N: usize>(pub [f32; N]);
pub(super) struct TwiddlesF64<const N: usize> {
pub fwd: AlignedF64<N>,
pub inv: AlignedF64<N>,
}
pub(super) struct TwiddlesF32<const N: usize> {
pub fwd: AlignedF32<N>,
pub inv: AlignedF32<N>,
}
fn build_twiddles_f64<const N: usize>(n: usize) -> TwiddlesF64<N> {
let pairs = N / 2; let mut fwd = [0.0_f64; N];
let mut inv = [0.0_f64; N];
for k in 0..pairs {
let theta = core::f64::consts::TAU * (k as f64) / (n as f64);
let (s, c) = theta.sin_cos();
fwd[2 * k] = c; fwd[2 * k + 1] = -s; inv[2 * k] = c; inv[2 * k + 1] = s; }
TwiddlesF64 {
fwd: AlignedF64(fwd),
inv: AlignedF64(inv),
}
}
fn build_twiddles_f32<const N: usize>(n: usize) -> TwiddlesF32<N> {
let pairs = N / 2;
let mut fwd = [0.0_f32; N];
let mut inv = [0.0_f32; N];
for k in 0..pairs {
let theta = core::f32::consts::TAU * (k as f32) / (n as f32);
let (s, c) = theta.sin_cos();
fwd[2 * k] = c;
fwd[2 * k + 1] = -s;
inv[2 * k] = c;
inv[2 * k + 1] = s;
}
TwiddlesF32 {
fwd: AlignedF32(fwd),
inv: AlignedF32(inv),
}
}
pub(super) fn twiddles_16_f64() -> &'static TwiddlesF64<32> {
static ONCE: OnceLock<TwiddlesF64<32>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f64::<32>(16))
}
pub(super) fn twiddles_32_f64() -> &'static TwiddlesF64<64> {
static ONCE: OnceLock<TwiddlesF64<64>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f64::<64>(32))
}
pub(super) fn twiddles_64_f64() -> &'static TwiddlesF64<128> {
static ONCE: OnceLock<TwiddlesF64<128>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f64::<128>(64))
}
pub(super) fn twiddles_16_f32() -> &'static TwiddlesF32<32> {
static ONCE: OnceLock<TwiddlesF32<32>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f32::<32>(16))
}
pub(super) fn twiddles_32_f32() -> &'static TwiddlesF32<64> {
static ONCE: OnceLock<TwiddlesF32<64>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f32::<64>(32))
}
pub(super) fn twiddles_64_f32() -> &'static TwiddlesF32<128> {
static ONCE: OnceLock<TwiddlesF32<128>> = OnceLock::new();
ONCE.get_or_init(|| build_twiddles_f32::<128>(64))
}