use std::simd::{simd_swizzle, u32x16, u32x8};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use super::m31::PackedBaseField;
use super::utils::UnsafeMut;
use crate::core::fields::m31::P;
use crate::parallel_iter;
pub mod ifft;
pub mod rfft;
pub const CACHED_FFT_LOG_SIZE: u32 = 16;
pub const MIN_FFT_LOG_SIZE: u32 = 5;
pub unsafe fn transpose_vecs(values: *mut u32, log_n_vecs: usize) {
let half = log_n_vecs / 2;
let values = UnsafeMut(values);
parallel_iter!(0..1 << half).for_each(|a| {
let values = values.get();
for b in 0..1 << (log_n_vecs & 1) {
for c in 0..1 << half {
let i = (a << (log_n_vecs - half)) | (b << half) | c;
let j = (c << (log_n_vecs - half)) | (b << half) | a;
if i >= j {
continue;
}
let val0 = load(values.add(i << 4).cast_const());
let val1 = load(values.add(j << 4).cast_const());
store(values.add(i << 4), val1);
store(values.add(j << 4), val0);
}
}
});
}
pub fn compute_first_twiddles(twiddle1_dbl: u32x8) -> (u32x16, u32x16) {
let t1 = simd_swizzle!(
twiddle1_dbl,
twiddle1_dbl,
[0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7]
);
const P2: u32 = P * 2;
const NEGATION_MASK: u32x16 =
u32x16::from_array([0, P2, P2, 0, 0, P2, P2, 0, 0, P2, P2, 0, 0, P2, P2, 0]);
let t0 = simd_swizzle!(
t1,
[
0b0001, 0b0001, 0b0000, 0b0000, 0b0011, 0b0011, 0b0010, 0b0010, 0b0101, 0b0101, 0b0100,
0b0100, 0b0111, 0b0111, 0b0110, 0b0110,
]
) ^ NEGATION_MASK;
(t0, t1)
}
#[inline]
const unsafe fn load(mem_addr: *const u32) -> u32x16 {
std::ptr::read(mem_addr as *const u32x16)
}
#[inline]
const unsafe fn store(mem_addr: *mut u32, a: u32x16) {
std::ptr::write(mem_addr as *mut u32x16, a);
}
fn mul_twiddle(v: PackedBaseField, twiddle_dbl: u32x16) -> PackedBaseField {
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] {
crate::prover::backend::simd::m31::mul_doubled_neon(v, twiddle_dbl)
} else if #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] {
crate::prover::backend::simd::m31::mul_doubled_wasm(v, twiddle_dbl)
} else if #[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))] {
crate::prover::backend::simd::m31::mul_doubled_avx512(v, twiddle_dbl)
} else if #[cfg(all(target_arch = "x86_64", target_feature = "avx2"))] {
crate::prover::backend::simd::m31::mul_doubled_avx2(v, twiddle_dbl)
} else {
crate::prover::backend::simd::m31::mul_doubled_simd(v, twiddle_dbl)
}
}
}