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 core::cmp::Ordering;
use core::num::FpCategory;
use multitype::{Float, Uint};

/// Denotes SIMD vector of floating-point scalars.
#[expect(clippy::wrong_self_convention)]
pub trait SimdFloat<T, const N: usize>: crate::num::seal::SimdFloat + Sized
where
	T: SimdScalar + Float<Bits: SimdScalar + Uint<Int: SimdScalar>>,

	SimdLayout<T, N>: ValidLayout,

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

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

	MaskLayout<N>: ValidLayout,
{
	/// See <code>[f64]::[EPSILON](f64::EPSILON)</code>.
	const EPSILON:         Self;

	/// See <code>[f64]::[MIN](f64::MIN)</code>.
	const MIN:             Self;

	/// See <code>[f64]::[MIN_POSITIVE](f64::MIN_POSITIVE)</code>.
	const MIN_POSITIVE:    Self;

	/// See <code>[f64]::[MAX](f64::MAX)</code>.
	const MAX:             Self;

	/// See <code>[f64]::[INFINITY](f64::INFINITY)</code>.
	const INFINITY:        Self;

	/// See <code>[f64]::[NEG_INFINITY](f64::NEG_INFINITY)</code>.
	const NEG_INFINITY:    Self;

	/// See <code>[f64]::[NAN](f64::NAN)</code>.
	const NAN:             Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[E](core::f64::consts::E)</code>.
	const E:               Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[PI](core::f64::consts::PI)</code>.
	const PI:              Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[TAU](core::f64::consts::TAU)</code>.
	const TAU:             Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LOG2_10](core::f64::consts::LOG2_10)</code>.
	const LOG2_10:         Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LOG2_E](core::f64::consts::LOG2_E)</code>.
	const LOG2_E:          Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LN_2](core::f64::consts::LN_2)</code>.
	const LN_2:            Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LN_10](core::f64::consts::LN_10)</code>.
	const LN_10:           Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LOG10_2](core::f64::consts::LOG10_2)</code>.
	const LOG10_2:         Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[LOG10_E](core::f64::consts::LOG10_E)</code>.
	const LOG10_E:         Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[SQRT_2](core::f64::consts::SQRT_2)</code>.
	const SQRT_2:          Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_1_PI](core::f64::consts::FRAC_1_PI)</code>.
	const FRAC_1_PI:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_1_SQRT_2](core::f64::consts::FRAC_1_SQRT_2)</code>.
	const FRAC_1_SQRT_2:   Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_2_PI](core::f64::consts::FRAC_2_PI)</code>.
	const FRAC_2_PI:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_2_SQRT_PI](core::f64::consts::FRAC_2_SQRT_PI)</code>.
	const FRAC_2_SQRT_PI:  Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_PI_2](core::f64::consts::FRAC_PI_2)</code>.
	const FRAC_PI_2:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_PI_3](core::f64::consts::FRAC_PI_3)</code>.
	const FRAC_PI_3:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_PI_4](core::f64::consts::FRAC_PI_4)</code>.
	const FRAC_PI_4:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_PI_6](core::f64::consts::FRAC_PI_6)</code>.
	const FRAC_PI_6:       Self;

	/// See <code>[f64](core::f64)::[consts](core::f64::consts)::[FRAC_PI_8](core::f64::consts::FRAC_PI_8)</code>.
	const FRAC_PI_8:       Self;

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

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

	/// See <code>[f64]::[from_bits](f64::from_bits)</code>.
	#[must_use]
	fn from_bits(bits: Simd<T::Bits, N>) -> Self;

	/// See <code>[f64]::[mul_add](f64::mul_add)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn mul_add(self, a: Self, b: Self) -> Self;

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

	/// See <code>[f64]::[div_euclid](f64::div_euclid)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn div_euclid(self, rhs: Self) -> Self;

	/// See <code>[f64]::[rem_euclid](f64::rem_euclid)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn rem_euclid(self, rhs: Self) -> Self;

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

	/// See <code>[f64]::[powf](f64::powf)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn powf(self, rhs: Self) -> Self;

	/// See <code>[f64]::[powi](f64::powi)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn powi(self, rhs: Simd<i32, N>) -> Self;

	/// See <code>[f64]::[rhs](f64::exp)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn exp(self) -> Self;

	/// See <code>[f64]::[exp_m1](f64::exp_m1)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn exp_m1(self) -> Self;

	/// See <code>[f64]::[exp2](f64::exp2)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn exp2(self) -> Self;

	/// See <code>[f64]::[sqrt](f64::sqrt)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn sqrt(self) -> Self;

	/// See <code>[f64]::[cbrt](f64::cbrt)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn cbrt(self) -> Self;

	/// See <code>[f64]::[log](f64::log)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn log(self, base: Self) -> Self;

	/// See <code>[f64]::[ln](f64::ln)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn ln(self) -> Self;

	/// See <code>[f64]::[ln_1p](f64::ln_1p)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn ln_1p(self) -> Self;

	/// See <code>[f64]::[log2](f64::log2)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn log2(self) -> Self;

	/// See <code>[f64]::[log10](f64::log10)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn log10(self) -> Self;

	/// See <code>[f64]::[hypot](f64::hypot)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn hypot(self, rhs: Self) -> Self;

	/// See <code>[f64]::[sin](f64::sin)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn sin(self) -> Self;

	/// See <code>[f64]::[cos](f64::cos)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn cos(self) -> Self;

	/// See <code>[f64]::[tan](f64::tan)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn tan(self) -> Self;

	/// See <code>[f64]::[asin](f64::asin)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn asin(self) -> Self;

	/// See <code>[f64]::[acos](f64::acos)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn acos(self) -> Self;

	/// See <code>[f64]::[atan](f64::atan)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn atan(self) -> Self;

	/// See <code>[f64]::[atan2](f64::atan2)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn atan2(self, rhs: Self) -> Self;

	/// See <code>[f64]::[sinh](f64::sinh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn sinh(self) -> Self;

	/// See <code>[f64]::[cosh](f64::cosh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn cosh(self) -> Self;

	/// See <code>[f64]::[tanh](f64::tanh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn tanh(self) -> Self;

	/// See <code>[f64]::[asinh](f64::asinh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn asinh(self) -> Self;

	/// See <code>[f64]::[acosh](f64::acosh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn acosh(self) -> Self;

	/// See <code>[f64]::[atanh](f64::atanh)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn atanh(self) -> Self;

	/// See <code>[f64]::[round](f64::round)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn round(self) -> Self;

	/// See <code>[f64]::[round_ties_even](f64::round_ties_even)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn round_ties_even(self) -> Self;

	/// See <code>[f64]::[floor](f64::floor)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn floor(self) -> Self;

	/// See <code>[f64]::[ceil](f64::ceil)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn ceil(self) -> Self;

	/// See <code>[f64]::[trunc](f64::trunc)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn trunc(self) -> Self;

	/// See <code>[f64]::[fract](f64::fract)</code>.
	#[cfg(feature = "std")]
	#[must_use]
	fn fract(self) -> Self;

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

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

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

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

	/// See <code>[f64]::[copysign](f64::copysign)</code>.
	#[must_use]
	fn copysign(self, sign: Self) -> Self;

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

	/// See <code>[f64]::[clamp](f64::clamp)</code>.
	#[must_use]
	fn clamp(self, min: Self, max: Self) -> Self;

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

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

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

	/// See <code>[f64]::[classify](f64::classify)</code>.
	#[must_use]
	fn classify(self) -> [FpCategory; N];

	/// See <code>[f64]::[total_cmp](f64::total_cmp)</code>.
	#[must_use]
	fn total_cmp(&self, rhs: &Self) -> [Ordering; N];

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

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

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

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

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

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

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

	/// See <code>[f64]::[to_bits](f64::to_bits)</code>.
	#[must_use]
	fn to_bits(self) -> Simd<T::Bits, N>;
}