polylane 0.10.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::cmp::{
	SimdEq,
	SimdOrd,
	SimdPartialEq,
	SimdPartialOrd,
};
use crate::num::SimdInt;
use crate::simd::SimdScalar;

use core::cmp::{
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
};
use core::ops::{
	Add,
	AddAssign,
	BitAnd,
	BitAndAssign,
	BitOr,
	BitOrAssign,
	BitXor,
	BitXorAssign,
	Div,
	DivAssign,
	Mul,
	MulAssign,
	Not,
	Rem,
	RemAssign,
	Shl,
	ShlAssign,
	Shr,
	ShrAssign,
	Sub,
	SubAssign,
};
use multitype::Uint;

/// Denotes SIMD vector of unsigned, integral scalars.
pub trait SimdUint
where
	Self:
		crate::num::seal::SimdUint
		+ Copy
		+ Eq
		+ Ord
		+ PartialEq
		+ PartialOrd
		+ SimdEq
		+ SimdOrd
		+ SimdPartialEq
		+ SimdPartialOrd
		// Arithmetic operators:
		+ Add<   Output = Self>
		+ BitAnd<Output = Self>
		+ BitOr< Output = Self>
		+ BitXor<Output = Self>
		+ Div<   Output = Self>
		+ Mul<   Output = Self>
		+ Not<   Output = Self>
		+ Rem<   Output = Self>
		+ Shl<   Output = Self>
		+ Shr<   Output = Self>
		+ Sub<   Output = Self>
		// Assigning arithmetic operators:
		+ AddAssign
		+ BitAndAssign
		+ BitOrAssign
		+ BitXorAssign
		+ DivAssign
		+ MulAssign
		+ RemAssign
		+ ShlAssign
		+ ShrAssign
		+ SubAssign,
{
	/// The underlying, scalar type.
	type Scalar: SimdScalar + Uint;

	/// The length of the vector type.
	const LEN: usize;

	/// The equivalent, signed, integral vector type.
	type Int: SimdInt<
		Scalar = <Self::Scalar as Uint>::Int,
		Uint   = Self,
		U32    = Self::U32,
	>;

	/// An equivalent vector type of [`u32`] scalars.
	type U32: SimdUint<Scalar = u32>;

	/// See [`u32::MIN`].
	const MIN: Self;

	/// See [`u32::MAX`].
	const MAX: Self;

	/// See <code>[u32]::[from_le](u32::from_le)</code>.
	#[must_use]
	fn from_le(value: Self) -> Self;

	/// See <code>[u32]::[from_be](u32::from_be)</code>.
	#[must_use]
	fn from_be(value: Self) -> Self;

	/// See <code>[u32]::[div_ceil](u32::div_ceil)</code>.
	#[must_use]
	fn div_ceil(self, rhs: Self) -> Self;

	/// See <code>[u32]::[div_euclid](u32::div_euclid)</code>.
	#[must_use]
	fn div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[rem_euclid](u32::rem_euclid)</code>.
	#[must_use]
	fn rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[rotate_left](u32::rotate_left)</code>.
	#[must_use]
	fn rotate_left(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[rotate_right](u32::rotate_right)</code>.
	#[must_use]
	fn rotate_right(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[swap_bytes](u32::swap_bytes)</code>.
	#[must_use]
	fn swap_bytes(self) -> Self;

	/// See <code>[u32]::[reverse_bits](u32::reverse_bits)</code>.
	#[must_use]
	fn reverse_bits(self) -> Self;

	/// See <code>[u32]::[pow](u32::pow)</code>.
	#[must_use]
	fn pow(self, exp: Self::U32) -> Self;

	/// See <code>[u32]::[isqrt](u32::isqrt)</code>.
	#[must_use]
	fn isqrt(self) -> Self;

	/// See <code>[u32]::[ilog](u32::ilog)</code>.
	#[must_use]
	fn ilog(self, base: Self) -> Self::U32;

	/// See <code>[u32]::[ilog2](u32::ilog2)</code>.
	#[must_use]
	fn ilog2(self) -> Self::U32;

	/// See <code>[u32]::[ilog10](u32::ilog10)</code>.
	#[must_use]
	fn ilog10(self) -> Self::U32;

	/// See <code>[u32]::[abs_diff](u32::abs_diff)</code>.
	#[must_use]
	fn abs_diff(self, rhs: Self) -> Self;

	/// See <code>[u32]::[midpoint](u32::midpoint)</code>.
	#[must_use]
	fn midpoint(self, rhs: Self) -> Self;

	/// See <code>[u32]::[count_zeros](u32::count_zeros)</code>.
	#[must_use]
	fn count_zeros(self) -> Self::U32;

	/// See <code>[u32]::[count_ones](u32::count_ones)</code>.
	#[must_use]
	fn count_ones(self) -> Self::U32;

	/// See <code>[u32]::[leading_zeros](u32::leading_zeros)</code>.
	#[must_use]
	fn leading_zeros(self) -> Self::U32;

	/// See <code>[u32]::[leading_ones](u32::leading_ones)</code>.
	#[must_use]
	fn leading_ones(self) -> Self::U32;

	/// See <code>[u32]::[trailing_zeros](u32::trailing_zeros)</code>.
	#[must_use]
	fn trailing_zeros(self) -> Self::U32;

	/// See <code>[u32]::[trailing_ones](u32::trailing_ones)</code>.
	#[must_use]
	fn trailing_ones(self) -> Self::U32;

	/// See <code>[u32]::[is_multiple_of](u32::is_multiple_of)</code>.
	#[must_use]
	fn is_multiple_of(self, rhs: Self) -> Self::Mask;

	/// See <code>[u32]::[is_power_of_two](u32::is_power_of_two)</code>.
	#[must_use]
	fn is_power_of_two(self) -> Self::Mask;

	/// See <code>[u32]::[next_multiple_of](u32::next_multiple_of)</code>.
	#[must_use]
	fn next_multiple_of(self, rhs: Self) -> Self;

	/// See <code>[u32]::[next_power_of_two](u32::next_power_of_two)</code>.
	#[must_use]
	fn next_power_of_two(self) -> Self;

	/// See <code>[u32]::[strict_add](u32::strict_add)</code>.
	#[must_use]
	fn strict_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_add_signed](u32::strict_add_signed)</code>.
	#[must_use]
	fn strict_add_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[strict_sub](u32::strict_sub)</code>.
	#[must_use]
	fn strict_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_sub_signed](u32::strict_sub_signed)</code>.
	#[must_use]
	fn strict_sub_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[strict_mul](u32::strict_mul)</code>.
	#[must_use]
	fn strict_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_div](u32::strict_div)</code>.
	#[must_use]
	fn strict_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_div_euclid](u32::strict_div_euclid)</code>.
	#[must_use]
	fn strict_div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_rem](u32::strict_rem)</code>.
	#[must_use]
	fn strict_rem(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_rem_euclid](u32::strict_rem_euclid)</code>.
	#[must_use]
	fn strict_rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[strict_shl](u32::strict_shl)</code>.
	#[must_use]
	fn strict_shl(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[strict_shr](u32::strict_shr)</code>.
	#[must_use]
	fn strict_shr(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[strict_neg](u32::strict_neg)</code>.
	#[must_use]
	fn strict_neg(self) -> Self;

	/// See <code>[u32]::[strict_pow](u32::strict_pow)</code>.
	#[must_use]
	fn strict_pow(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[unchecked_add](u32::unchecked_add)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[unchecked_sub](u32::unchecked_sub)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[unchecked_mul](u32::unchecked_mul)</code>.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn unchecked_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_add](u32::wrapping_add)</code>.
	#[must_use]
	fn wrapping_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_add_signed](u32::wrapping_add_signed)</code>.
	#[must_use]
	fn wrapping_add_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[wrapping_sub](u32::wrapping_sub)</code>.
	#[must_use]
	fn wrapping_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_sub_signed](u32::wrapping_sub_signed)</code>.
	#[must_use]
	fn wrapping_sub_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[wrapping_mul](u32::wrapping_mul)</code>.
	#[must_use]
	fn wrapping_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_div](u32::wrapping_div)</code>.
	#[must_use]
	fn wrapping_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_div_euclid](u32::wrapping_div_euclid)</code>.
	#[must_use]
	fn wrapping_div_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_rem](u32::wrapping_rem)</code>.
	#[must_use]
	fn wrapping_rem(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_rem_euclid](u32::wrapping_rem_euclid)</code>.
	#[must_use]
	fn wrapping_rem_euclid(self, rhs: Self) -> Self;

	/// See <code>[u32]::[wrapping_shl](u32::wrapping_shl)</code>.
	#[must_use]
	fn wrapping_shl(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[wrapping_shr](u32::wrapping_shr)</code>.
	#[must_use]
	fn wrapping_shr(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[wrapping_neg](u32::wrapping_neg)</code>.
	#[must_use]
	fn wrapping_neg(self) -> Self;

	/// See <code>[u32]::[wrapping_pow](u32::wrapping_pow)</code>.
	#[must_use]
	fn wrapping_pow(self, exp: Self::U32) -> Self;

	/// See <code>[u32]::[saturating_add](u32::saturating_add)</code>.
	#[must_use]
	fn saturating_add(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_add_signed](u32::saturating_add_signed)</code>.
	#[must_use]
	fn saturating_add_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[saturating_sub](u32::saturating_sub)</code>.
	#[must_use]
	fn saturating_sub(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_sub_signed](u32::saturating_sub_signed)</code>.
	#[must_use]
	fn saturating_sub_signed(self, rhs: Self::Int) -> Self;

	/// See <code>[u32]::[saturating_mul](u32::saturating_mul)</code>.
	#[must_use]
	fn saturating_mul(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_div](u32::saturating_div)</code>.
	#[must_use]
	fn saturating_div(self, rhs: Self) -> Self;

	/// See <code>[u32]::[saturating_pow](u32::saturating_pow)</code>.
	#[must_use]
	fn saturating_pow(self, exp: Self::U32) -> Self;

	/// See <code>[u32]::[unbounded_shl](u32::unbounded_shl)</code>.
	#[must_use]
	fn unbounded_shl(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[unbounded_shr](u32::unbounded_shr)</code>.
	#[must_use]
	fn unbounded_shr(self, rhs: Self::U32) -> Self;

	/// See <code>[u32]::[cast_signed](u32::cast_signed)</code>.
	#[must_use]
	fn cast_signed(self) -> Self::Int;

	/// See <code>[u32]::[to_le](u32::to_le)</code>.
	#[must_use]
	fn to_le(self) -> Self;

	/// See <code>[u32]::[to_be](u32::to_be)</code>.
	#[must_use]
	fn to_be(self) -> Self;
}