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 crate::cmp::{
	SimdEq,
	SimdOrd,
	SimdPartialEq,
	SimdPartialOrd,
};
use crate::num::SimdUint;
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,
	Neg,
	Not,
	Rem,
	RemAssign,
	Shl,
	ShlAssign,
	Shr,
	ShrAssign,
	Sub,
	SubAssign,
};
use multitype::Int;

/// Denotes SIMD vector of unsigned, integral scalars.
pub trait SimdInt
where
	Self:
		crate::num::seal::SimdInt
		+ 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>
		+ Neg<   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 + Int;

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

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

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

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

	/// See [`i32::MAX`].
	const MAX: 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: Self::U32) -> Self;

	/// See <code>[i32]::[rotate_right](i32::rotate_right)</code>.
	#[must_use]
	fn rotate_right(self, rhs: Self::U32) -> 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) -> Self::Uint;

	/// See <code>[i32]::[pow](i32::pow)</code>.
	#[must_use]
	fn pow(self, exp: Self::U32) -> 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) -> Self::U32;

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

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

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

	/// 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) -> Self::Mask;

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

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

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

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

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

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

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

	/// 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: Self::Uint) -> 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: Self::Uint) -> 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: Self::U32) -> Self;

	/// See <code>[i32]::[strict_shr](i32::strict_shr)</code>.
	#[must_use]
	fn strict_shr(self, rhs: Self::U32) -> 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: Self::U32) -> 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]::[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: Self::Uint) -> 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: Self::Uint) -> 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: Self::U32) -> Self;

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

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

	/// See <code>[i32]::[wrapping_pow](i32::wrapping_pow)</code>.
	#[must_use]
	fn wrapping_pow(self, exp: Self::U32) -> 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: Self::Uint) -> 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: Self::Uint) -> 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, exp: Self::U32) -> Self;

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

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

	/// Reinterprets `self` as an unsigned integer.
	#[must_use]
	fn cast_unsigned(self) -> Self::Uint;

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