use crate::{
Affine, Aligned, Alignment, Length, Mask, Matrix, Quaternion, Scalar, SupportedLength,
Unaligned, Vector, utils::transmute_generic,
};
macro_rules! specialize {
(<$T:ty as $Backend:ident<$N:tt, $A:tt>>::$f:ident($($arg:expr),*$(,)?)) => {
(const {
$crate::utils::specialize_helper::<
$N,
$A,
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
>(
<$T as $Backend<2, $crate::Aligned>>::$f,
<$T as $Backend<3, $crate::Aligned>>::$f,
<$T as $Backend<4, $crate::Aligned>>::$f,
<$T as $Backend<2, $crate::Unaligned>>::$f,
<$T as $Backend<3, $crate::Unaligned>>::$f,
<$T as $Backend<4, $crate::Unaligned>>::$f,
)
})($($arg),*)
};
(<$T:ty as $Backend:ident<$A:tt>>::$f:ident($($arg:expr),*$(,)?)) => {
(const {
$crate::utils::specialize_helper::<
2,
$A,
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
>(
<$T as $Backend<$crate::Aligned>>::$f,
<$T as $Backend<$crate::Aligned>>::$f,
<$T as $Backend<$crate::Aligned>>::$f,
<$T as $Backend<$crate::Unaligned>>::$f,
<$T as $Backend<$crate::Unaligned>>::$f,
<$T as $Backend<$crate::Unaligned>>::$f,
)
})($($arg),*)
};
($Struct:ident::<$N:tt, $T:ident, $A:tt>::$f:ident($($arg:expr),*$(,)?)) => {
(const {
$crate::utils::specialize_helper::<
$N,
$A,
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
$crate::utils::specialize!(@fn($($arg),*)),
>(
<$Struct::<2, $T, $crate::Aligned>>::$f,
<$Struct::<3, $T, $crate::Aligned>>::$f,
<$Struct::<4, $T, $crate::Aligned>>::$f,
<$Struct::<2, $T, $crate::Unaligned>>::$f,
<$Struct::<3, $T, $crate::Unaligned>>::$f,
<$Struct::<4, $T, $crate::Unaligned>>::$f,
)
})($($arg),*)
};
(@fn()) => {
fn() -> _
};
(@fn($_0:expr)) => {
fn(_) -> _
};
(@fn($_0:expr, $_1:expr)) => {
fn(_, _) -> _
};
(@fn($_0:expr, $_1:expr, $_2:expr)) => {
fn(_, _, _) -> _
};
}
pub(crate) use specialize;
#[expect(private_bounds)]
pub const fn specialize_helper<const N: usize, A: Alignment, F2, F3, F4, F2U, F3U, F4U, F>(
f2: F2,
f3: F3,
f4: F4,
f2u: F2U,
f3u: F3U,
f4u: F4U,
) -> F
where
Length<N>: SupportedLength,
F2: Specialize<F, 2, N, Aligned, A> + Copy,
F3: Specialize<F, 3, N, Aligned, A> + Copy,
F4: Specialize<F, 4, N, Aligned, A> + Copy,
F2U: Specialize<F, 2, N, Unaligned, A> + Copy,
F3U: Specialize<F, 3, N, Unaligned, A> + Copy,
F4U: Specialize<F, 4, N, Unaligned, A> + Copy,
{
match (N, A::IS_ALIGNED) {
(2, true) => unsafe { transmute_generic::<F2, F>(f2) },
(3, true) => unsafe { transmute_generic::<F3, F>(f3) },
(4, true) => unsafe { transmute_generic::<F4, F>(f4) },
(2, false) => unsafe { transmute_generic::<F2U, F>(f2u) },
(3, false) => unsafe { transmute_generic::<F3U, F>(f3u) },
(4, false) => unsafe { transmute_generic::<F4U, F>(f4u) },
_ => unreachable!(),
}
}
unsafe trait Specialize<T2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
where
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<T, N, N2, A, A2> for T
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Vector<N2, T, A2>, N, N2, A, A2> for Vector<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a Vector<N2, T, A2>, N, N2, A, A2> for &'a Vector<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a mut Vector<N2, T, A2>, N, N2, A, A2> for &'a mut Vector<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Matrix<N2, T, A2>, N, N2, A, A2> for Matrix<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a Matrix<N2, T, A2>, N, N2, A, A2> for &'a Matrix<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a mut Matrix<N2, T, A2>, N, N2, A, A2> for &'a mut Matrix<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Quaternion<T, A2>, N, N2, A, A2> for Quaternion<T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Affine<N2, T, A2>, N, N2, A, A2> for Affine<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a Affine<N2, T, A2>, N, N2, A, A2> for &'a Affine<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a mut Affine<N2, T, A2>, N, N2, A, A2> for &'a mut Affine<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Mask<N2, T, A2>, N, N2, A, A2> for Mask<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a Mask<N2, T, A2>, N, N2, A, A2> for &'a Mask<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<'a, T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<&'a mut Mask<N2, T, A2>, N, N2, A, A2> for &'a mut Mask<N, T, A>
where
T: Scalar,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, T2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<[T2; N2], N, N2, A, A2> for [T; N]
where
T: Specialize<T2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<
'a,
T,
T2,
const N: usize,
const N1: usize,
const N2: usize,
A: Alignment,
A2: Alignment,
> Specialize<&'a [T2; N], N1, N2, A, A2> for &'a [T; N]
where
T: Specialize<T2, N1, N2, A, A2>,
Length<N1>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<(), N, N2, A, A2> for ()
where
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<(T,), N, N2, A, A2> for (T,)
where
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<Ta, Ta2, Tb, Tb2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<(Ta2, Tb2), N, N2, A, A2> for (Ta, Tb)
where
Ta: Specialize<Ta2, N, N2, A, A2>,
Tb: Specialize<Tb2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<T, T2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<Option<T2>, N, N2, A, A2> for Option<T>
where
T: Specialize<T2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<R, R2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<fn() -> R2, N, N2, A, A2> for fn() -> R
where
R: Specialize<R2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<Pa, Pa2, R, R2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<fn(Pa2) -> R2, N, N2, A, A2> for fn(Pa) -> R
where
Pa: Specialize<Pa2, N, N2, A, A2>,
R: Specialize<R2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<Pa, Pa2, Pb, Pb2, R, R2, const N: usize, const N2: usize, A: Alignment, A2: Alignment>
Specialize<fn(Pa2, Pb2) -> R2, N, N2, A, A2> for fn(Pa, Pb) -> R
where
Pa: Specialize<Pa2, N, N2, A, A2>,
Pb: Specialize<Pb2, N, N2, A, A2>,
R: Specialize<R2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}
unsafe impl<
Pa,
Pa2,
Pb,
Pb2,
Pc,
Pc2,
R,
R2,
const N: usize,
const N2: usize,
A: Alignment,
A2: Alignment,
> Specialize<fn(Pa2, Pb2, Pc2) -> R2, N, N2, A, A2> for fn(Pa, Pb, Pc) -> R
where
Pa: Specialize<Pa2, N, N2, A, A2>,
Pb: Specialize<Pb2, N, N2, A, A2>,
Pc: Specialize<Pc2, N, N2, A, A2>,
R: Specialize<R2, N, N2, A, A2>,
Length<N>: SupportedLength,
Length<N2>: SupportedLength,
{
}