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

use crate::ValidLayout;
use crate::mask::{Mask, MaskLayout};
use crate::simd::{Simd, SimdLayout, SimdScalar};

use multitype::Int;

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

	SimdLayout<T,                N>: ValidLayout,
	SimdLayout<<T as Int>::Uint, 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 [`i32::MIN`].
	const MIN: Self;

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

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

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

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

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

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

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

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

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

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

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

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

	/// See <code>[i32]::[unsigned_abs](i32::unsigned_abs)</code>.
	#[must_use]
	fn unsigned_abs(self) -> Simd<T::Uint, N>;

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

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

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

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

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

	/// See <code>[i32]::[abs_diff](i32::abs_diff)</code>.
	#[must_use]
	fn abs_diff(self, rhs: Self) -> Simd<T::Uint, N>;

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

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

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

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

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

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

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

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

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

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

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

	/// See <code>[i32]::[strict_add_unsigned](i32::strict_add_unsigned)</code>.
	#[must_use]
	fn strict_add_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

	/// See <code>[i32]::[strict_sub_unsigned](i32::strict_sub_unsigned)</code>.
	#[must_use]
	fn strict_sub_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	/// See <code>[i32]::[wrapping_add_unsigned](i32::wrapping_add_unsigned)</code>.
	#[must_use]
	fn wrapping_add_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

	/// See <code>[i32]::[wrapping_sub_unsigned](i32::wrapping_sub_unsigned)</code>.
	#[must_use]
	fn wrapping_sub_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

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

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

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

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

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

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

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

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

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

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

	/// See <code>[i32]::[saturating_add_unsigned](i32::saturating_add_unsigned)</code>.
	#[must_use]
	fn saturating_add_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

	/// See <code>[i32]::[saturating_sub_unsigned](i32::saturating_sub_unsigned)</code>.
	#[must_use]
	fn saturating_sub_unsigned(self, rhs: Simd<T::Uint, N>) -> Self;

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

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

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

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

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

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

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

	/// Reinterprets `self` as an unsigned integer.
	#[must_use]
	fn cast_unsigned(self) -> Simd<T::Uint, N>;

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

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