use super::traits::{Vector, VectorTranscendental};
use crate::Transcendental;
pub fn sin_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.sin();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].sin();
}
}
}
pub fn cos_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.cos();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].cos();
}
}
}
pub fn tan_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.tan();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].tan();
}
}
}
pub fn exp_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.exp();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].exp();
}
}
}
pub fn ln_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.ln();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].ln();
}
}
}
pub fn sqrt_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: VectorTranscendental<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.sqrt();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].sqrt();
}
}
}
pub fn abs_slice<T: Transcendental, const N: usize, V>(input: &[T], output: &mut [T])
where
V: Vector<T, N>,
{
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let vec = V::load(&input[start..start + N]);
let result = vec.abs();
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].abs();
}
}
}
pub fn min_slice<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], output: &mut [T])
where
V: Vector<T, N>,
{
assert_eq!(a.len(), b.len());
assert_eq!(a.len(), output.len());
let chunks = a.len() / N;
let remainder = a.len() % N;
for i in 0..chunks {
let start = i * N;
let a_vec = V::load(&a[start..start + N]);
let b_vec = V::load(&b[start..start + N]);
let result = a_vec.min(&b_vec);
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = a[start + i].min(b[start + i]);
}
}
}
pub fn max_slice<T: Transcendental, const N: usize, V>(a: &[T], b: &[T], output: &mut [T])
where
V: Vector<T, N>,
{
assert_eq!(a.len(), b.len());
assert_eq!(a.len(), output.len());
let chunks = a.len() / N;
let remainder = a.len() % N;
for i in 0..chunks {
let start = i * N;
let a_vec = V::load(&a[start..start + N]);
let b_vec = V::load(&b[start..start + N]);
let result = a_vec.max(&b_vec);
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = a[start + i].max(b[start + i]);
}
}
}
pub fn clamp_slice<T: Transcendental, const N: usize, V>(
input: &[T],
min: &[T],
max: &[T],
output: &mut [T],
) where
V: Vector<T, N>,
{
assert_eq!(input.len(), min.len());
assert_eq!(input.len(), max.len());
assert_eq!(input.len(), output.len());
let chunks = input.len() / N;
let remainder = input.len() % N;
for i in 0..chunks {
let start = i * N;
let input_vec = V::load(&input[start..start + N]);
let min_vec = V::load(&min[start..start + N]);
let max_vec = V::load(&max[start..start + N]);
let result = input_vec.clamp(&min_vec, &max_vec);
result.store(&mut output[start..start + N]);
}
if remainder > 0 {
let start = chunks * N;
for i in 0..remainder {
output[start + i] = input[start + i].clamp(min[start + i], max[start + i]);
}
}
}
#[cfg(feature = "fast_math")]
pub fn fast_sin_slice_f32(input: &[f32], output: &mut [f32]) {
sin_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
}
#[cfg(feature = "fast_math")]
pub fn fast_cos_slice_f32(input: &[f32], output: &mut [f32]) {
cos_slice::<f32, 4, crate::math::vector::scalar::ScalarVector4<f32>>(input, output);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Transcendental;
}