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

use crate::compat;

use crate::detail::DataKind;

use core::ptr;

/// Denotes a type suitable as a [SIMD vector](crate::simd::Simd) element.
///
/// # Safety
///
/// Any given SIMD scalar type must ophold the following type invariants:
///
/// * The type is neither ZST nor DST
/// * The type has contiguous representation that can be reinterpreted as some integral type of the same width
/// * The type has no padding
/// * The type has no interiour mutability
pub unsafe trait SimdScalar:
	crate::simd::seal::SimdScalar
	+ Copy
	+ Default
	+ compat::Freeze
	+ compat::zerocopy::FromZeros
	+ compat::zerocopy::Immutable
	+ compat::zerocopy::KnownLayout
	+ compat::Thin
	+ Unpin
	+ compat::bytemuck::Zeroable
{}

macro_rules! simd_scalars {
	{
		$($Ty:ty: $data_kind:ident = { ZEROED = $zeroed:expr, ONED = $oned:expr$(,)? } $(= $feature:literal)?),*$(,)?
	} => {
		$(
			$(#[cfg(feature = $feature)])?
			unsafe impl ::polylane::simd::seal::SimdScalar for $Ty {
				const DATA_KIND: ::polylane::detail::DataKind = ::polylane::detail::DataKind::$data_kind;

				const ZEROED: Self = $zeroed;

				const ONED: Self = $oned;
			}

			$(#[cfg(feature = $feature)])?
			unsafe impl ::polylane::simd::SimdScalar for $Ty {}
		)*
	};
}

simd_scalars! {
	u8:    U8    = { ZEROED = 0, ONED = u8::MAX },
	u16:   U16   = { ZEROED = 0, ONED = u16::MAX },
	u32:   U32   = { ZEROED = 0, ONED = u32::MAX },
	u64:   U64   = { ZEROED = 0, ONED = u64::MAX },
	u128:  U128  = { ZEROED = 0, ONED = u128::MAX },
	usize: Usize = { ZEROED = 0, ONED = usize::MAX },

	i8:    I8    = { ZEROED = 0, ONED = -1 },
	i16:   I16   = { ZEROED = 0, ONED = -1 },
	i32:   I32   = { ZEROED = 0, ONED = -1 },
	i64:   I64   = { ZEROED = 0, ONED = -1 },
	i128:  I128  = { ZEROED = 0, ONED = -1 },
	isize: Isize = { ZEROED = 0, ONED = -1 },

	f16:  F16  = { ZEROED = f16::from_bits(0),  ONED = f16::from_bits(u16::MAX) }   = "f16",
	f32:  F32  = { ZEROED = f32::from_bits(0),  ONED = f32::from_bits(u32::MAX) },
	f64:  F64  = { ZEROED = f64::from_bits(0),  ONED = f64::from_bits(u64::MAX) },
	f128: F128 = { ZEROED = f128::from_bits(0), ONED = f128::from_bits(u128::MAX) } = "f128",
}

unsafe impl<T: Sized> crate::simd::seal::SimdScalar for *const T {
	const DATA_KIND: DataKind = DataKind::ConstPtr;

	const ZEROED: Self = ptr::without_provenance(usize::MIN);

	const ONED: Self = ptr::without_provenance(usize::MAX);
}

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

unsafe impl<T: Sized> crate::simd::seal::SimdScalar for *mut T {
	const DATA_KIND: DataKind = DataKind::MutPtr;

	const ZEROED: Self = ptr::without_provenance_mut(usize::MIN);

	const ONED: Self = ptr::without_provenance_mut(usize::MAX);
}

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