polylane 0.14.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::ValidLayout;
use crate::mask::{Mask, MaskLayout};
use crate::simd::{Simd, SimdLayout, SimdScalar};

use multitype::Uint;

/// Denotes SIMD vector of unsigned, integral scalars.
#[expect(clippy::wrong_self_convention)]
pub trait SimdUint<T, const N: usize>: crate::num::seal::SimdUint + Sized
where
	T: SimdScalar + Uint<Int: SimdScalar>,

	SimdLayout<T,                N>: ValidLayout,
	SimdLayout<<T as Uint>::Int, N>: ValidLayout,

	SimdLayout<u32, N>: ValidLayout,
	SimdLayout<i32, N>: ValidLayout,

	MaskLayout<N>: ValidLayout,
{
	/// The total bitwise width of this vector type.
	const BITS: u32;

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

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

	/// Equivalent to <code>Self::[splat](Simd::splat)(T::[ZERO](Uint::ZERO))</code>.
	const ZERO:             Self;

	/// Equivalent to <code>Self::[splat](Simd::splat)(T::[ONE](Uint::ONE))</code>.
	const ONE:              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: Simd<u32, N>) -> Self;

	/// See <code>[u32]::[rotate_right](u32::rotate_right)</code>.
	#[must_use]
	fn rotate_right(self, rhs: Simd<u32, N>) -> 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, rhs: Simd<u32, N>) -> 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) -> Simd<u32, N>;

	/// See <code>[u32]::[ilog2](u32::ilog2)</code>.
	#[must_use]
	fn ilog2(self) -> Simd<u32, N>;

	/// See <code>[u32]::[ilog10](u32::ilog10)</code>.
	#[must_use]
	fn ilog10(self) -> Simd<u32, N>;

	/// 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) -> Simd<u32, N>;

	/// See <code>[u32]::[count_ones](u32::count_ones)</code>.
	#[must_use]
	fn count_ones(self) -> Simd<u32, N>;

	/// See <code>[u32]::[leading_zeros](u32::leading_zeros)</code>.
	#[must_use]
	fn leading_zeros(self) -> Simd<u32, N>;

	/// See <code>[u32]::[leading_ones](u32::leading_ones)</code>.
	#[must_use]
	fn leading_ones(self) -> Simd<u32, N>;

	/// See <code>[u32]::[trailing_zeros](u32::trailing_zeros)</code>.
	#[must_use]
	fn trailing_zeros(self) -> Simd<u32, N>;

	/// See <code>[u32]::[trailing_ones](u32::trailing_ones)</code>.
	#[must_use]
	fn trailing_ones(self) -> Simd<u32, N>;

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

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

	/// 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: Simd<T::Int, N>) -> 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: Simd<T::Int, N>) -> 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: Simd<u32, N>) -> Self;

	/// See <code>[u32]::[strict_shr](u32::strict_shr)</code>.
	#[must_use]
	fn strict_shr(self, rhs: Simd<u32, N>) -> 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: Simd<u32, N>) -> 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]::[overflowing_add](u32::overflowing_add)</code>.
	#[must_use]
	fn overflowing_add(self, rhs: Self) -> (Self, Mask<N>);

	/// See <code>[u32]::[overflowing_add_signed](u32::overflowing_add_signed)</code>.
	#[must_use]
	fn overflowing_add_signed(self, rhs: Simd<T::Int, N>) -> (Self, Mask<N>);

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

	/// See <code>[u32]::[overflowing_sub_signed](u32::overflowing_sub_signed)</code>.
	#[must_use]
	fn overflowing_sub_signed(self, rhs: Simd<T::Int, N>) -> (Self, Mask<N>);

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

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

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

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

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

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

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

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

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

	/// 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: Simd<T::Int, N>) -> 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: Simd<T::Int, N>) -> 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: Simd<u32, N>) -> Self;

	/// See <code>[u32]::[wrapping_shr](u32::wrapping_shr)</code>.
	#[must_use]
	fn wrapping_shr(self, rhs: Simd<u32, N>) -> 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, rhs: Simd<u32, N>) -> 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: Simd<T::Int, N>) -> 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: Simd<T::Int, N>) -> 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, rhs: Simd<u32, N>) -> Self;

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

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

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

	/// 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;
}