use core::fmt;
use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
use crate::Scalar;
use crate::Transcendental;
pub trait Vector<T: Scalar, const N: usize>:
Copy
+ Clone
+ Send
+ Sync
+ 'static
+ Default
+ PartialEq
+ fmt::Debug
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Rem<Output = Self>
+ Neg<Output = Self>
{
fn splat(value: T) -> Self;
fn load(slice: &[T]) -> Self;
fn store(&self, slice: &mut [T]);
fn extract(&self, index: usize) -> T;
fn insert(&self, index: usize, value: T) -> Self;
fn add(&self, other: &Self) -> Self;
fn sub(&self, other: &Self) -> Self;
fn mul(&self, other: &Self) -> Self;
fn div(&self, other: &Self) -> Self;
fn rem(&self, other: &Self) -> Self;
fn neg(&self) -> Self;
fn abs(&self) -> Self;
fn min(&self, other: &Self) -> Self;
fn max(&self, other: &Self) -> Self;
fn clamp(&self, min: &Self, max: &Self) -> Self;
}
pub trait VectorTranscendental<T: Transcendental, const N: usize>: Vector<T, N> {
fn sqrt(&self) -> Self;
fn exp(&self) -> Self;
fn ln(&self) -> Self;
fn sin(&self) -> Self;
fn cos(&self) -> Self;
fn tan(&self) -> Self;
}
pub trait VectorScalarOps<T: Scalar, const N: usize>: Vector<T, N> {
fn add_scalar(&self, scalar: T) -> Self {
self.add(&Self::splat(scalar))
}
fn sub_scalar(&self, scalar: T) -> Self {
self.sub(&Self::splat(scalar))
}
fn mul_scalar(&self, scalar: T) -> Self {
self.mul(&Self::splat(scalar))
}
fn div_scalar(&self, scalar: T) -> Self {
self.div(&Self::splat(scalar))
}
fn rem_scalar(&self, scalar: T) -> Self {
self.rem(&Self::splat(scalar))
}
}
impl<T: Scalar, const N: usize, V: Vector<T, N>> VectorScalarOps<T, N> for V {}
impl<T: Scalar, const N: usize, V: Vector<T, N>> VectorReduce<T, N> for V {}
pub trait VectorReduce<T: Scalar, const N: usize>: Vector<T, N> {
fn horizontal_sum(&self) -> T {
let mut sum = T::ZERO;
for i in 0..N {
sum += self.extract(i);
}
sum
}
fn horizontal_product(&self) -> T {
let mut prod = T::ONE;
for i in 0..N {
prod *= self.extract(i);
}
prod
}
fn horizontal_min(&self) -> T {
let mut min = self.extract(0);
for i in 1..N {
min = min.min(self.extract(i));
}
min
}
fn horizontal_max(&self) -> T {
let mut max = self.extract(0);
for i in 1..N {
max = max.max(self.extract(i));
}
max
}
fn horizontal_mean(&self) -> T {
let sum = self.horizontal_sum();
sum / T::from_usize(N)
}
}
pub trait VectorMask<T: Scalar, const N: usize> {
type Mask;
fn eq(&self, other: &Self) -> Self::Mask;
fn ne(&self, other: &Self) -> Self::Mask;
fn gt(&self, other: &Self) -> Self::Mask;
fn ge(&self, other: &Self) -> Self::Mask;
fn lt(&self, other: &Self) -> Self::Mask;
fn le(&self, other: &Self) -> Self::Mask;
fn select(&self, other: &Self, mask: Self::Mask) -> Self;
fn all(mask: &Self::Mask) -> bool;
}