use core::{mem::MaybeUninit, ops::Add};
use crate::{
common,
numeric::{One, Zero},
scalar::{HasScalar, Scalar},
tuple::Tuple,
};
impl<T, const N: usize> Tuple<T, N> {
#[inline]
pub const fn from_array(inner: [T; N]) -> Self {
Self { inner }
}
#[inline]
pub const fn splat(value: T) -> Self
where
T: Copy,
{
Self::from_array([value; N])
}
#[inline]
pub fn iota() -> Self
where
T: Zero + One + Add<Output = T> + Copy,
{
let mut out = [T::ZERO; N];
let mut value = T::ZERO;
for item in &mut out {
*item = value;
value = value + T::ONE;
}
Self::from_array(out)
}
#[inline]
pub const fn len(&self) -> usize {
N
}
#[inline]
pub const fn is_empty(&self) -> bool {
N == 0
}
#[inline]
pub const fn as_array(&self) -> &[T; N] {
&self.inner
}
#[inline]
pub fn into_array(self) -> [T; N] {
self.inner
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&self.inner
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.inner
}
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.inner.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
self.inner.iter_mut()
}
#[inline]
pub fn map<U, F>(self, f: F) -> Tuple<U, N>
where
F: FnMut(T) -> U,
{
Tuple::from_array(self.inner.map(f))
}
#[inline]
pub fn try_map<U, E, F>(self, mut f: F) -> Result<Tuple<U, N>, E>
where
F: FnMut(T) -> Result<U, E>,
{
let mut output: [MaybeUninit<U>; N] = [const { MaybeUninit::uninit() }; N];
for (index, value) in self.inner.into_iter().enumerate() {
output[index].write(f(value)?);
}
let output = unsafe { core::mem::transmute_copy::<[MaybeUninit<U>; N], [U; N]>(&output) };
Ok(Tuple::from_array(output))
}
#[inline]
pub fn map_ref<U, F>(&self, f: F) -> Tuple<U, N>
where
F: FnMut(&T) -> U,
{
Tuple::from_array(self.inner.each_ref().map(f))
}
#[inline]
pub fn zip_with<U, V, F>(&self, rhs: &Tuple<U, N>, mut f: F) -> Tuple<V, N>
where
F: FnMut(&T, &U) -> V,
{
Tuple::from_array(core::array::from_fn(|i| f(&self.inner[i], &rhs.inner[i])))
}
#[inline]
pub fn zip<'a, U>(&'a self, rhs: &'a Tuple<U, N>) -> Tuple<(&'a T, &'a U), N> {
Tuple::from_array(core::array::from_fn(|i| (&self.inner[i], &rhs.inner[i])))
}
}
common::impl_tuplelike_for_wrapper!([T, const N: usize], Tuple<T, N>, item: T, len: N);
common::impl_bytemuck_basic!([T, const N: usize], Tuple<T, N>, item: T);
impl<T, const N: usize> HasScalar for Tuple<T, N>
where
T: Scalar,
{
type Scalar = T;
}