#![doc = include_str!("../README.md")]
pub use support::{Element, FloatElement, IntElement, MaskElement, SintElement, UintElement};
#[doc(hidden)]
pub mod __internal;
mod api;
mod arch;
pub mod column_major;
pub mod row_major;
mod swizzle;
mod utils;
#[cfg(all(algea_force_simd = "true", algea_force_simd = "false",))]
compile_error!("`algea_force_simd` cannot be both `true` and `false`");
#[cfg(all(algea_force_simd, not(any(algea_force_simd = "true", algea_force_simd = "false",)),))]
compile_error!("`algea_force_simd` must be `true` or `false`");
cfg_select! {
algea_force_simd = "true" => {
mod simd;
use simd::kernels;
}
algea_force_simd = "false" => {
mod non_simd;
use non_simd::kernels;
}
any(
target_feature = "sse2",
all(target_feature = "neon", target_arch = "aarch64"),
target_feature = "simd128",
) => {
mod simd;
use simd::kernels;
}
_ => {
mod non_simd;
use non_simd::kernels;
}
}
pub struct Vector<T: Element<D>, const D: usize> {
pub(crate) storage: <T as private::SealedElement<D, 1>>::Storage,
}
pub struct Mask<T: MaskElement<D>, const D: usize> {
pub(crate) storage: utils::MaskStorage<<T as private::SealedElement<D, 1>>::Storage>,
}
#[macro_export]
macro_rules! vector {
($elem:expr; $n:expr) => {
$crate::Vector::<_, $n>::splat($elem)
};
($a:expr $(,)?) => {
$crate::__internal::__IntoVector::__into_vector($a)
};
($a:expr, $b:expr $(,)?) => {
<$crate::__internal::__ConcatDispatch as $crate::__internal::__Concat2<_, _>>::__concat(
$crate::__internal::__IntoVector::__into_vector($a),
$crate::__internal::__IntoVector::__into_vector($b),
)
};
($a:expr, $b:expr, $c:expr $(,)?) => {
<$crate::__internal::__ConcatDispatch as $crate::__internal::__Concat3<_, _, _>>::__concat(
$crate::__internal::__IntoVector::__into_vector($a),
$crate::__internal::__IntoVector::__into_vector($b),
$crate::__internal::__IntoVector::__into_vector($c),
)
};
($a:expr, $b:expr, $c:expr, $d:expr $(,)?) => {
<$crate::__internal::__ConcatDispatch as $crate::__internal::__Concat4<_, _, _, _>>::__concat(
$crate::__internal::__IntoVector::__into_vector($a),
$crate::__internal::__IntoVector::__into_vector($b),
$crate::__internal::__IntoVector::__into_vector($c),
$crate::__internal::__IntoVector::__into_vector($d),
)
};
}
fn _assert_vector_macro_compile<T: Element>(
s: T,
a: Vector<T, 1>,
b: Vector<T, 2>,
c: Vector<T, 3>,
) {
_ = vector![s];
_ = vector![s, s];
_ = vector![s, s, s];
_ = vector![s, s, s, s];
_ = vector![a];
_ = vector![a, a];
_ = vector![a, a, a];
_ = vector![a, a, a, a];
_ = vector![b];
_ = vector![c];
_ = vector![c, a];
_ = vector![a, c];
_ = vector![b, a];
_ = vector![a, b];
_ = vector![b, a, a];
_ = vector![a, b, a];
_ = vector![a, a, b];
}
pub trait EachOrd {
fn each_max(self, other: Self) -> Self;
fn each_min(self, other: Self) -> Self;
fn each_clamp(self, min: Self, max: Self) -> Self;
}
pub trait Select<T> {
fn select(self, true_values: T, false_values: T) -> T;
}
macro_rules! impl_marker_trait {
($trait:ident for [$($t:ty $({ $($item:item)* })?),+ $(,)?]) => {
$(
impl $trait for $t {
$($($item)*)?
}
)+
};
}
macro_rules! impl_cast_from {
($self:ident from [$($t:ty),+]) => {
$(impl CastFrom<$t> for $self {})+
};
}
pub mod marker {
use crate::private;
#[expect(private_bounds)]
pub trait CastFrom<T>: private::Sealed {}
impl_cast_from!(f32 from [f32, f64, i32, i64, u32, u64]);
impl_cast_from!(f64 from [f32, f64, i32, i64, u32, u64]);
impl_cast_from!(i32 from [f32, f64, i32, i64, u32, u64]);
impl_cast_from!(i64 from [f32, f64, i32, i64, u32, u64]);
impl_cast_from!(u32 from [f32, f64, i32, i64, u32, u64]);
impl_cast_from!(u64 from [f32, f64, i32, i64, u32, u64]);
#[expect(private_bounds)]
pub trait NumOps:
Sized
+ private::Sealed
+ core::cmp::PartialEq
+ core::cmp::PartialOrd
+ core::ops::Add<Output = Self>
+ core::ops::Sub<Output = Self>
+ core::ops::Mul<Output = Self>
+ core::ops::Div<Output = Self>
+ core::ops::Rem<Output = Self>
{
}
impl<T> NumOps for T where
T: private::Sealed
+ core::cmp::PartialEq
+ core::cmp::PartialOrd
+ core::ops::Add<Output = T>
+ core::ops::Sub<Output = T>
+ core::ops::Mul<Output = T>
+ core::ops::Div<Output = T>
+ core::ops::Rem<Output = T>
{
}
#[expect(private_bounds)]
pub trait BitOps:
Sized
+ private::Sealed
+ core::ops::Not<Output = Self>
+ core::ops::BitAnd<Output = Self>
+ core::ops::BitOr<Output = Self>
+ core::ops::BitXor<Output = Self>
+ core::ops::Shr<Output = Self>
+ core::ops::Shl<Output = Self>
{
}
impl<T> BitOps for T where
T: private::Sealed
+ core::ops::Not<Output = Self>
+ core::ops::BitAnd<Output = Self>
+ core::ops::BitOr<Output = Self>
+ core::ops::BitXor<Output = Self>
+ core::ops::Shr<Output = Self>
+ core::ops::Shl<Output = Self>
{
}
#[expect(private_bounds)]
pub trait Signed: private::Sealed + Copy + core::ops::Neg<Output = Self> {}
#[expect(private_bounds)]
pub trait Unsigned: private::Sealed + Copy {}
#[expect(private_bounds)]
pub trait Int: private::Sealed + NumOps + BitOps {
type Signed: Sint;
type Unsigned: Uint;
}
pub trait Sint: Signed + Int<Signed = Self, Unsigned: Unsigned + Int<Signed = Self>> {}
pub trait Uint: Unsigned + Int<Unsigned = Self, Signed: Signed + Int<Unsigned = Self>> {}
pub trait Float: Signed + NumOps {
type Bits: Uint;
}
impl_marker_trait!(Signed for [f32, f64, i32, i64]);
impl_marker_trait!(Unsigned for [u32, u64]);
impl_marker_trait!(Int for [
i32 { type Signed = Self; type Unsigned = u32; },
i64 { type Signed = Self; type Unsigned = u64; },
u32 { type Signed = i32; type Unsigned = Self; },
u64 { type Signed = i64; type Unsigned = Self; },
]);
impl_marker_trait!(Sint for [i32, i64]);
impl_marker_trait!(Uint for [u32, u64]);
impl_marker_trait!(Float for [
f32 { type Bits = u32; },
f64 { type Bits = u64; },
]);
#[expect(private_bounds)]
pub trait StoredVerbatim: private::Sealed {}
impl_marker_trait!(StoredVerbatim for [f32, f64, i32, i64, u32, u64]);
#[expect(private_bounds)]
pub trait Lane: Copy + private::Sealed {
type Mask;
}
impl_marker_trait!(Lane for [
f32 { type Mask = i32; },
f64 { type Mask = i64; },
i32 { type Mask = i32; },
i64 { type Mask = i64; },
u32 { type Mask = i32; },
u64 { type Mask = i64; },
]);
}
pub mod support {
use crate::{Vector, column_major, marker::*, private, row_major};
#[expect(private_bounds)]
pub trait SupportedMatrixElement<const R: usize, const C: usize>:
private::SealedElement<R, C> + private::SealedElement<C, R>
{
}
macro_rules! impl_element {
([$($t:ty),+], $r:tt) => {
$(impl_element!{ type=$t, $r, $r })+
};
(type=$t:ty, [$($r:literal),+], $c:tt) => {
$(impl_element!{ type=$t, row=$r, $c })+
};
(type=$t:ty, row=$r:literal, [$($c:literal),+]) => {
$(impl SupportedMatrixElement<$r, $c> for $t {})+
};
}
impl_element!([f32, f64, i32, i64, u32, u64], [1, 2, 3, 4]);
macro_rules! impl_element2 {
({$($acc:tt)*}, $r:tt,) => {
impl_element2! { @a { $($acc)* }, $r, $r }
};
(@a {$($acc:tt)*}, [], $c:tt) => {
$($acc)* {}
};
(@a {$($acc:tt)*}, [$r0:expr $(, $r:expr)*], $c:tt) => {
impl_element2! { @b {$($acc)*}, $r0, [$($r),*], $c }
};
(@b {$($acc:tt)*}, $r0:expr, $r:tt, [$($c:expr),*]) => {
impl_element2!{ @a {
$($acc)* $(+ SupportedMatrixElement<$r0, $c>)*
}, $r, [$($c),*] }
};
}
macro_rules! impl_element3 {
({$($acc:tt)*}, $dims:tt $(,)?) => {
impl_element3! { @a {$($acc)*}, $dims, $dims, $dims }
};
(@a {$($acc:tt)*}, [], $bs:tt, $cs:tt) => {
$($acc)* {}
};
(@a {$($acc:tt)*}, [$a:expr $(, $as:expr)*], $bs:tt, $cs:tt) => {
impl_element3! { @b {$($acc)*}, $a, [$($as),*], $bs, $bs, $cs}
};
(@b {$($acc:tt)*}, $a:tt, $as:tt, [], $bs:tt, $cs:tt) => {
impl_element3! { @a {$($acc)*}, $as, $bs, $cs }
};
(@b {$($acc:tt)*}, $a:expr, $as:tt, [$b:expr $(, $bs_remaining:expr)*], $bs:tt, [$($c:expr),*]) => {
impl_element3! { @b {
$($acc)* $(+ row_major::MatrixProduct<$a, $b, $c> + column_major::MatrixProduct<$a, $b, $c>)*
}, $a, $as, [$($bs_remaining),*], $bs, [$($c),*]
}
};
}
impl_element2! {{
pub trait Element<const D0: usize = 1, const D1: usize = 1>:
Lane<Mask: MaskElement<D0, D1>>
}, [1, 2, 3, 4, D0, D1],
}
impl_element2! {{
impl<T, const D0: usize, const D1: usize> Element<D0, D1> for T
where T: Lane<Mask: MaskElement<D0, D1>>
}, [1, 2, 3, 4, D0, D1],
}
impl_element2! {{
pub trait MaskElement<const D0: usize = 1, const D1: usize = 1>:
Sint + Lane<Mask = Self>
}, [1, 2, 3, 4, D0, D1],
}
impl_element2! {{
impl<T, const D0: usize, const D1: usize> MaskElement<D0, D1> for T
where T: Sint + Lane<Mask = Self>
}, [1, 2, 3, 4, D0, D1],
}
impl_element3! {{
pub trait FloatElement<const D0: usize = 1, const D1: usize = 1>:
Element<D0, D1> + Float<Bits: Uint<Signed: Element<D0, D1>> + Element<D0, D1>>
}, [1, 2, 3, 4, D0, D1]
}
impl_element3! {{
impl<T, const D0: usize, const D1: usize> FloatElement<D0, D1> for T
where T: Element<D0, D1> + Float<Bits: Uint<Signed: Element<D0, D1>> + Element<D0, D1>>
}, [1, 2, 3, 4, D0, D1]
}
pub trait IntElement<const D0: usize = 1, const D1: usize = 1>:
Int<Signed: SintElement<D0, D1>, Unsigned: UintElement<D0, D1>> + Element<D0, D1>
{
}
pub trait SintElement<const D0: usize = 1, const D1: usize = 1>:
Sint<Unsigned: Element<D0, D1>> + Element<D0, D1>
{
}
pub trait UintElement<const D0: usize = 1, const D1: usize = 1>:
Uint<Signed: Element<D0, D1>> + Element<D0, D1>
{
}
impl<T, const D0: usize, const D1: usize> IntElement<D0, D1> for T where
T: Int<Signed: SintElement<D0, D1>, Unsigned: UintElement<D0, D1>> + Element<D0, D1>
{
}
impl<T, const D0: usize, const D1: usize> SintElement<D0, D1> for T where
T: Sint<Unsigned: Element<D0, D1>> + Element<D0, D1>
{
}
impl<T, const D0: usize, const D1: usize> UintElement<D0, D1> for T where
T: Uint<Signed: Element<D0, D1>> + Element<D0, D1>
{
}
mod integer_element_compile_checks {
use super::*;
fn _assert_unsigned_cast_relationships<T: UintElement>(a: Vector<T, 1>) {
_ = a.cast_signed().cast_unsigned().cast_signed();
_accept_integer_vector(a);
_accept_integer_vector(a.cast_signed());
_accept_integer_vector(a.cast_signed().cast_unsigned());
}
fn _accept_integer_vector<T: IntElement>(a: Vector<T, 1>) {
_assert_unsigned_cast_relationships(a.abs_diff(a))
}
fn _assert_float_bit_pattern_is_unsigned<T: FloatElement>(a: Vector<T, 1>) {
_assert_unsigned_cast_relationships(a.to_bits())
}
}
}
pub(crate) mod private {
use crate::{
marker::{Float, Lane, StoredVerbatim},
utils::MaskStorage,
};
pub(crate) trait Fmt {
fn fmt<T: SealedElement<M, N> + core::fmt::Debug, const M: usize, const N: usize>(
storage: impl crate::utils::Store<T::Storage>,
) -> impl core::fmt::Debug;
}
pub(crate) enum VectorFmt {}
pub(crate) enum Indices2<const I0: usize, const I1: usize> {}
pub(crate) enum Indices3<const I0: usize, const I1: usize, const I2: usize> {}
pub(crate) enum Indices4<const I0: usize, const I1: usize, const I2: usize, const I3: usize> {}
pub(crate) trait SwizzleDispatch<T, const M: usize, const N: usize> {
#[allow(dead_code)]
fn dispatch(v: <T as SealedElement<M, 1>>::Storage) -> <T as SealedElement<N, 1>>::Storage
where
T: SealedElement<M, 1> + SealedElement<N, 1>;
}
pub(crate) trait SwizzleDispatchAny<const N: usize>:
SwizzleDispatch<f32, 2, N>
+ SwizzleDispatch<f32, 3, N>
+ SwizzleDispatch<f32, 4, N>
+ SwizzleDispatch<i32, 2, N>
+ SwizzleDispatch<i32, 3, N>
+ SwizzleDispatch<i32, 4, N>
+ SwizzleDispatch<u32, 2, N>
+ SwizzleDispatch<u32, 3, N>
+ SwizzleDispatch<u32, 4, N>
+ SwizzleDispatch<f64, 2, N>
+ SwizzleDispatch<f64, 3, N>
+ SwizzleDispatch<f64, 4, N>
+ SwizzleDispatch<i64, 2, N>
+ SwizzleDispatch<i64, 3, N>
+ SwizzleDispatch<i64, 4, N>
+ SwizzleDispatch<u64, 2, N>
+ SwizzleDispatch<u64, 3, N>
+ SwizzleDispatch<u64, 4, N>
{
}
impl<T, const N: usize> SwizzleDispatchAny<N> for T where
T: SwizzleDispatch<f32, 2, N>
+ SwizzleDispatch<f32, 3, N>
+ SwizzleDispatch<f32, 4, N>
+ SwizzleDispatch<i32, 2, N>
+ SwizzleDispatch<i32, 3, N>
+ SwizzleDispatch<i32, 4, N>
+ SwizzleDispatch<u32, 2, N>
+ SwizzleDispatch<u32, 3, N>
+ SwizzleDispatch<u32, 4, N>
+ SwizzleDispatch<f64, 2, N>
+ SwizzleDispatch<f64, 3, N>
+ SwizzleDispatch<f64, 4, N>
+ SwizzleDispatch<i64, 2, N>
+ SwizzleDispatch<i64, 3, N>
+ SwizzleDispatch<i64, 4, N>
+ SwizzleDispatch<u64, 2, N>
+ SwizzleDispatch<u64, 3, N>
+ SwizzleDispatch<u64, 4, N>
{
}
impl Fmt for VectorFmt {
#[inline(never)]
fn fmt<T: SealedElement<M, N> + core::fmt::Debug, const M: usize, const N: usize>(
storage: impl crate::utils::Store<T::Storage>,
) -> impl core::fmt::Debug {
let array = T::to_array(storage.store());
assert_eq!(array.len(), 1);
array.into_iter().next().unwrap()
}
}
pub(crate) enum Type {
F32,
F64,
I32,
I64,
U32,
U64,
}
pub(crate) trait Sealed: Sized {
const TYPE: Type = panic!("TYPE is only defined for sealed scalar types");
fn sqrt(self) -> Self { unimplemented!() }
}
impl_marker_trait!(Sealed for [
f32 {
const TYPE: Type = Type::F32;
#[inline(always)] fn sqrt(self) -> Self { self.sqrt() }
},
f64 {
const TYPE: Type = Type::F64;
#[inline(always)] fn sqrt(self) -> Self { self.sqrt() }
},
i32 {
const TYPE: Type = Type::I32;
#[inline(always)] fn sqrt(self) -> Self { self.isqrt() }
},
i64 {
const TYPE: Type = Type::I64;
#[inline(always)] fn sqrt(self) -> Self { self.isqrt() }
},
u32 {
const TYPE: Type = Type::U32;
#[inline(always)] fn sqrt(self) -> Self { self.isqrt() }
},
u64 {
const TYPE: Type = Type::U64;
#[inline(always)] fn sqrt(self) -> Self { self.isqrt() }
},
]);
pub(crate) trait SealedElement<const M: usize, const N: usize>: Sealed {
type Storage: Copy;
const ZERO: Self::Storage;
const ONE: Self::Storage;
const IDENTITY: Self::Storage = unimplemented!();
const POS_X: Self::Storage = unimplemented!();
const POS_Y: Self::Storage = unimplemented!();
const POS_Z: Self::Storage = unimplemented!();
const POS_W: Self::Storage = unimplemented!();
const NEG_X: Self::Storage = unimplemented!();
const NEG_Y: Self::Storage = unimplemented!();
const NEG_Z: Self::Storage = unimplemented!();
const NEG_W: Self::Storage = unimplemented!();
fn map2(
a: Self::Storage,
b: Self::Storage,
f: impl FnMut(Self, Self) -> Self,
) -> Self::Storage;
fn index(_a: &Self::Storage, _index: (usize, usize)) -> Option<&Self> { unimplemented!() }
fn index_mut(_a: &mut Self::Storage, _index: (usize, usize)) -> Option<&mut Self> {
unimplemented!()
}
fn as_array_first(_a: &Self::Storage) -> &[Self; M] { unimplemented!() }
fn as_mut_array_first(_a: &mut Self::Storage) -> &mut [Self; M] { unimplemented!() }
fn to_array(a: Self::Storage) -> [[Self; M]; N];
fn from_array(array: [[Self; M]; N]) -> Self::Storage;
fn from_vecs(array: [crate::Vector<Self, M>; N]) -> <Self as SealedElement<M, N>>::Storage
where
Self: crate::Element<M>;
fn filled(value: Self) -> Self::Storage;
fn substantiate_f32(_a: Self::Storage) -> <f32 as SealedElement<M, N>>::Storage
where
f32: SealedElement<M, N>,
{
unimplemented!()
}
fn substantiate_f64(_a: Self::Storage) -> <f64 as SealedElement<M, N>>::Storage
where
f64: SealedElement<M, N>,
{
unimplemented!()
}
fn substantiate_i32(_a: Self::Storage) -> <i32 as SealedElement<M, N>>::Storage
where
i32: SealedElement<M, N>,
{
unimplemented!()
}
fn substantiate_i64(_a: Self::Storage) -> <i64 as SealedElement<M, N>>::Storage
where
i64: SealedElement<M, N>,
{
unimplemented!()
}
fn substantiate_u32(_a: Self::Storage) -> <u32 as SealedElement<M, N>>::Storage
where
u32: SealedElement<M, N>,
{
unimplemented!()
}
fn substantiate_u64(_a: Self::Storage) -> <u64 as SealedElement<M, N>>::Storage
where
u64: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_f32(_a: <f32 as SealedElement<M, N>>::Storage) -> Self::Storage
where
f32: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_f64(_a: <f64 as SealedElement<M, N>>::Storage) -> Self::Storage
where
f64: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_i32(_a: <i32 as SealedElement<M, N>>::Storage) -> Self::Storage
where
i32: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_i64(_a: <i64 as SealedElement<M, N>>::Storage) -> Self::Storage
where
i64: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_u32(_a: <u32 as SealedElement<M, N>>::Storage) -> Self::Storage
where
u32: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from_u64(_a: <u64 as SealedElement<M, N>>::Storage) -> Self::Storage
where
u64: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_from<U: SealedElement<M, N>>(
a: <U as SealedElement<M, N>>::Storage,
) -> Self::Storage;
fn cast_signed(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self::Signed as SealedElement<M, N>>::Storage
where
Self: crate::IntElement<M, N>,
{
unimplemented!()
}
fn cast_unsigned(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self::Unsigned as SealedElement<M, N>>::Storage
where
Self: crate::IntElement<M, N>,
{
unimplemented!()
}
fn swizzle2<const I0: usize, const I1: usize>(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<2, 1>>::Storage
where
Self: SealedElement<2, 1>,
Indices2<I0, I1>: SwizzleDispatchAny<2>,
{
unimplemented!()
}
fn swizzle3<const I0: usize, const I1: usize, const I2: usize>(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<3, 1>>::Storage
where
Self: SealedElement<3, 1>,
Indices3<I0, I1, I2>: SwizzleDispatchAny<3>,
{
unimplemented!()
}
fn swizzle4<const I0: usize, const I1: usize, const I2: usize, const I3: usize>(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<4, 1>>::Storage
where
Self: SealedElement<4, 1>,
Indices4<I0, I1, I2, I3>: SwizzleDispatchAny<4>,
{
unimplemented!()
}
fn select_mask(
_mask: MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>,
_true_values: <Self as SealedElement<M, N>>::Storage,
_false_values: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<M, N>>::Storage
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn select_any_mask<Mask>(
_mask: MaskStorage<<Mask as SealedElement<M, N>>::Storage>,
_true_values: <Self as SealedElement<M, N>>::Storage,
_false_values: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<M, N>>::Storage
where
Mask: SealedElement<M, N>,
{
unimplemented!()
}
#[expect(dead_code)]
fn select_u64(
_mask: u64,
_true_values: Self::Storage,
_false_values: Self::Storage,
) -> Self::Storage {
unimplemented!()
}
fn cast_i32(
_a: MaskStorage<Self::Storage>,
) -> MaskStorage<<i32 as SealedElement<M, N>>::Storage>
where
i32: SealedElement<M, N>,
{
unimplemented!()
}
fn cast_i64(
_a: MaskStorage<Self::Storage>,
) -> MaskStorage<<i64 as SealedElement<M, N>>::Storage>
where
i64: SealedElement<M, N>,
{
unimplemented!()
}
#[allow(clippy::wrong_self_convention)]
fn to_bool_array(_a: MaskStorage<Self::Storage>) -> [[bool; M]; N] { unimplemented!() }
fn from_bool_array(_array: [[bool; M]; N]) -> MaskStorage<Self::Storage> {
unimplemented!()
}
fn all(_mask: MaskStorage<Self::Storage>) -> bool { unimplemented!() }
fn any(_mask: MaskStorage<Self::Storage>) -> bool { unimplemented!() }
#[allow(clippy::wrong_self_convention)]
#[expect(dead_code)]
fn to_bitmask(_mask: MaskStorage<Self::Storage>) -> u64 { unimplemented!() }
fn canonical_not(_a: MaskStorage<Self::Storage>) -> MaskStorage<Self::Storage> {
unimplemented!()
}
fn canonical_bitand(
_a: MaskStorage<Self::Storage>,
_b: MaskStorage<Self::Storage>,
) -> MaskStorage<Self::Storage> {
unimplemented!()
}
fn canonical_bitor(
_a: MaskStorage<Self::Storage>,
_b: MaskStorage<Self::Storage>,
) -> MaskStorage<Self::Storage> {
unimplemented!()
}
fn canonical_bitxor(
_a: MaskStorage<Self::Storage>,
_b: MaskStorage<Self::Storage>,
) -> MaskStorage<Self::Storage> {
unimplemented!()
}
fn canonical_select_any_mask<Mask>(
_mask: MaskStorage<<Mask as SealedElement<M, N>>::Storage>,
_true_values: MaskStorage<<Self as SealedElement<M, N>>::Storage>,
_false_values: MaskStorage<<Self as SealedElement<M, N>>::Storage>,
) -> MaskStorage<<Self as SealedElement<M, N>>::Storage>
where
Mask: SealedElement<M, N>,
{
unimplemented!()
}
fn each_eq(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_ne(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_lt(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_le(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_gt(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_ge(
_a: Self::Storage,
_b: Self::Storage,
) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
#[expect(dead_code)]
fn is_nan(_a: Self::Storage) -> MaskStorage<<Self::Mask as SealedElement<M, N>>::Storage>
where
Self: Lane<Mask: SealedElement<M, N>>,
{
unimplemented!()
}
fn each_max(a: Self::Storage, b: Self::Storage) -> Self::Storage;
fn each_min(a: Self::Storage, b: Self::Storage) -> Self::Storage;
fn each_clamp<F: Fmt>(
a: Self::Storage,
min: Self::Storage,
max: Self::Storage,
) -> Self::Storage;
fn eq(a: Self::Storage, b: Self::Storage) -> bool;
fn ne(a: Self::Storage, b: Self::Storage) -> bool;
fn add(a: Self::Storage, b: Self::Storage) -> Self::Storage;
fn sub(a: Self::Storage, b: Self::Storage) -> Self::Storage;
fn mul(a: Self::Storage, b: Self::Storage) -> Self::Storage;
fn div(_a: Self::Storage, _b: Self::Storage) -> Self::Storage;
fn sqrt(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn transpose(
a: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<N, M>>::Storage
where
Self: SealedElement<N, M>;
fn from_bits(_a: <<Self as Float>::Bits as SealedElement<M, N>>::Storage) -> Self::Storage
where
Self: Float<Bits: SealedElement<M, N>>,
{
unimplemented!()
}
#[allow(clippy::wrong_self_convention)]
fn to_bits(_a: Self::Storage) -> <<Self as Float>::Bits as SealedElement<M, N>>::Storage
where
Self: Float<Bits: SealedElement<M, N>>,
{
unimplemented!()
}
fn floor(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn ceil(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn round(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn round_ties_even(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn trunc(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn fract(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn neg(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn abs(_a: Self::Storage) -> Self::Storage { unimplemented!() }
#[expect(dead_code)]
fn signum(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn rem(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn not(_a: Self::Storage) -> Self::Storage { unimplemented!() }
fn bitand(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn bitor(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn bitxor(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn shl(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn shr(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn reduce_sum(_a: Self::Storage) -> Self { unimplemented!() }
#[inline(always)]
fn dot(a: Self::Storage, b: Self::Storage) -> Self { Self::reduce_sum(Self::mul(a, b)) }
#[expect(dead_code)]
fn cross(_a: Self::Storage, _b: Self::Storage) -> Self::Storage { unimplemented!() }
fn vector_concat_1_1(
a: <Self as SealedElement<1, 1>>::Storage,
b: <Self as SealedElement<1, 1>>::Storage,
) -> <Self as SealedElement<2, 1>>::Storage
where
Self: SealedElement<1, 1> + SealedElement<2, 1>,
{
let [[a]] = <Self as SealedElement<1, 1>>::to_array(a);
let [[b]] = <Self as SealedElement<1, 1>>::to_array(b);
SealedElement::<2, 1>::from_array([[a, b]])
}
fn vector_concat_1_2(
a: <Self as SealedElement<1, 1>>::Storage,
b: <Self as SealedElement<2, 1>>::Storage,
) -> <Self as SealedElement<3, 1>>::Storage
where
Self: SealedElement<1, 1> + SealedElement<2, 1> + SealedElement<3, 1>,
{
let [[a]] = <Self as SealedElement<1, 1>>::to_array(a);
let [[b, c]] = <Self as SealedElement<2, 1>>::to_array(b);
SealedElement::<3, 1>::from_array([[a, b, c]])
}
fn vector_concat_2_1(
a: <Self as SealedElement<2, 1>>::Storage,
b: <Self as SealedElement<1, 1>>::Storage,
) -> <Self as SealedElement<3, 1>>::Storage
where
Self: SealedElement<1, 1> + SealedElement<2, 1> + SealedElement<3, 1>,
{
let [[a0, a1]] = <Self as SealedElement<2, 1>>::to_array(a);
let [[b0]] = <Self as SealedElement<1, 1>>::to_array(b);
SealedElement::<3, 1>::from_array([[a0, a1, b0]])
}
fn diagonal(
_a: <Self as SealedElement<M, N>>::Storage,
) -> <Self as SealedElement<N, 1>>::Storage
where
Self: SealedElement<N, 1>,
{
unimplemented!()
}
fn inverse(_a: Self::Storage) -> Self::Storage { unimplemented!() }
#[expect(dead_code)]
fn try_inverse(_a: Self::Storage) -> Option<Self::Storage> { unimplemented!() }
fn determinant(_a: Self::Storage) -> Self { unimplemented!() }
}
#[repr(C)]
pub struct XY<T: StoredVerbatim> {
pub x: T,
pub y: T,
}
#[repr(C)]
#[allow(clippy::upper_case_acronyms)] pub struct XYZ<T: StoredVerbatim> {
pub x: T,
pub y: T,
pub z: T,
}
#[repr(C)]
#[allow(clippy::upper_case_acronyms)] pub struct XYZW<T: StoredVerbatim> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
impl<T: StoredVerbatim> XY<T> {
#[inline(always)]
pub(crate) const fn from_array(array: &[T; 2]) -> &Self {
const {
assert!(size_of::<XY<T>>() == size_of::<[T; 2]>());
assert!(align_of::<XY<T>>() <= align_of::<[T; 2]>());
}
unsafe { &*(array as *const [T; 2] as *const Self) }
}
#[inline(always)]
pub(crate) const fn from_mut_array(array: &mut [T; 2]) -> &mut Self {
const {
assert!(size_of::<XY<T>>() == size_of::<[T; 2]>());
assert!(align_of::<XY<T>>() <= align_of::<[T; 2]>());
}
unsafe { &mut *(array as *mut [T; 2] as *mut Self) }
}
}
impl<T: StoredVerbatim> XYZ<T> {
#[inline(always)]
pub(crate) const fn from_array(array: &[T; 3]) -> &Self {
const {
assert!(size_of::<XYZ<T>>() == size_of::<[T; 3]>());
assert!(align_of::<XYZ<T>>() <= align_of::<[T; 3]>());
}
unsafe { &*(array as *const [T; 3] as *const Self) }
}
#[inline(always)]
pub(crate) const fn from_mut_array(array: &mut [T; 3]) -> &mut Self {
const {
assert!(size_of::<XYZ<T>>() == size_of::<[T; 3]>());
assert!(align_of::<XYZ<T>>() <= align_of::<[T; 3]>());
}
unsafe { &mut *(array as *mut [T; 3] as *mut Self) }
}
}
impl<T: StoredVerbatim> XYZW<T> {
#[inline(always)]
pub(crate) const fn from_array(array: &[T; 4]) -> &Self {
const {
assert!(size_of::<XYZW<T>>() == size_of::<[T; 4]>());
assert!(align_of::<XYZW<T>>() <= align_of::<[T; 4]>());
}
unsafe { &*(array as *const [T; 4] as *const Self) }
}
#[inline(always)]
pub(crate) const fn from_mut_array(array: &mut [T; 4]) -> &mut Self {
const {
assert!(size_of::<XYZW<T>>() == size_of::<[T; 4]>());
assert!(align_of::<XYZW<T>>() <= align_of::<[T; 4]>());
}
unsafe { &mut *(array as *mut [T; 4] as *mut Self) }
}
}
}