polylane 0.9.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 core::fmt::Debug;
use core::hash::Hash;
use core::panic::{RefUnwindSafe, UnwindSafe};

#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};

#[cfg(feature = "freeze")]
use core::marker::Freeze;

#[cfg(feature = "zerocopy")]
use zerocopy::{FromBytes, IntoBytes, KnownLayout};

pub trait CoreCompat:
	Clone
	+ Copy
	+ Debug
	+ Default
	+ Eq
	+ Hash
	+ Ord
	+ PartialEq
	+ PartialOrd
	+ RefUnwindSafe
	+ Send
	+ Sync
	+ Unpin
	+ UnwindSafe
{}

impl<T> CoreCompat for T
where
	T:
		Clone
		+ Copy
		+ Debug
		+ Default
		+ Eq
		+ Hash
		+ Ord
		+ PartialEq
		+ PartialOrd
		+ RefUnwindSafe
		+ Send
		+ Sync
		+ Unpin
		+ UnwindSafe,
{}

#[cfg(feature = "bytemuck")]
pub trait BytemuckCompat:
	Pod
	+ Zeroable
{}

#[cfg(feature = "bytemuck")]
impl<T> BytemuckCompat for T
where
	T:
		Pod
		+ Zeroable,
{}

#[cfg(not(feature = "bytemuck"))]
pub trait BytemuckCompat {}

#[cfg(not(feature = "bytemuck"))]
impl<T> BytemuckCompat for T {}

#[cfg(feature = "freeze")]
pub trait FreezeCompat: Freeze {}

#[cfg(feature = "freeze")]
impl<T: Freeze> FreezeCompat for T {}

#[cfg(not(feature = "freeze"))]
pub trait FreezeCompat {}

#[cfg(not(feature = "freeze"))]
impl<T> FreezeCompat for T {}

#[cfg(feature = "zerocopy")]
pub trait ZerocopyCompat:
	FromBytes
	+ IntoBytes
	+ KnownLayout
{}

#[cfg(feature = "zerocopy")]
impl<T> ZerocopyCompat for T
where
	T:
		FromBytes
		+ IntoBytes
		+ KnownLayout,
{}

#[cfg(not(feature = "zerocopy"))]
pub trait ZerocopyCompat {}

#[cfg(not(feature = "zerocopy"))]
impl<T> ZerocopyCompat for T {}

// This trait should require all derived traits and
// auto traits that are expected for `Simd`.
pub trait Alignement: CoreCompat + BytemuckCompat + FreezeCompat + ZerocopyCompat {
	const NEW: Self;
}

macro_rules! def_alignements {
	{ $($Ident:ident @ $align:literal),*$(,)? } => {
		$(
			#[repr(align($align), C)]
			#[derive(
				::core::clone::Clone,
				::core::marker::Copy,
				::core::fmt::Debug,
				::core::default::Default,
				::core::cmp::Eq,
				::core::hash::Hash,
				::core::cmp::Ord,
				::core::cmp::PartialEq,
				::core::cmp::PartialOrd,
			)]
			#[cfg_attr(
				feature = "bytemuck",
				derive(
					::bytemuck::Pod,
					::bytemuck::Zeroable,
				),
			)]
			#[cfg_attr(
				feature = "zerocopy",
				derive(
					::zerocopy::FromBytes,
					::zerocopy::IntoBytes,
					::zerocopy::KnownLayout,
				),
			)]
			pub struct $Ident;

			impl ::polylane::simd::Alignement for $Ident {
				const NEW: Self = Self;
			}
		)?
	};
}

def_alignements! {
	AlignementByteX1    @ 0x001,
	AlignementByteX2    @ 0x002,
	AlignementByteX4    @ 0x004,
	AlignementByteX8    @ 0x008,
	AlignementByteX16   @ 0x010,
	AlignementByteX32   @ 0x020,
	AlignementByteX64   @ 0x040,
	AlignementByteX128  @ 0x080,
	AlignementByteX256  @ 0x100,
	AlignementByteX512  @ 0x200,
	AlignementByteX1024 @ 0x400,
}

macro_rules! def_alignement_aliases {
	{ $($Alias:ident = $Alignement:ty),*$(,)? } => {$(
		pub type $Alias = $Alignement;
	)*};
}

#[cfg(target_pointer_width = "16")]
def_alignement_aliases! {
	AlignementSizeX1  = AlignementByteX2,
	AlignementSizeX2  = AlignementByteX4,
	AlignementSizeX4  = AlignementByteX8,
	AlignementSizeX8  = AlignementByteX16,
	AlignementSizeX16 = AlignementByteX32,
	AlignementSizeX32 = AlignementByteX64,
	AlignementSizeX64 = AlignementByteX128,
}

#[cfg(target_pointer_width = "32")]
def_alignement_aliases! {
	AlignementSizeX1  = AlignementByteX4,
	AlignementSizeX2  = AlignementByteX8,
	AlignementSizeX4  = AlignementByteX16,
	AlignementSizeX8  = AlignementByteX32,
	AlignementSizeX16 = AlignementByteX64,
	AlignementSizeX32 = AlignementByteX128,
	AlignementSizeX64 = AlignementByteX256,
}

#[cfg(target_pointer_width = "64")]
def_alignement_aliases! {
	AlignementSizeX1  = AlignementByteX8,
	AlignementSizeX2  = AlignementByteX16,
	AlignementSizeX4  = AlignementByteX32,
	AlignementSizeX8  = AlignementByteX64,
	AlignementSizeX16 = AlignementByteX128,
	AlignementSizeX32 = AlignementByteX256,
	AlignementSizeX64 = AlignementByteX512,
}