polylane 0.15.0

Portable and versatile SIMD.
Documentation
// Copyright 2025 Gabriel Bjørnager Jensen.
//
// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, you
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.

//! SIMD conversion facilities.

mod simd_scalar_cast;

pub use simd_scalar_cast::SimdScalarCast;

use crate::detail::DataKind;
use crate::simd::SimdScalar;

use core::mem::ManuallyDrop;

#[expect(clippy::ptr_cast_constness)]
#[inline(always)]
#[must_use]
#[track_caller]
pub(crate) const fn simd_scalar_cast<T, U>(value: T) -> U
where
	T: SimdScalar,
	U: SimdScalar,
{
	#[inline(always)]
	#[must_use]
	#[track_caller]
	const fn sidecast<T, U>(value: T) -> U
	where
		T: SimdScalar,
		U: SimdScalar,
	{
		assert!(T::DATA_KIND as u8 == U::DATA_KIND as u8);

		union Transmute<Src, Dst> {
			src: ManuallyDrop<Src>,
			dst: ManuallyDrop<Dst>,
		}

		let transmute = Transmute { src: ManuallyDrop::new(value) };
		unsafe { ManuallyDrop::into_inner(transmute.dst) }
	}

	macro_rules! casts {
		{ $(($InKind:ident = $InTy:ty) => ($OutKind:ident = $OutTy:ty) $(= ($($feature:literal),*$(,)?))?),*$(,)? } => {{
			match (T::DATA_KIND, U::DATA_KIND) {
				$(
					$(#[cfg(all($(feature = $feature, )*))])?
					(DataKind::$InKind, DataKind::$OutKind) => sidecast::<$OutTy, U>(sidecast::<T, $InTy>(value) as $OutTy),
				)*

				_ => unreachable!(),
			}
		}};
	}

	casts! {
		(U8 = u8) => (U8       = u8),
		(U8 = u8) => (I8       = i8),
		(U8 = u8) => (U16      = u16),
		(U8 = u8) => (I16      = i16),
		(U8 = u8) => (U32      = u32),
		(U8 = u8) => (I32      = i32),
		(U8 = u8) => (U64      = u64),
		(U8 = u8) => (I64      = i64),
		(U8 = u8) => (U128     = u128),
		(U8 = u8) => (I128     = i128),
		(U8 = u8) => (Usize    = usize),
		(U8 = u8) => (Isize    = isize),
		(U8 = u8) => (F16      = f16)       = ("f16"),
		(U8 = u8) => (F32      = f32),
		(U8 = u8) => (F64      = f64),
		(U8 = u8) => (F128     = f128)      = ("f128"),
		(U8 = u8) => (ConstPtr = *const ()),
		(U8 = u8) => (MutPtr   = *mut ()),

		(I8 = i8) => (U8       = u8),
		(I8 = i8) => (I8       = i8),
		(I8 = i8) => (U16      = u16),
		(I8 = i8) => (I16      = i16),
		(I8 = i8) => (U32      = u32),
		(I8 = i8) => (I32      = i32),
		(I8 = i8) => (U64      = u64),
		(I8 = i8) => (I64      = i64),
		(I8 = i8) => (U128     = u128),
		(I8 = i8) => (I128     = i128),
		(I8 = i8) => (Usize    = usize),
		(I8 = i8) => (Isize    = isize),
		(I8 = i8) => (F16      = f16)       = ("f16"),
		(I8 = i8) => (F32      = f32),
		(I8 = i8) => (F64      = f64),
		(I8 = i8) => (F128     = f128)      = ("f128"),
		(I8 = i8) => (ConstPtr = *const ()),
		(I8 = i8) => (MutPtr   = *mut ()),

		(U16 = u16) => (U8       = u8),
		(U16 = u16) => (I8       = i8),
		(U16 = u16) => (U16      = u16),
		(U16 = u16) => (I16      = i16),
		(U16 = u16) => (U32      = u32),
		(U16 = u16) => (I32      = i32),
		(U16 = u16) => (U64      = u64),
		(U16 = u16) => (I64      = i64),
		(U16 = u16) => (U128     = u128),
		(U16 = u16) => (I128     = i128),
		(U16 = u16) => (Usize    = usize),
		(U16 = u16) => (Isize    = isize),
		(U16 = u16) => (F16      = f16)       = ("f16"),
		(U16 = u16) => (F32      = f32),
		(U16 = u16) => (F64      = f64),
		(U16 = u16) => (F128     = f128)      = ("f128"),
		(U16 = u16) => (ConstPtr = *const ()),
		(U16 = u16) => (MutPtr   = *mut ()),

		(I16 = i16) => (U8       = u8),
		(I16 = i16) => (I8       = i8),
		(I16 = i16) => (U16      = u16),
		(I16 = i16) => (I16      = i16),
		(I16 = i16) => (U32      = u32),
		(I16 = i16) => (I32      = i32),
		(I16 = i16) => (U64      = u64),
		(I16 = i16) => (I64      = i64),
		(I16 = i16) => (U128     = u128),
		(I16 = i16) => (I128     = i128),
		(I16 = i16) => (Usize    = usize),
		(I16 = i16) => (Isize    = isize),
		(I16 = i16) => (F16      = f16)       = ("f16"),
		(I16 = i16) => (F32      = f32),
		(I16 = i16) => (F64      = f64),
		(I16 = i16) => (F128     = f128)      = ("f128"),
		(I16 = i16) => (ConstPtr = *const ()),
		(I16 = i16) => (MutPtr   = *mut ()),

		(U32 = u32) => (U8       = u8),
		(U32 = u32) => (I8       = i8),
		(U32 = u32) => (U16      = u16),
		(U32 = u32) => (I16      = i16),
		(U32 = u32) => (U32      = u32),
		(U32 = u32) => (I32      = i32),
		(U32 = u32) => (U64      = u64),
		(U32 = u32) => (I64      = i64),
		(U32 = u32) => (U128     = u128),
		(U32 = u32) => (I128     = i128),
		(U32 = u32) => (Usize    = usize),
		(U32 = u32) => (Isize    = isize),
		(U32 = u32) => (F16      = f16)       = ("f16"),
		(U32 = u32) => (F32      = f32),
		(U32 = u32) => (F64      = f64),
		(U32 = u32) => (F128     = f128)      = ("f128"),
		(U32 = u32) => (ConstPtr = *const ()),
		(U32 = u32) => (MutPtr   = *mut ()),

		(I32 = i32) => (U8       = u8),
		(I32 = i32) => (I8       = i8),
		(I32 = i32) => (U16      = u16),
		(I32 = i32) => (I16      = i16),
		(I32 = i32) => (U32      = u32),
		(I32 = i32) => (I32      = i32),
		(I32 = i32) => (U64      = u64),
		(I32 = i32) => (I64      = i64),
		(I32 = i32) => (U128     = u128),
		(I32 = i32) => (I128     = i128),
		(I32 = i32) => (Usize    = usize),
		(I32 = i32) => (Isize    = isize),
		(I32 = i32) => (F16      = f16)       = ("f16"),
		(I32 = i32) => (F32      = f32),
		(I32 = i32) => (F64      = f64),
		(I32 = i32) => (F128     = f128)      = ("f128"),
		(I32 = i32) => (ConstPtr = *const ()),
		(I32 = i32) => (MutPtr   = *mut ()),

		(U64 = u64) => (U8       = u8),
		(U64 = u64) => (I8       = i8),
		(U64 = u64) => (U16      = u16),
		(U64 = u64) => (I16      = i16),
		(U64 = u64) => (U32      = u32),
		(U64 = u64) => (I32      = i32),
		(U64 = u64) => (U64      = u64),
		(U64 = u64) => (I64      = i64),
		(U64 = u64) => (U128     = u128),
		(U64 = u64) => (I128     = i128),
		(U64 = u64) => (Usize    = usize),
		(U64 = u64) => (Isize    = isize),
		(U64 = u64) => (F16      = f16)       = ("f16"),
		(U64 = u64) => (F32      = f32),
		(U64 = u64) => (F64      = f64),
		(U64 = u64) => (F128     = f128)      = ("f128"),
		(U64 = u64) => (ConstPtr = *const ()),
		(U64 = u64) => (MutPtr   = *mut ()),

		(I64 = i64) => (U8       = u8),
		(I64 = i64) => (I8       = i8),
		(I64 = i64) => (U16      = u16),
		(I64 = i64) => (I16      = i16),
		(I64 = i64) => (U32      = u32),
		(I64 = i64) => (I32      = i32),
		(I64 = i64) => (U64      = u64),
		(I64 = i64) => (I64      = i64),
		(I64 = i64) => (U128     = u128),
		(I64 = i64) => (I128     = i128),
		(I64 = i64) => (Usize    = usize),
		(I64 = i64) => (Isize    = isize),
		(I64 = i64) => (F16      = f16)       = ("f16"),
		(I64 = i64) => (F32      = f32),
		(I64 = i64) => (F64      = f64),
		(I64 = i64) => (F128     = f128)      = ("f128"),
		(I64 = i64) => (ConstPtr = *const ()),
		(I64 = i64) => (MutPtr   = *mut ()),

		(U128 = u128) => (U8       = u8),
		(U128 = u128) => (I8       = i8),
		(U128 = u128) => (U16      = u16),
		(U128 = u128) => (I16      = i16),
		(U128 = u128) => (U32      = u32),
		(U128 = u128) => (I32      = i32),
		(U128 = u128) => (U64      = u64),
		(U128 = u128) => (I64      = i64),
		(U128 = u128) => (U128     = u128),
		(U128 = u128) => (I128     = i128),
		(U128 = u128) => (Usize    = usize),
		(U128 = u128) => (Isize    = isize),
		(U128 = u128) => (F16      = f16)       = ("f16"),
		(U128 = u128) => (F32      = f32),
		(U128 = u128) => (F64      = f64),
		(U128 = u128) => (F128     = f128)      = ("f128"),
		(U128 = u128) => (ConstPtr = *const ()),
		(U128 = u128) => (MutPtr   = *mut ()),

		(I128 = i128) => (U8       = u8),
		(I128 = i128) => (I8       = i8),
		(I128 = i128) => (U16      = u16),
		(I128 = i128) => (I16      = i16),
		(I128 = i128) => (U32      = u32),
		(I128 = i128) => (I32      = i32),
		(I128 = i128) => (U64      = u64),
		(I128 = i128) => (I64      = i64),
		(I128 = i128) => (U128     = u128),
		(I128 = i128) => (I128     = i128),
		(I128 = i128) => (Usize    = usize),
		(I128 = i128) => (Isize    = isize),
		(I128 = i128) => (F16      = f16)       = ("f16"),
		(I128 = i128) => (F32      = f32),
		(I128 = i128) => (F64      = f64),
		(I128 = i128) => (F128     = f128)      = ("f128"),
		(I128 = i128) => (ConstPtr = *const ()),
		(I128 = i128) => (MutPtr   = *mut ()),

		(Usize = usize) => (U8       = u8),
		(Usize = usize) => (I8       = i8),
		(Usize = usize) => (U16      = u16),
		(Usize = usize) => (I16      = i16),
		(Usize = usize) => (U32      = u32),
		(Usize = usize) => (I32      = i32),
		(Usize = usize) => (U64      = u64),
		(Usize = usize) => (I64      = i64),
		(Usize = usize) => (U128     = u128),
		(Usize = usize) => (I128     = i128),
		(Usize = usize) => (Usize    = usize),
		(Usize = usize) => (Isize    = isize),
		(Usize = usize) => (F16      = f16)       = ("f16"),
		(Usize = usize) => (F32      = f32),
		(Usize = usize) => (F64      = f64),
		(Usize = usize) => (F128     = f128)      = ("f128"),
		(Usize = usize) => (ConstPtr = *const ()),
		(Usize = usize) => (MutPtr   = *mut ()),

		(Isize = usize) => (U8       = u8),
		(Isize = usize) => (I8       = i8),
		(Isize = usize) => (U16      = u16),
		(Isize = usize) => (I16      = i16),
		(Isize = usize) => (U32      = u32),
		(Isize = usize) => (I32      = i32),
		(Isize = usize) => (U64      = u64),
		(Isize = usize) => (I64      = i64),
		(Isize = usize) => (U128     = u128),
		(Isize = usize) => (I128     = i128),
		(Isize = usize) => (Usize    = usize),
		(Isize = usize) => (Isize    = isize),
		(Isize = usize) => (F16      = f16)       = ("f16"),
		(Isize = usize) => (F32      = f32),
		(Isize = usize) => (F64      = f64),
		(Isize = usize) => (F128     = f128)      = ("f128"),
		(Isize = usize) => (ConstPtr = *const ()),
		(Isize = usize) => (MutPtr   = *mut ()),

		(F16 = f16) => (U8    = u8)    = ("f16"),
		(F16 = f16) => (I8    = i8)    = ("f16"),
		(F16 = f16) => (U16   = u16)   = ("f16"),
		(F16 = f16) => (I16   = i16)   = ("f16"),
		(F16 = f16) => (U32   = u32)   = ("f16"),
		(F16 = f16) => (I32   = i32)   = ("f16"),
		(F16 = f16) => (U64   = u64)   = ("f16"),
		(F16 = f16) => (I64   = i64)   = ("f16"),
		(F16 = f16) => (U128  = u128)  = ("f16"),
		(F16 = f16) => (I128  = i128)  = ("f16"),
		(F16 = f16) => (Usize = usize) = ("f16"),
		(F16 = f16) => (Isize = isize) = ("f16"),
		(F16 = f16) => (F16   = f16)   = ("f16"),
		(F16 = f16) => (F32   = f32)   = ("f16"),
		(F16 = f16) => (F64   = f64)   = ("f16"),
		(F16 = f16) => (F128  = f128)  = ("f16", "f128"),

		(F32 = f32) => (U8    = u8),
		(F32 = f32) => (I8    = i8),
		(F32 = f32) => (U16   = u16),
		(F32 = f32) => (I16   = i16),
		(F32 = f32) => (U32   = u32),
		(F32 = f32) => (I32   = i32),
		(F32 = f32) => (U64   = u64),
		(F32 = f32) => (I64   = i64),
		(F32 = f32) => (U128  = u128),
		(F32 = f32) => (I128  = i128),
		(F32 = f32) => (Usize = usize),
		(F32 = f32) => (Isize = isize),
		(F32 = f32) => (F16   = f16)   = ("f16"),
		(F32 = f32) => (F32   = f32),
		(F32 = f32) => (F64   = f64),
		(F32 = f32) => (F128  = f128)  = ("f128"),


		(F64 = f64) => (U8    = u8),
		(F64 = f64) => (I8    = i8),
		(F64 = f64) => (U16   = u16),
		(F64 = f64) => (I16   = i16),
		(F64 = f64) => (U32   = u32),
		(F64 = f64) => (I32   = i32),
		(F64 = f64) => (U64   = u64),
		(F64 = f64) => (I64   = i64),
		(F64 = f64) => (U128  = u128),
		(F64 = f64) => (I128  = i128),
		(F64 = f64) => (Usize = usize),
		(F64 = f64) => (Isize = isize),
		(F64 = f64) => (F16   = f16)   = ("f16"),
		(F64 = f64) => (F32   = f32),
		(F64 = f64) => (F64   = f64),
		(F64 = f64) => (F128  = f128)  = ("f128"),


		(F128 = f128) => (U8    = u8)    = ("f128"),
		(F128 = f128) => (I8    = i8)    = ("f128"),
		(F128 = f128) => (U16   = u16)   = ("f128"),
		(F128 = f128) => (I16   = i16)   = ("f128"),
		(F128 = f128) => (U32   = u32)   = ("f128"),
		(F128 = f128) => (I32   = i32)   = ("f128"),
		(F128 = f128) => (U64   = u64)   = ("f128"),
		(F128 = f128) => (I64   = i64)   = ("f128"),
		(F128 = f128) => (U128  = u128)  = ("f128"),
		(F128 = f128) => (I128  = i128)  = ("f128"),
		(F128 = f128) => (Usize = usize) = ("f128"),
		(F128 = f128) => (Isize = isize) = ("f128"),
		(F128 = f128) => (F16   = f16)   = ("f128", "f16"),
		(F128 = f128) => (F32   = f32)   = ("f128"),
		(F128 = f128) => (F64   = f64)   = ("f128"),
		(F128 = f128) => (F128  = f128)  = ("f128"),

		(ConstPtr = *const ()) => (ConstPtr = *const ()),
		(ConstPtr = *const ()) => (MutPtr   = *mut ()),

		(MutPtr = *mut ()) => (ConstPtr = *const ()),
		(MutPtr = *mut ()) => (MutPtr   = *mut ()),
	}
}