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/>.

mod test;

use crate::simd::SimdScalar;

/// Denotes SIMD scalars types that can be cast.
///
/// # Safety
///
/// Only SIMD scalar types that support `as` casts may implement this trait.
pub unsafe trait SimdScalarCast<T>: SimdScalar {}

macro_rules! simd_casts {
	{ $($InTy:ty => $OutTy:ty $(= ($($feature:literal),+$(,)?))?),*$(,)? } => {$(
		$(#[cfg(all($(feature = $feature, )+))])?
		unsafe impl ::polylane::convert::SimdScalarCast<$OutTy> for $InTy {}
	)*};
}

macro_rules! simd_to_const_ptr_casts {
	{ $($InTy:ty => *const _),*$(,)? } => {$(
		unsafe impl<T: Sized> ::polylane::convert::SimdScalarCast<*const T> for $InTy {}
	)*};
}

macro_rules! simd_to_mut_ptr_casts {
	{ $($InTy:ty => *mut _),*$(,)? } => {$(
		unsafe impl<T: Sized> ::polylane::convert::SimdScalarCast<*mut T> for $InTy {}
	)*};
}

simd_casts! {
	u8 => u8,
	u8 => i8,
	u8 => u16,
	u8 => i16,
	u8 => u32,
	u8 => i32,
	u8 => u64,
	u8 => i64,
	u8 => u128,
	u8 => i128,
	u8 => usize,
	u8 => isize,
	u8 => f16   = ("f16"),
	u8 => f32,
	u8 => f64,
	u8 => f128  = ("f128"),

	i8 => u8,
	i8 => i8,
	i8 => u16,
	i8 => i16,
	i8 => u32,
	i8 => i32,
	i8 => u64,
	i8 => i64,
	i8 => u128,
	i8 => i128,
	i8 => usize,
	i8 => isize,
	i8 => f16   = ("f16"),
	i8 => f32,
	i8 => f64,
	i8 => f128  = ("f128"),

	u16 => u8,
	u16 => i8,
	u16 => u16,
	u16 => i16,
	u16 => u32,
	u16 => i32,
	u16 => u64,
	u16 => i64,
	u16 => u128,
	u16 => i128,
	u16 => usize,
	u16 => isize,
	u16 => f16   = ("f16"),
	u16 => f32,
	u16 => f64,
	u16 => f128  = ("f128"),

	i16 => u8,
	i16 => i8,
	i16 => u16,
	i16 => i16,
	i16 => u32,
	i16 => i32,
	i16 => u64,
	i16 => i64,
	i16 => u128,
	i16 => i128,
	i16 => usize,
	i16 => isize,
	i16 => f16   = ("f16"),
	i16 => f32,
	i16 => f64,
	i16 => f128  = ("f128"),

	u32 => u8,
	u32 => i8,
	u32 => u16,
	u32 => i16,
	u32 => u32,
	u32 => i32,
	u32 => u64,
	u32 => i64,
	u32 => u128,
	u32 => i128,
	u32 => usize,
	u32 => isize,
	u32 => f16   = ("f16"),
	u32 => f32,
	u32 => f64,
	u32 => f128  = ("f128"),

	i32 => u8,
	i32 => i8,
	i32 => u16,
	i32 => i16,
	i32 => u32,
	i32 => i32,
	i32 => u64,
	i32 => i64,
	i32 => u128,
	i32 => i128,
	i32 => usize,
	i32 => isize,
	i32 => f16   = ("f16"),
	i32 => f32,
	i32 => f64,
	i32 => f128  = ("f128"),

	u64 => u8,
	u64 => i8,
	u64 => u16,
	u64 => i16,
	u64 => u32,
	u64 => i32,
	u64 => u64,
	u64 => i64,
	u64 => u128,
	u64 => i128,
	u64 => usize,
	u64 => isize,
	u64 => f16   = ("f16"),
	u64 => f32,
	u64 => f64,
	u64 => f128  = ("f128"),

	i64 => u8,
	i64 => i8,
	i64 => u16,
	i64 => i16,
	i64 => u32,
	i64 => i32,
	i64 => u64,
	i64 => i64,
	i64 => u128,
	i64 => i128,
	i64 => usize,
	i64 => isize,
	i64 => f16   = ("f16"),
	i64 => f32,
	i64 => f64,
	i64 => f128  = ("f128"),

	u128 => u8,
	u128 => i8,
	u128 => u16,
	u128 => i16,
	u128 => u32,
	u128 => i32,
	u128 => u64,
	u128 => i64,
	u128 => u128,
	u128 => i128,
	u128 => usize,
	u128 => isize,
	u128 => f16   = ("f16"),
	u128 => f32,
	u128 => f64,
	u128 => f128  = ("f128"),

	i128 => u8,
	i128 => i8,
	i128 => u16,
	i128 => i16,
	i128 => u32,
	i128 => i32,
	i128 => u64,
	i128 => i64,
	i128 => u128,
	i128 => i128,
	i128 => usize,
	i128 => isize,
	i128 => f16   = ("f16"),
	i128 => f32,
	i128 => f64,
	i128 => f128  = ("f128"),

	usize => u8,
	usize => i8,
	usize => u16,
	usize => i16,
	usize => u32,
	usize => i32,
	usize => u64,
	usize => i64,
	usize => u128,
	usize => i128,
	usize => usize,
	usize => isize,
	usize => f16   = ("f16"),
	usize => f32,
	usize => f64,
	usize => f128  = ("f128"),

	isize => u8,
	isize => i8,
	isize => u16,
	isize => i16,
	isize => u32,
	isize => i32,
	isize => u64,
	isize => i64,
	isize => u128,
	isize => i128,
	isize => usize,
	isize => isize,
	isize => f16   = ("f16"),
	isize => f32,
	isize => f64,
	isize => f128  = ("f128"),

	f16 => u8    = ("f16"),
	f16 => i8    = ("f16"),
	f16 => u16   = ("f16"),
	f16 => i16   = ("f16"),
	f16 => u32   = ("f16"),
	f16 => i32   = ("f16"),
	f16 => u64   = ("f16"),
	f16 => i64   = ("f16"),
	f16 => u128  = ("f16"),
	f16 => i128  = ("f16"),
	f16 => usize = ("f16"),
	f16 => isize = ("f16"),
	f16 => f16   = ("f16"),
	f16 => f32   = ("f16"),
	f16 => f64   = ("f16"),
	f16 => f128  = ("f128"),

	f32 => u8,
	f32 => i8,
	f32 => u16,
	f32 => i16,
	f32 => u32,
	f32 => i32,
	f32 => u64,
	f32 => i64,
	f32 => u128,
	f32 => i128,
	f32 => usize,
	f32 => isize,
	f32 => f16   = ("f16"),
	f32 => f32,
	f32 => f64,
	f32 => f128  = ("f128"),

	f64 => u8,
	f64 => i8,
	f64 => u16,
	f64 => i16,
	f64 => u32,
	f64 => i32,
	f64 => u64,
	f64 => i64,
	f64 => u128,
	f64 => i128,
	f64 => usize,
	f64 => isize,
	f64 => f16   = ("f16"),
	f64 => f32,
	f64 => f64,
	f64 => f128  = ("f128"),

	f128 => u8    = ("f128"),
	f128 => i8    = ("f128"),
	f128 => u16   = ("f128"),
	f128 => i16   = ("f128"),
	f128 => u32   = ("f128"),
	f128 => i32   = ("f128"),
	f128 => u64   = ("f128"),
	f128 => i64   = ("f128"),
	f128 => u128  = ("f128"),
	f128 => i128  = ("f128"),
	f128 => usize = ("f128"),
	f128 => isize = ("f128"),
	f128 => f16   = ("f128", "f16"),
	f128 => f32   = ("f128"),
	f128 => f64   = ("f128"),
	f128 => f128  = ("f128"),
}

simd_to_const_ptr_casts! {
	u8    => *const _,
	i8    => *const _,
	u16   => *const _,
	i16   => *const _,
	u32   => *const _,
	i32   => *const _,
	u64   => *const _,
	i64   => *const _,
	u128  => *const _,
	i128  => *const _,
	usize => *const _,
	isize => *const _,
}

simd_to_mut_ptr_casts! {
	u8    => *mut _,
	i8    => *mut _,
	u16   => *mut _,
	i16   => *mut _,
	u32   => *mut _,
	i32   => *mut _,
	u64   => *mut _,
	i64   => *mut _,
	u128  => *mut _,
	i128  => *mut _,
	usize => *mut _,
	isize => *mut _,
}

unsafe impl<T: Sized> SimdScalarCast<*const T> for *const T {}

unsafe impl<T: Sized> SimdScalarCast<*mut T> for *const T {}

unsafe impl<T: Sized> SimdScalarCast<*const T> for *mut T {}

unsafe impl<T: Sized> SimdScalarCast<*mut T> for *mut T {}