Skip to main content

Compensated

Struct Compensated 

Source
#[repr(C)]
pub struct Compensated<V> { pub value: V, pub error: V, }
Expand description

Compensated arithmetic number type.

This type represents a number as the sum of two components: a high-order value and a low-order error term. Using these, it can effectively double the mantissa precision of standard floating-point types, providing significantly improved accuracy for a wide range of numerical computations.

Compensated<f32 | f64> have some functionality required for use as an Element in vectorized types, but cannot use the math library. Use Vector<f32> or Vector<f64> as the inner type for full functionality.

Fields§

§value: V§error: V

Implementations§

Source§

impl<V: ScalarValue> Compensated<V>

Source

pub const fn new(value: V) -> Self

Creates a new compensated number with zero error term.

Source

pub fn value(self) -> V

Returns the normalized value (value + error).

Strict, so a re-bracketing into surrounding arithmetic cannot discard the second word instead of rounding it in.

Source

pub const fn uncompensated(self) -> V

Returns the uncompensated value, with no error term applied.

Source

pub const fn error(self) -> V

Returns the error term.

Source

pub fn normalize(self) -> Self

Source§

impl<V: CompensatedFloatVector> Compensated<V>

Source

pub fn splat_value(value: V::Element) -> Self

Source§

impl<V: ScalarValue> Compensated<V>

Source

pub fn accumulate_unnormalized(&mut self, rhs: Self)

Accumulate rhs into self without renormalization.

This should only be used in specific scenarios where renormalization is not desired, such as within iterative series expansions.

Source

pub fn reduce_unnormalized(&mut self, rhs: Self)

Reduce rhs from self without renormalization.

This should only be used in specific scenarios where renormalization is not desired, such as within iterative series expansions.

Source§

impl<V: ScalarValue> Compensated<V>

Source

pub fn div_scalar(num: V, denom: Self) -> Self

Source§

impl<V: ScalarValue> Compensated<V>

Source

pub fn from_fraction(numerator: V, denominator: V) -> Self

Creates a compensated number from a fraction numerator / denominator, dividing with compensation.

Source§

impl Compensated<f32>

Source

pub const fn from_f64(v: f64) -> Self

Create a compensated f32 value from an f64 value, preserving as much precision as possible.

Trait Implementations§

Source§

impl<V: ScalarValue> Add for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Self) -> Self::Output

Performs the + operation. Read more
Source§

impl<V: ScalarValue> Add<V> for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the + operator.
Source§

fn add(self, rhs: V) -> Self::Output

Performs the + operation. Read more
Source§

impl<V: Copy, T> AddAssign<T> for Compensated<V>
where Self: Add<T, Output = Self>,

Source§

fn add_assign(&mut self, rhs: T)

Performs the += operation. Read more
Source§

impl<V: CompensatedFloatVector, Rhs> AddAssignMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Add<Rhs, Output = Self>,

Source§

fn add_assign_c(&mut self, mask: V::Mask, rhs: Rhs)

Computes AddAssign with rhs where mask is true.
Source§

fn add_assign_m(&mut self, src: Self, mask: V::Mask, rhs: Rhs)

Merges AddAssign with src using mask, assigning src where mask is false.
Source§

fn add_assign_z(&mut self, mask: V::Mask, rhs: Rhs)

Computes AddAssign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector, Rhs> AddMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Add<Rhs, Output = Self>,

Source§

fn add_c(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Add with rhs where mask is true.
Source§

fn add_m(self, src: Self, mask: V::Mask, rhs: Rhs) -> Self

Merges Add with src using mask, returning src where mask is false.
Source§

fn add_z(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Add masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector> AddSubExt for Compensated<V>

Source§

type Output = Compensated<V>

The result of the lane-alternating operation.
Source§

fn addsub(self, b: Self) -> Self

[a0 - b0, a1 + b1, a2 - b2, ...] - even lanes subtract, odd lanes add.
Source§

fn fmaddsub(self, b: Self, c: Self) -> Self

[a0*b0 - c0, a1*b1 + c1, ...] - fused multiply then addsub.
Source§

fn fmsubadd(self, b: Self, c: Self) -> Self

[a0*b0 + c0, a1*b1 - c1, ...] - fused multiply then subadd (opposite parity).
Source§

impl<V: CompensatedFloatVector> AddSubExtMasked<<V as GenericVector>::Mask> for Compensated<V>

Source§

fn addsub_c(self, mask: V::Mask, b: Self) -> Self

addsub where mask is true, else self.
Source§

fn addsub_m(self, src: Self, mask: V::Mask, b: Self) -> Self

addsub where mask is true, else src.
Source§

fn addsub_z(self, mask: V::Mask, b: Self) -> Self

addsub where mask is true, else zero.
Source§

fn fmaddsub_c(self, mask: V::Mask, b: Self, c: Self) -> Self

fmaddsub where mask is true, else self.
Source§

fn fmaddsub_m(self, src: Self, mask: V::Mask, b: Self, c: Self) -> Self

fmaddsub where mask is true, else src.
Source§

fn fmaddsub_z(self, mask: V::Mask, b: Self, c: Self) -> Self

fmaddsub where mask is true, else zero.
Source§

fn fmsubadd_c(self, mask: V::Mask, b: Self, c: Self) -> Self

fmsubadd where mask is true, else self.
Source§

fn fmsubadd_m(self, src: Self, mask: V::Mask, b: Self, c: Self) -> Self

fmsubadd where mask is true, else src.
Source§

fn fmsubadd_z(self, mask: V::Mask, b: Self, c: Self) -> Self

fmsubadd where mask is true, else zero.
Source§

impl BernoulliNumbers for Compensated<f32>

Available on crate feature special only.
Source§

const B2N: &'static [Compensated<f32>]

$B_2, B_4, B_6, \ldots$, every even-index Bernoulli number finite in Self, starting at $B_2$, so that entry i is $B_{2i+2}$. Read more
Source§

impl BernoulliNumbers for Compensated<f64>

Available on crate feature special only.
Source§

const B2N: &'static [Compensated<f64>]

$B_2, B_4, B_6, \ldots$, every even-index Bernoulli number finite in Self, starting at $B_2$, so that entry i is $B_{2i+2}$. Read more
Source§

impl<V: CompensatedFloatVector> Bounded for Compensated<V>

Source§

fn min_value() -> Self

Returns the smallest finite number this type can represent
Source§

fn max_value() -> Self

Returns the largest finite number this type can represent
Source§

impl<FROM, TO> CastVector<Compensated<FROM>> for Compensated<TO>

Source§

fn cast_into(self) -> Compensated<FROM>

Convert this vector into a vector of type FROM, lane-by-lane.
Source§

fn cast_from(from: Compensated<FROM>) -> Self

Convert a vector of type FROM into Self, lane-by-lane, using as semantics on each element. See the trait docs for what float-to-int does with NaN and out-of-range lanes.
Source§

fn saturating_cast_from(from: FROM) -> Self

Convert lane-by-lane, clamping out-of-range values to Self’s element range rather than wrapping (integers) or producing a backend-defined value (float to int). Read more
Source§

fn fast_cast_from(from: FROM) -> Self

Like cast_from, but may take a faster path that relaxes IEEE corner cases. See GenericVector::fast_cast. Read more
Source§

fn fast_cast_into(self) -> FROM

Like cast_into, but may take a faster path that relaxes IEEE corner cases. See GenericVector::fast_cast.
Source§

impl<V: Clone> Clone for Compensated<V>

Source§

fn clone(&self) -> Compensated<V>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<V: ScalarValue> ConstDefault for Compensated<V>

Source§

const DEFAULT: Self

The constant default value.
Source§

impl<V: Copy> Copy for Compensated<V>

Source§

impl<V: Debug> Debug for Compensated<V>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<V: Default> Default for Compensated<V>

Source§

fn default() -> Compensated<V>

Returns the “default value” for a type. Read more
Source§

impl<V: PrettyPrintScalar> Display for Compensated<V>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<V: ScalarValue> Div for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Self) -> Self

Performs the / operation. Read more
Source§

impl<V: ScalarValue> Div<V> for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the / operator.
Source§

fn div(self, rhs: V) -> Self

Performs the / operation. Read more
Source§

impl<V: Copy, T> DivAssign<T> for Compensated<V>
where Self: Div<T, Output = Self>,

Source§

fn div_assign(&mut self, rhs: T)

Performs the /= operation. Read more
Source§

impl<V: CompensatedFloatVector, Rhs> DivAssignMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Div<Rhs, Output = Self>,

Source§

fn div_assign_c(&mut self, mask: V::Mask, rhs: Rhs)

Computes DivAssign with rhs where mask is true.
Source§

fn div_assign_m(&mut self, src: Self, mask: V::Mask, rhs: Rhs)

Merges DivAssign with src using mask, assigning src where mask is false.
Source§

fn div_assign_z(&mut self, mask: V::Mask, rhs: Rhs)

Computes DivAssign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector, Rhs> DivMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Div<Rhs, Output = Self>,

Source§

fn div_c(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Div with rhs where mask is true.
Source§

fn div_m(self, src: Self, mask: V::Mask, rhs: Rhs) -> Self

Merges Div with src using mask, returning src where mask is false.
Source§

fn div_z(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Div masked (zeroed where mask is false).
Source§

impl<E: ScalarValue + Element> Element for Compensated<E>

Source§

const ONE: Self

Source§

const ZERO: Self

Source§

const ORDER_MAX: Self

The greatest value under this type’s natural total order, and the least. Read more
Source§

const ORDER_MIN: Self

The least value under this type’s natural total order. See ORDER_MAX.
Source§

const HAS_UNORDERED: bool = E::HAS_UNORDERED

Whether values of this type can be unordered under PartialOrd - float NaN. false for every integer type. Read more
Source§

const IS_FLOAT: bool = E::IS_FLOAT

Whether this is a floating-point element type. This is distinct from HAS_UNORDERED because some float types may not have NaN and so are ordered, but still have some special properties of floats.
Source§

type Signed = <E as Element>::Signed

SignedBits integer type to be used with operations that require signed counts, such as shifts.
Source§

type Unsigned = <E as Element>::Unsigned

Unsigned integer type to be used with operations that require unsigned counts, such as shifts.
Source§

fn from_i8(value: i8) -> Self

Source§

fn from_u8(value: u8) -> Self

Source§

fn from_u16(value: u16) -> Self

Source§

impl EllipticConsts for Compensated<f64>

Available on crate feature special only.
Source§

const CARLSON_THRESH: Self

(3 * 2^-104)^(1/8)

Source§

const RC_SERIES_THRESH: Self

2^-14: the R_C series tail t^8/17 is then 1e-34. Below this the ln arm of the closed form loses about eps/s with s ~ sqrt(t) = 0.008, a few units of 1e-30, which is the accuracy floor of R_J on this type.

Source§

impl EllipticConsts for Compensated<f32>

Available on crate feature special only.
Source§

const CARLSON_THRESH: Self

(3 * 2^-46)^(1/8)

Source§

const RC_SERIES_THRESH: Self

1/128 still: the tail 1.5e-17 is below this type’s 2^-46.

Source§

impl<V: CompensatedFloatVector> ExpIntDetails<Compensated<<V as GenericVector>::Element>, Compensated<V>> for Compensated<V>
where Compensated<V>: FloatVector<Element = Compensated<V::Element>>,

Available on crate feature special only.

Double-double is still real arithmetic, so the regime and domain rules apply unchanged - but the Lentz sentinel does not.

Source§

fn cf_tiny() -> Compensated<V>

The default, MIN_POSITIVE, is reciprocated on the first Lentz step, and 1/2.2e-308 = 4.5e307 is past the ~1.3e300 where compensated multiplication’s Dekker 2^27+1 splitter overflows to infinity - so every continued-fraction lane came back NaN. expint takes the fraction for x >= 1, which is exactly where it failed.

Same defect and same fix as Complex, and as the erf/erfc tail in this crate: a sentinel only has to be negligible as a floor, but this one also has to survive being inverted.

Source§

fn use_series(z: V) -> <V as GenericVector>::Mask

Lanes that should take the power series rather than the continued fraction. Read more
Source§

fn invalid(z: V) -> <V as GenericVector>::Mask

Lanes outside the domain, forced to NaN when the policy checks overflow. Read more
Source§

impl<V: ScalarValue> FloatConsts for Compensated<V>

Source§

const NEG_ZERO: Self

Negative zero (-0) (only sign bit set)
Source§

const E: Self

Euler’s number (e)
Source§

const EULER_GAMMA: Self

Euler-Mascheroni constant (γ)
Source§

const PI_SQUARED: Self

$\pi^2$
Source§

const PI_CUBED: Self

$\pi^3$
Source§

const PI_FOURTH: Self

$\pi^4$
Source§

const FRAC_1_PI: Self

$1/\pi$
Source§

const FRAC_1_SQRT_2: Self

$1/\sqrt{2}$
Source§

const FRAC_1_SQRT_3: Self

$1/\sqrt{3}$
Source§

const FRAC_1_SQRT_5: Self

$1/\sqrt{5}$
Source§

const FRAC_2_PI: Self

$2/\pi$
Source§

const FRAC_1_SQRT_PI: Self

$1/\sqrt{\pi}$
Source§

const FRAC_1_SQRT_SQRT_PI: Self

$\pi^{-1/4}$, the normalization of the Hermite functions
Source§

const FRAC_2_SQRT_PI: Self

$2/\sqrt{\pi}$
Source§

const FRAC_SQRT_PI_2: Self

$\sqrt{\pi}/2$
Source§

const FRAC_1_SQRT_TAU: Self

$1/\sqrt{2\pi}$
Source§

const FRAC_PI_2: Self

$\pi/2$
Source§

const FRAC_PI_3: Self

$\pi/3$
Source§

const FRAC_PI_4: Self

$\pi/4$
Source§

const FRAC_PI_6: Self

$\pi/6$
Source§

const FRAC_PI_8: Self

$\pi/8$
Source§

const FRAC_PI_180: Self

$\pi/180$
Source§

const FRAC_180_PI: Self

$180/\pi$
Source§

const LN_2: Self

$\ln 2$
Source§

const LN_10: Self

$\ln 10$
Source§

const LN_PI: Self

$\ln \pi$
Source§

const LN_TAU: Self

$\ln 2\pi$
Source§

const LN_9: Self

$\ln 9$
Source§

const NINE_LN_9_HI: Self

$9 \ln 9$, the high word of the two-word split used by the Stirling shift in thermite-special’s Poisson kernel. $9 \ln 9 \approx 19.8$ sits in an exponent, where one rounding of it is about 8 ulp of the density.
Source§

const NINE_LN_9_LO: Self

$9 \ln 9$ minus NINE_LN_9_HI, exactly. Format-dependent like the epsilons.
Source§

const FRAC_LN_PI_2: Self

$\frac{1}{2}\ln \pi$
Source§

const FRAC_LN_TAU_2: Self

$\frac{1}{2}\ln 2\pi$, the constant term of the Stirling series for $\ln \Gamma$
Source§

const LOG2_10: Self

$\log_2 10$
Source§

const LOG2_E: Self

$\log_2 e$
Source§

const LOG2_PI: Self

$\log_2 \pi$
Source§

const LOG10_2: Self

$\log_{10} 2$
Source§

const LOG10_E: Self

$\log_{10} e$
Source§

const PI: Self

Archimedes’ constant (π)
Source§

const SQRT_2: Self

$\sqrt{2}$
Source§

const SQRT_3: Self

$\sqrt{3}$
Source§

const SQRT_5: Self

$\sqrt{5}$
Source§

const SQRT_E: Self

$\sqrt{e}$
Source§

const EPSILON: Self

The machine epsilon
Source§

const SQRT_EPSILON: Self

The square root of the machine epsilon ($\sqrt{\varepsilon}$)
Source§

const FOURTH_ROOT_EPSILON: Self

The fourth root of the machine epsilon ($\sqrt[4]{\varepsilon}$)
Source§

const TAU: Self

The full circle constant (τ)
Source§

const SQRT_FRAC_PI_2: Self

$\sqrt{\pi/2}$
Source§

const SQRT_TAU: Self

$\sqrt{2\pi}$
Source§

const PHI: Self

The golden ratio (φ)
Source§

const FRAC_1_PHI: Self

$1/\varphi = \varphi - 1$, the 1D golden-ratio low-discrepancy increment
Source§

const FRAC_1_PHI_SQUARED: Self

$1/\varphi^2$
Source§

const GOLDEN_ANGLE: Self

The golden angle $2\pi/\varphi^2 = \pi(3 - \sqrt{5})$ in radians Read more
Source§

const FRAC_1_3: Self

$1/3$
Source§

const FRAC_2_3: Self

$2/3$
Source§

const FRAC_1_4: Self

$1/4$
Source§

const FRAC_1_6: Self

$1/6$
Source§

const FRAC_1_E: Self

$1/e$
Source§

const FRAC_NEG_1_E: Self

$-1/e$
Source§

const FRAC_1_2: Self

$1/2$
Source§

const FRAC_3_4: Self

$3/4$
Source§

const LN_LN_2: Self

$\ln(\ln 2)$, the median of the Gumbel distribution
Source§

const SQRT_LN_4: Self

$\sqrt{\ln 4}$
Source§

const FRAC_2PI_3: Self

$2\pi/3$
Source§

const FRAC_3PI_4: Self

$3\pi/4$
Source§

const FRAC_4PI_3: Self

$4\pi/3$, the volume of the unit sphere
Source§

const FOUR_PI: Self

$4\pi$, the solid angle of the whole sphere in steradians
Source§

const FRAC_1_4PI: Self

$1/(4\pi)$, the density of the uniform distribution on the sphere
Source§

const FRAC_1_TAU: Self

$1/(2\pi)$
Source§

const SQRT_PI: Self

$\sqrt{\pi}$
Source§

const PI_MINUS_3: Self

$\pi - 3$
Source§

const FOUR_MINUS_PI: Self

$4 - \pi$
Source§

const PI_POW_E: Self

$\pi^e$
Source§

const CBRT_2: Self

$\sqrt[3]{2}$
Source§

const CBRT_3: Self

$\sqrt[3]{3}$
Source§

const CBRT_PI: Self

$\sqrt[3]{\pi}$
Source§

const FRAC_1_CBRT_PI: Self

$1/\sqrt[3]{\pi}$
Source§

const FRAC_1_SQRT_E: Self

$1/\sqrt{e} = e^{-1/2}$
Source§

const E_POW_PI: Self

$e^\pi$, Gelfond’s constant
Source§

const GELFOND_SCHNEIDER: Self

$2^{\sqrt{2}}$, the Gelfond-Schneider constant (also called Hilbert’s number)
Source§

const SIN_1: Self

$\sin 1$
Source§

const COS_1: Self

$\cos 1$
Source§

const TAN_1: Self

$\tan 1$
Source§

const SINH_1: Self

$\sinh 1$
Source§

const COSH_1: Self

$\cosh 1$
Source§

const TANH_1: Self

$\tanh 1$
Source§

const LN_PHI: Self

$\ln \varphi$
Source§

const FRAC_1_LN_PHI: Self

$1/\ln \varphi$
Source§

const FRAC_1_EULER_GAMMA: Self

$1/\gamma$
Source§

const EULER_GAMMA_SQUARED: Self

$\gamma^2$
Source§

const ZETA_2: Self

$\zeta(2) = \pi^2/6$
Source§

const ZETA_3: Self

$\zeta(3)$, Apery’s constant
Source§

const ZETA_4: Self

$\zeta(4) = \pi^4/90$
Source§

const CATALAN: Self

Catalan’s constant $K$
Source§

const GLAISHER: Self

The Glaisher-Kinkelin constant $A$
Source§

const KHINCHIN: Self

Khinchin’s constant $K_0$
Source§

const LEVY: Self

Levy’s constant $e^{\pi^2/(12\ln 2)}$ Read more
Source§

const EXTREME_VALUE_SKEWNESS: Self

$12\sqrt{6}\,\zeta(3)/\pi^3$, the skewness of the extreme value distribution
Source§

const RAYLEIGH_SKEWNESS: Self

$2\sqrt{\pi}(\pi-3)/(4-\pi)^{3/2}$, the skewness of the Rayleigh distribution
Source§

const RAYLEIGH_KURTOSIS_EXCESS: Self

$-(6\pi^2 - 24\pi + 16)/(4-\pi)^2$, the excess kurtosis of the Rayleigh distribution
Source§

const RAYLEIGH_KURTOSIS: Self

$3 - (6\pi^2 - 24\pi + 16)/(4-\pi)^2$, the kurtosis of the Rayleigh distribution Read more
Source§

const FEIGENBAUM_DELTA: Self

The first Feigenbaum constant $\delta$
Source§

const PLASTIC_RATIO: Self

The plastic ratio $\rho$, the real root of $x^3 = x + 1$
Source§

const FRAC_1_PLASTIC_RATIO: Self

$1/\rho$, the first increment of the 2D R2 low-discrepancy sequence Read more
Source§

const FRAC_1_PLASTIC_RATIO_SQUARED: Self

$1/\rho^2$, the second R2 increment
Source§

const GAUSS: Self

Gauss’s constant $G = 1/\mathrm{agm}(1, \sqrt{2})$
Source§

const LEMNISCATE: Self

The lemniscate constant $\varpi = \pi G = 2\int_0^1 dt/\sqrt{1-t^4}$
Source§

const DOTTIE: Self

The Dottie number, the unique real solution of $\cos x = x$
Source§

const OMEGA: Self

The omega constant $\Omega$, the solution of $\Omega e^{\Omega} = 1$, i.e. $W(1)$
Source§

const PSI: Self

The reciprocal Fibonacci constant $\psi = \sum_{k=1}^{\infty} 1/F_k$
Source§

const LAPLACE_LIMIT: Self

The Laplace limit, the root of $x e^{\sqrt{1+x^2}} / (1 + \sqrt{1+x^2}) = 1$
Source§

const ERDOS_BORWEIN: Self

The Erdos-Borwein constant $E = \sum_{k=1}^{\infty} 1/(2^k - 1)$
Source§

const NIVEN: Self

Niven’s constant $1 + \sum_{k=2}^{\infty} (1 - 1/\zeta(k))$, the average maximum prime exponent
Source§

const SOLDNER: Self

The Ramanujan-Soldner constant $\mu$, the positive root of the logarithmic integral $\mathrm{li}(x)$
Source§

const FRANSEN_ROBINSON: Self

The Fransen-Robinson constant $\int_0^{\infty} dx/\Gamma(x)$
Source§

const GOLOMB_DICKMAN: Self

The Golomb-Dickman constant $\lambda = \int_0^1 e^{\mathrm{li}(t)}\,dt$
Source§

const TWIN_PRIME: Self

The twin prime constant $C_2 = \prod_{p \ge 3} (1 - 1/(p-1)^2)$
Source§

const MERTENS: Self

The Meissel-Mertens constant $M = \gamma + \sum_p (\ln(1 - 1/p) + 1/p)$
Source§

const ARTIN: Self

Artin’s constant $A = \prod_p (1 - 1/(p(p-1)))$ Read more
Source§

impl<E: ScalarValue + FloatElement> FloatElement for Compensated<E>

Source§

const HAS_INFINITY: bool = E::HAS_INFINITY

Does the format support Infinity? If FALSE, overflow saturates to MAX_FINITE instead of INF. (e.g., E4M3 = false, E5M2 = true)
Source§

const HAS_SIGNED_ZERO: bool = E::HAS_SIGNED_ZERO

Does the format distinguish between +0 and -0? (Usually true, but some integer-like quantizations might not)
Source§

const HAS_SUBNORMALS: bool = E::HAS_SUBNORMALS

Does the format support subnormal numbers? If FALSE, any value smaller than MinNormal is flushed to zero (FTZ).
Source§

type ConstInt<const N: LargeInt> = <E as ScalarValue>::CompensatedConstInt<N>

Marker type for splatting a compile-time integer constant as this float type. Read more
Source§

type ConstRatio<const N: LargeInt, const D: LargeInt> = <E as ScalarValue>::CompensatedConstRatio<N, D>

Marker type for splatting a compile-time rational constant (N/D) as this float type. Read more
Source§

fn sqrt(this: Self) -> Self

Source§

fn floor(this: Self) -> Self

Source§

fn ceil(this: Self) -> Self

Source§

fn round(this: Self) -> Self

Round to nearest, ties to even. Read more
Source§

fn trunc(this: Self) -> Self

Source§

fn next_up(this: Self) -> Self

Source§

fn next_down(this: Self) -> Self

Source§

fn try_from_int(value: LargeInt) -> Option<Self>

Try to represent this LargeInt value as this float type, returning None if it cannot be represented exactly.
Source§

fn try_from_ratio(n: LargeInt, d: LargeInt) -> Option<Self>

Source§

fn from_int(value: i64) -> Self

Source§

fn from_ratio(n: i64, d: i64) -> Self

Source§

fn fract(value: Self) -> Self

Source§

impl<V: CompensatedFloatVector> FloatVector for Compensated<V>

Source§

type ExtendedPrecision = Compensated<V>

Don’t use Compensated if you need to go higher precision than it provides.

If you absolutely must, use CastVector to convert to a higher-precision type.

Source§

const HALF: Self

The value 0.5 represented in this vector type.
Source§

const NEG_ZERO: Self

The value -0.0 represented in this vector type.
Source§

const INFINITY: Self

The value infinity represented in this vector type.
Source§

const NEG_INFINITY: Self

The value -infinity represented in this vector type.
Source§

const NAN: Self

The value NaN represented in this vector type.
Source§

const EPSILON: Self

Hardware epsilon value in this vector type.
Source§

const HAS_APPROX_RCP: bool = false

true if the backend has a hardware approximate-reciprocal instruction (e.g. rcpps on x86). When false, rcp falls back to a full IEEE division and provides no speed advantage over Self::ONE / self.
Source§

const HAS_APPROX_RSQRT: bool = false

true if the backend has a hardware approximate-reciprocal-square-root instruction (e.g. rsqrtps on x86). When false, rsqrt falls back to Self::ONE / self.sqrt().
Source§

fn is_infinite(self) -> Self::Mask

Check if each element in the vector is infinite, returning a mask.
Source§

fn is_finite(self) -> Self::Mask

Check if each element in the vector is finite, returning a mask.
Source§

fn is_nan(self) -> Self::Mask

Check if each element in the vector is NaN, returning a mask.
Source§

fn is_zero_or_subnormal(self) -> Self::Mask

Check if each element in the vector is zero or subnormal, returning a mask.
Source§

fn is_normal(self) -> Self::Mask

Check if each element in the vector is normal, returning a mask.
Source§

fn is_subnormal(self) -> Self::Mask

Check if each element in the vector is subnormal, returning a mask.
Source§

fn sqrt(self) -> Self

Lane-wise IEEE 754 square root. Read more
Source§

fn rsqrt(self) -> Self

Lane-wise approximate reciprocal square root. Read more
Source§

fn rcp(self) -> Self

Lane-wise approximate reciprocal: 1 / self. Read more
Source§

fn floor(self) -> Self

Lane-wise floor: largest integer less than or equal to each element. Read more
Source§

fn ceil(self) -> Self

Lane-wise ceiling: smallest integer greater than or equal to each element, kept in the float representation.
Source§

fn round(self) -> Self

Lane-wise round-to-nearest, ties to even (banker’s rounding). Read more
Source§

fn trunc(self) -> Self

Lane-wise truncation toward zero (drops the fractional part), kept in the float representation.
Source§

fn fract(self) -> Self

Lane-wise fractional part: self - self.trunc(). Read more
Source§

fn mul_sign(self, sign: Self) -> Self

Effectively self * sign.signum(), multiplying the sign bits.
Source§

fn signed_zero(self) -> Self

Returns zero with the sign of self, i.e.: only the sign bit is set.
Source§

fn next_up(self) -> Self

Returns the next representable value greater than the current value, towards positive infinity.
Source§

fn next_down(self) -> Self

Returns the next representable value less than the current value, towards negative infinity.
Source§

unsafe fn block_autovectorization(&mut self)

Inhibit further LLVM auto-vectorization of code surrounding this call. Read more
Source§

fn sqrt_c(self, mask: Self::Mask) -> Self

Lane-wise IEEE 754 square root. Read more
Source§

fn sqrt_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise IEEE 754 square root. Read more
Source§

fn sqrt_z(self, mask: Self::Mask) -> Self

Lane-wise IEEE 754 square root. Read more
Source§

fn rsqrt_c(self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal square root. Read more
Source§

fn rsqrt_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal square root. Read more
Source§

fn rsqrt_z(self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal square root. Read more
Source§

fn rcp_c(self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal: 1 / self. Read more
Source§

fn rcp_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal: 1 / self. Read more
Source§

fn rcp_z(self, mask: Self::Mask) -> Self

Lane-wise approximate reciprocal: 1 / self. Read more
Source§

fn floor_c(self, mask: Self::Mask) -> Self

Lane-wise floor: largest integer less than or equal to each element. Read more
Source§

fn floor_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise floor: largest integer less than or equal to each element. Read more
Source§

fn floor_z(self, mask: Self::Mask) -> Self

Lane-wise floor: largest integer less than or equal to each element. Read more
Source§

fn ceil_c(self, mask: Self::Mask) -> Self

Lane-wise ceiling: smallest integer greater than or equal to each element, kept in the float representation. Computes ceil when mask is true, returns self where false.
Source§

fn ceil_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise ceiling: smallest integer greater than or equal to each element, kept in the float representation. Merges ceil with src using mask.
Source§

fn ceil_z(self, mask: Self::Mask) -> Self

Lane-wise ceiling: smallest integer greater than or equal to each element, kept in the float representation. Computes ceil masked (zeroed where mask is false).
Source§

fn round_c(self, mask: Self::Mask) -> Self

Lane-wise round-to-nearest, ties to even (banker’s rounding). Read more
Source§

fn round_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise round-to-nearest, ties to even (banker’s rounding). Read more
Source§

fn round_z(self, mask: Self::Mask) -> Self

Lane-wise round-to-nearest, ties to even (banker’s rounding). Read more
Source§

fn trunc_c(self, mask: Self::Mask) -> Self

Lane-wise truncation toward zero (drops the fractional part), kept in the float representation. Computes trunc when mask is true, returns self where false.
Source§

fn trunc_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise truncation toward zero (drops the fractional part), kept in the float representation. Merges trunc with src using mask.
Source§

fn trunc_z(self, mask: Self::Mask) -> Self

Lane-wise truncation toward zero (drops the fractional part), kept in the float representation. Computes trunc masked (zeroed where mask is false).
Source§

fn fract_c(self, mask: Self::Mask) -> Self

Lane-wise fractional part: self - self.trunc(). Read more
Source§

fn fract_m(self, src: Self, mask: Self::Mask) -> Self

Lane-wise fractional part: self - self.trunc(). Read more
Source§

fn fract_z(self, mask: Self::Mask) -> Self

Lane-wise fractional part: self - self.trunc(). Read more
Source§

fn signed_zero_c(self, mask: Self::Mask) -> Self

Returns zero with the sign of self, i.e.: only the sign bit is set. Computes signed_zero when mask is true, returns self where false.
Source§

fn signed_zero_m(self, src: Self, mask: Self::Mask) -> Self

Returns zero with the sign of self, i.e.: only the sign bit is set. Merges signed_zero with src using mask.
Source§

fn signed_zero_z(self, mask: Self::Mask) -> Self

Returns zero with the sign of self, i.e.: only the sign bit is set. Computes signed_zero masked (zeroed where mask is false).
Source§

fn next_up_c(self, mask: Self::Mask) -> Self

Returns the next representable value greater than the current value, towards positive infinity. Computes next_up when mask is true, returns self where false.
Source§

fn next_up_m(self, src: Self, mask: Self::Mask) -> Self

Returns the next representable value greater than the current value, towards positive infinity. Merges next_up with src using mask.
Source§

fn next_up_z(self, mask: Self::Mask) -> Self

Returns the next representable value greater than the current value, towards positive infinity. Computes next_up masked (zeroed where mask is false).
Source§

fn next_down_c(self, mask: Self::Mask) -> Self

Returns the next representable value less than the current value, towards negative infinity. Computes next_down when mask is true, returns self where false.
Source§

fn next_down_m(self, src: Self, mask: Self::Mask) -> Self

Returns the next representable value less than the current value, towards negative infinity. Merges next_down with src using mask.
Source§

fn next_down_z(self, mask: Self::Mask) -> Self

Returns the next representable value less than the current value, towards negative infinity. Computes next_down masked (zeroed where mask is false).
Source§

fn mul_sign_c(self, mask: Self::Mask, rhs: Self) -> Self

Effectively self * sign.signum(), multiplying the sign bits. Computes mul_sign when mask is true, returns self where false.
Source§

fn mul_sign_m(self, src: Self, mask: Self::Mask, rhs: Self) -> Self

Effectively self * sign.signum(), multiplying the sign bits. Merges mul_sign with src using mask.
Source§

fn mul_sign_z(self, mask: Self::Mask, rhs: Self) -> Self

Effectively self * sign.signum(), multiplying the sign bits. Computes mul_sign masked (zeroed where mask is false).
Source§

fn mix(self, a: Self, b: Self) -> Self

Linearly interpolates between a and b by self, where self is typically in the range [0, 1]. Read more
Source§

fn one_minus_sq(self) -> Self

Computes $1 - x^2$ accurately, avoiding the cancellation a naive 1 - self * self suffers as self approaches ±1 (where the result is small but self * self is near 1). Read more
Source§

fn with_bits<const N: usize, K>( _values: [Self; N], _kernel: K, ) -> Option<<K as AsFloatVectorWithBitsKernel<Self, N>>::Output>
where K: AsFloatVectorWithBitsKernel<Self, N>,

Attempt to upcast this FloatVector to a FloatVectorWithBits, using the provided kernel. If not possible, returns None.
Source§

impl<V: CompensatedFloatVector> GenericSelectable for Compensated<V>

Source§

type SelectableMask = <V as GenericSelectable>::SelectableMask

The mask type whose lane count and layout match Self.
Source§

fn select<M>(mask: M, t: Self, f: Self) -> Self
where Self::SelectableMask: CastMask<M>,

For each lane, take the value from t where mask is true, otherwise from f.
Source§

impl<V: CompensatedFloatVector> GenericVector for Compensated<V>

Source§

unsafe fn load_deinterleaved<const M: usize>( ptr: *const Self::Element, ) -> [Self; M]

A Compensated element is #[repr(C)] over two floats (value, error), so M interleaved Compensated streams are exactly 2 * M interleaved float streams, precisely a grouped problem with TAIL = 1 (see StreamGroup). This hands M straight to the inner vector’s GenericVector::load_deinterleaved_grouped (a NEON LD2/LD3/LD4, or a shuffle network on x86), for any M: no dispatch ladder, no scalar fallback.

Source§

unsafe fn store_interleaved<const M: usize>( ptr: *mut Self::Element, values: [Self; M], )

The exact inverse of load_deinterleaved.

Source§

const EMPTY: Self

A vector with all elements zeroed.
Source§

const LANES: usize = V::LANES

Number of lanes in the vector.
Source§

const HAS_NATIVE_ALIGN: bool = V::HAS_NATIVE_ALIGN

Whether align is a native cross-register instruction rather than the generic shuffle-and-blend fallback, forwarded from Register::HAS_NATIVE_ALIGN. Read more
Source§

type Element = Compensated<<V as GenericVector>::Element>

Scalar element type of the vector.
Source§

type Lanes = <V as GenericVector>::Lanes

Number of lanes in the vector, as a typenum.
Source§

type Unsigned = <V as GenericVector>::Unsigned

Unsigned Integer Type suitable for use with this vector.
Source§

type Signed = <V as GenericVector>::Signed

SignedBits Integer Type suitable for use with this vector.
Source§

type Mask = <V as GenericVector>::Mask

Mask type for this vector. Masks are semantically boolean vectors indicating true or false for each lane. They may or may not be represented as actual bits.
Source§

fn permutev(self, indices: Self::Unsigned) -> Self

Permute lanes by a live index vector: lane i of the result is self[indices[i]]. Read more
Source§

fn swizzle(self, other: Self, indices: Self::Unsigned) -> Self

Select lanes from the concatenation [self, other] by a live index vector: index i < LANES takes self[i], LANES <= i < 2*LANES takes other[i - LANES]. Read more
Source§

fn new<const N: usize>(value: [Self::Element; N]) -> Self
where Const<N>: IntoArrayLength<ArrayLength = Self::Lanes>,

Create a new vector from an array of elements. Read more
Source§

fn into_array(self) -> GenericArray<Self::Element, Self::Lanes>

Consume the vector and return its elements as a GenericArray. Read more
Source§

fn splat(value: Self::Element) -> Self

Create a new vector from a single element by splatting it across all lanes.
Source§

fn single(value: Self::Element) -> Self

Create a new vector with the first lane set to the given value, and all other lanes set to zero.
Source§

unsafe fn load(ptr: *const Self::Element) -> Self

Load a vector from an aligned pointer to its elements. Read more
Source§

fn interleave_by<const GROUP: usize>(self, other: Self) -> (Self, Self)

Interleave two vectors at group granularity: blocks of GROUP consecutive elements move as a unit and are never split. GROUP == 1 is interleave; GROUP == 2 is the complex interleave - lo == [a.c0, b.c0, a.c1, b.c1, ...] over the low half of the groups, hi over the high half - which lowers to the doubled-element unpack (unpacklo_pd + permute2f128 on AVX2, zip on NEON) rather than a general permute. The primitive for complex FFT transposes and any group-structured SIMD. GROUP must divide LANES. Read more
Source§

fn deinterleave_by<const GROUP: usize>(self, other: Self) -> (Self, Self)

The inverse of interleave_by - group-granularity de-interleave.
Source§

fn interleave_radix<const N: usize>(inputs: [Self; N]) -> [Self; N]

Radix-N interleave: the generic sibling of interleave (N == 2). Treats the N inputs as one contiguous N * LANES span and gives out with concat(out)[q * N + r] == inputs[r].extract(q). Read more
Source§

fn deinterleave_radix<const N: usize>(inputs: [Self; N]) -> [Self; N]

The inverse of interleave_radix - radix-N de-interleave: out[r].extract(q) == concat(inputs)[q * N + r].
Source§

fn deinterleave_radix_by<const N: usize, const GROUP: usize>( inputs: [Self; N], ) -> [Self; N]

Group-granularity radix-N de-interleave: the two-axis unification of deinterleave_radix (GROUP == 1) and deinterleave_by (N == 2). Each vector is viewed as LANES / GROUP groups of GROUP consecutive elements; out[r] group q is the (q * N + r)-th group of the concatenated input sequence, each group moving as a unit. Read more
Source§

fn interleave_radix_by<const N: usize, const GROUP: usize>( inputs: [Self; N], ) -> [Self; N]

The inverse of deinterleave_radix_by - group-granularity radix-N interleave. For the square case it is the same (self-inverse) register-array transpose.
Source§

unsafe fn load_m(src: Self, mask: Self::Mask, ptr: *const Self::Element) -> Self

Load a vector from an aligned pointer to its elements. Read more
Source§

unsafe fn load_z(mask: Self::Mask, ptr: *const Self::Element) -> Self

Load a vector from an aligned pointer to its elements. Read more
Source§

unsafe fn load_unaligned(ptr: *const Self::Element) -> Self

Load a vector from an unaligned pointer to its elements. Read more
Source§

unsafe fn load_streaming(ptr: *const Self::Element) -> Self

Load a vector from a pointer to its elements using non-temporal (streaming) loads. Read more
Source§

unsafe fn store(self, ptr: *mut Self::Element)

Store the vector to an aligned pointer to its elements. Read more
Source§

unsafe fn store_masked(self, mask: Self::Mask, ptr: *mut Self::Element)

Store the vector to an aligned pointer to its elements, but only for lanes where the corresponding mask lane is true. For lanes where the mask is false, the store is suppressed without panicking. Read more
Source§

unsafe fn store_unaligned(self, ptr: *mut Self::Element)

Store the vector to an unaligned pointer to its elements. Read more
Source§

unsafe fn store_streaming(self, ptr: *mut Self::Element)

Store the vector to a pointer to its elements using non-temporal (streaming) stores. Read more
Source§

unsafe fn lookup_unchecked( values: &[Self::Element], indices: Self::Unsigned, ) -> Self

Assemble a vector from a slice of elements and a vector of indices into that slice. The indices are NOT checked to be within bounds. Read more
Source§

fn broadcast<const I: usize>(self) -> Self

Broadcast the value of a single lane across all lanes of the vector.
Source§

fn broadcastv(self, idx: usize) -> Self

Broadcast the value of a single lane across all lanes of the vector. Read more
Source§

fn extract<const I: usize>(self) -> Self::Element

Extract a single element from the vector at the const-generic index I. Read more
Source§

fn extractv(self, idx: usize) -> Self::Element

Extract a single element from the vector at the runtime index idx. Read more
Source§

fn insert<const I: usize>(self, value: Self::Element) -> Self

Replace a single element in the vector at the const-generic index I. Read more
Source§

fn insertv(self, idx: usize, value: Self::Element) -> Self

Replace a single element in the vector at the runtime index idx. Read more
Source§

fn reverse(self) -> Self

Reverse the order of the elements in the vector. Read more
Source§

fn swap_bytes(self) -> Self

Swap the byte order of each element in the vector, converting between little-endian and big-endian representations lane-by-lane. Read more
Source§

fn zz(self, mask: Self::Mask) -> Self

(Zero If False) Zero elements if the corresponding mask lane is false; otherwise, leave unchanged. Read more
Source§

fn nz(self, mask: Self::Mask) -> Self

(Zero If True) Zero elements if the corresponding mask lane is true; otherwise, leave unchanged. Read more
Source§

fn compress(self, mask: Self::Mask) -> Self

Left-pack (a.k.a. compress): gather the lanes where mask is true into the low lanes, preserving their relative order. The unselected lanes are kept (not zeroed) and packed into the high lanes, also in order - a stable partition of the vector by mask. Read more
Source§

fn compress_z(self, mask: Self::Mask) -> Self

Zero-filling left-pack: like compress, but the lanes beyond the mask population count are zeroed instead of holding the unselected elements. Matches AVX-512 zero-masking vpcompress*. Read more
Source§

fn compress_m(self, src: Self, mask: Self::Mask) -> Self

Merge-masked left-pack: like compress, but the lanes at and beyond the mask population count take their values from src (at their own positions). Matches AVX-512 merge-masked vpcompress*. Read more
Source§

fn expand(self, mask: Self::Mask) -> Self

Inverse left-pack (expand): scatter this vector’s packed low lanes back out to the lanes where mask is set, preserving order; the unselected lanes read the tail. The exact inverse permutation of compress: v.compress(m).expand(m) == v and v.expand(m).compress(m) == v for every v and m. Read more
Source§

fn expand_z(self, mask: Self::Mask) -> Self

Zero-filling inverse left-pack: like expand, but the unselected lanes are zeroed. Matches AVX-512 zero-masking vpexpand*. Read more
Source§

fn expand_m(self, src: Self, mask: Self::Mask) -> Self

Merge-masked inverse left-pack: like expand, but the unselected lanes take their values from src. Matches AVX-512 merge-masked vpexpand*. Read more
Source§

fn align<const OFFSET: usize>(self, other: Self) -> Self

Two-register element align (the palignr family): the window of LANES lanes starting at lane OFFSET of the concatenation [self, other] (self’s lanes first, then other’s). OFFSET == 0 returns self, OFFSET == LANES returns other; in between, lanes spill from the tail of self into the head of other. Read more
Source§

fn map<F>(self, f: F) -> Self
where F: Fn(Self::Element) -> Self::Element,

Apply a function to each element in the vector, returning a new vector with the results. Read more
Source§

fn fold<F>(self, init: Self::Element, f: F) -> Self::Element
where F: Fn(Self::Element, Self::Element) -> Self::Element,

Fold the elements of the vector using the provided function and initial value. Read more
Source§

fn reduce<F>(self, f: F) -> Self::Element
where F: Fn(Self::Element, Self::Element) -> Self::Element,

Reduce the elements of the vector using the provided function. Read more
Source§

fn splat_m(src: Self, mask: Self::Mask, value: Self::Element) -> Self

Create a new vector from a single element by splatting it across all lanes. Merges splat with src using mask.
Source§

fn splat_z(mask: Self::Mask, value: Self::Element) -> Self

Create a new vector from a single element by splatting it across all lanes. Computes splat masked (zeroed where mask is false).
Source§

fn broadcast_c<const I: usize>(self, mask: Self::Mask) -> Self

Broadcast the value of a single lane across all lanes of the vector. Computes broadcast when mask is true, returns self where false.
Source§

fn broadcast_m<const I: usize>(self, src: Self, mask: Self::Mask) -> Self

Broadcast the value of a single lane across all lanes of the vector. Merges broadcast with src using mask.
Source§

fn broadcast_z<const I: usize>(self, mask: Self::Mask) -> Self

Broadcast the value of a single lane across all lanes of the vector. Computes broadcast masked (zeroed where mask is false).
Source§

fn broadcastv_c(self, mask: Self::Mask, idx: usize) -> Self

Broadcast the value of a single lane across all lanes of the vector. Read more
Source§

fn broadcastv_m(self, src: Self, mask: Self::Mask, idx: usize) -> Self

Broadcast the value of a single lane across all lanes of the vector. Read more
Source§

fn broadcastv_z(self, mask: Self::Mask, idx: usize) -> Self

Broadcast the value of a single lane across all lanes of the vector. Read more
Source§

fn reverse_c(self, mask: Self::Mask) -> Self

Reverse the order of the elements in the vector. Read more
Source§

fn reverse_m(self, src: Self, mask: Self::Mask) -> Self

Reverse the order of the elements in the vector. Read more
Source§

fn reverse_z(self, mask: Self::Mask) -> Self

Reverse the order of the elements in the vector. Read more
Source§

fn swap_bytes_c(self, mask: Self::Mask) -> Self

Swap the byte order of each element in the vector, converting between little-endian and big-endian representations lane-by-lane. Read more
Source§

fn swap_bytes_m(self, src: Self, mask: Self::Mask) -> Self

Swap the byte order of each element in the vector, converting between little-endian and big-endian representations lane-by-lane. Read more
Source§

fn swap_bytes_z(self, mask: Self::Mask) -> Self

Swap the byte order of each element in the vector, converting between little-endian and big-endian representations lane-by-lane. Read more
Source§

fn lanes() -> usize

Number of lanes in the vector, as a runtime value. Read more
Source§

fn concat<INTO>(self, hi: Self) -> INTO
where INTO: ConcatVector<Self, Element = Self::Element>,

Combine two vectors of the same type into one wider vector, with self as the lower half and hi as the upper half.
Source§

fn split<INTO>(self) -> (INTO, INTO)
where INTO: GenericVector, Self: ConcatVector<INTO, Element = <INTO as GenericVector>::Element>,

Split this vector into two narrower vectors of the same type, with the lower lanes in the first vector and the upper lanes in the second vector.
Source§

fn extend<INTO>(self) -> INTO
where INTO: ExtendVector<Self, Element = Self::Element>,

Zero-extend a narrower vector into this wider vector type, placing the original values in the lower lanes and filling the upper lanes with zeros.
Source§

fn narrow<INTO>(self) -> INTO
where INTO: GenericVector, Self: ExtendVector<INTO, Element = <INTO as GenericVector>::Element>,

Narrow this wider vector into a narrower vector by taking the lower lanes. Read more
Source§

fn align_slice( slice: &[Self::Element], ) -> (&[Self::Element], &[Self], &[Self::Element])

Align a slice of elements to the vector’s lane count, returning the aligned portion and any unaligned head or tail. Read more
Source§

fn align_slice_mut( slice: &mut [Self::Element], ) -> (&mut [Self::Element], &mut [Self], &mut [Self::Element])

Align a mutable slice of elements to the vector’s lane count, returning the aligned portion and any unaligned head or tail. Read more
Source§

fn from_slice(slice: &[Self::Element]) -> Self

Create a new vector from a slice of elements. The slice must have at least as many elements as the vector’s lanes. Read more
Source§

fn copy_to_slice(self, slice: &mut [Self::Element])

Copy the elements of the vector into a slice. The slice must have at least as many elements as the vector’s lanes. Read more
Source§

fn iter_unaligned<'a>( values: &'a [Self::Element], ) -> (Unaligned<'a, Self>, &'a [Self::Element])

Transform a slice of element values into an unaligned iterator of vectors, returning any remaining elements as a suffix slice.
Source§

fn iter_mut_unaligned<'a>( values: &'a mut [Self::Element], ) -> (UnalignedMut<'a, Self>, &'a mut [Self::Element])

Transform a mutable slice of element values into an unaligned iterator of vectors, returning any remaining elements as a suffix slice.
Source§

fn stream_aligned_slice<'a>( values: &'a [Self::Element], ) -> impl DoubleEndedIterator

Iterate over a slice of element values as Vectors using non-temporal (streaming) loads. Read more
Source§

fn stream_aligned_slice_mut<'a>( values: &'a mut [Self::Element], ) -> impl DoubleEndedIterator

Iterate over a mutable slice of element values as Vectors using non-temporal (streaming) loads and stores. Read more
Source§

fn gather<I>(slice: &[Self::Element], indices: I) -> Self
where I: VectorIndices<Self>,

Gather elements from memory at the specified indices and return a new vector with those elements. Read more
Source§

fn gather_or<I>(slice: &[Self::Element], indices: I, or: Self) -> Self
where I: VectorIndices<Self>, Self::Mask: CastMask<<I as GenericVector>::Mask>,

Gather elements from memory at the specified indices, or return or if the index is out of bounds. Read more
Source§

fn gather_or_zero<I>(slice: &[Self::Element], indices: I) -> Self
where I: VectorIndices<Self>, Self::Mask: CastMask<<I as GenericVector>::Mask>,

Gather elements from memory at the specified indices, or set the lane to zero if the index is out of bounds. Read more
Source§

fn gather_if<I>( slice: &[Self::Element], enable: Self::Mask, indices: I, or: Self, ) -> Self
where I: VectorIndices<Self>, Self::Mask: CastMask<<I as GenericVector>::Mask>, Self::Element: Default,

Gather elements from memory at the specified indices, or return or if the enable mask is false OR if any index is out of bounds. Read more
Source§

fn scatter<I>(self, slice: &mut [Self::Element], indices: I)
where I: VectorIndices<Self>, Self::Mask: CastMask<<I as GenericVector>::Mask>,

Scatter elements from the given vector into memory at the specified indices. If the index is outside of the bounds of the provided slice, the write is suppressed without panicking.
Source§

fn scatter_if<I>( self, slice: &mut [Self::Element], enable: Self::Mask, indices: I, )
where I: VectorIndices<Self>, Self::Mask: CastMask<<I as GenericVector>::Mask>,

Scatter elements from the given vector into memory at the specified indices, but only for lanes where the enable mask is true. If the index is outside of the bounds of the provided slice, the write is suppressed without panicking.
Source§

unsafe fn load_deinterleaved_arrays<const M: usize, const C: usize>( ptr: *const Self::Element, ) -> [[Self; C]; M]

Load M interleaved AoS records of C components each and de-interleave them: reads M * C * LANES contiguous elements, and out[j][c] holds component c of record j (out[j][c].extract(lane) == ptr[lane * M * C + j * C + c]). Read more
Source§

unsafe fn store_interleaved_arrays<const M: usize, const C: usize>( ptr: *mut Self::Element, values: [[Self; C]; M], )

Interleave M records of C components and store them contiguously - the exact inverse of load_deinterleaved_arrays, with the same lane-wise default. Read more
Source§

unsafe fn load_deinterleaved_grouped<const M: usize, const TAIL: usize>( ptr: *const Self::Element, ) -> [StreamGroup<Self, TAIL>; M]

Load M interleaved composite streams of 1 + TAIL components each and de-interleave them into M StreamGroups: reads M * (TAIL + 1) * LANES contiguous elements, and group j’s head/tail[c - 1] hold the de-interleaved components of composite stream j. See StreamGroup for why the component count is a separate const generic, and Register::load_deinterleaved_grouped for the register-level strategy. Read more
Source§

unsafe fn store_interleaved_grouped<const M: usize, const TAIL: usize>( ptr: *mut Self::Element, values: [StreamGroup<Self, TAIL>; M], )

Interleave M StreamGroups and store them as a contiguous array-of-structures - the exact inverse of load_deinterleaved_grouped, with the same lane-wise default and the same override expectations. Read more
Source§

fn lookup(values: &[Self::Element], indices: Self::Unsigned) -> Self

Assemble a vector from a slice of elements and a vector of indices into that slice. If an index is outside the bounds of the given slice, the resulting lane will be the first element of the input slice. Read more
Source§

fn first_element(self) -> Self::Element

Extract lane 0 – the scalar counterpart to single. Read more
Source§

fn last_element(self) -> Self::Element

Extract the last lane (LANES - 1), first_element’s counterpart at the other end. Read more
Source§

fn prefix_mask(n: usize) -> Self::Mask

Construct a mask whose first n lanes are true and the remaining lanes false. Read more
Source§

fn suffix_mask(n: usize) -> Self::Mask

Construct a mask whose last n lanes are true and the remaining lanes false. Read more
Source§

fn compress_n<const N: usize>(values: [Self; N], mask: Self::Mask) -> [Self; N]

Apply one mask’s compress to N vectors. Read more
Source§

fn compress_z_n<const N: usize>( values: [Self; N], mask: Self::Mask, ) -> [Self; N]

Apply one mask’s compress_z to N vectors. See compress_n.
Source§

fn expand_n<const N: usize>(values: [Self; N], mask: Self::Mask) -> [Self; N]

Apply one mask’s expand to N vectors. See compress_n.
Source§

fn expand_z_n<const N: usize>(values: [Self; N], mask: Self::Mask) -> [Self; N]

Apply one mask’s expand_z to N vectors. See compress_n.
Source§

fn cast<INTO>(self) -> INTO
where INTO: CastVector<Self>,

Numeric cast to another vector type, matching the semantics of Rust’s as operator on the underlying scalar elements for in-range, finite inputs. Read more
Source§

fn fast_cast<INTO>(self) -> INTO
where INTO: CastVector<Self>,

Fast numeric cast to another vector type. Read more
Source§

fn into_bits<INTO>(self) -> INTO
where INTO: BitCastVector<Self>,

Reinterpret the bits of this vector as another vector type of the same size and lane count. Read more
Source§

fn saturating_cast<INTO>(self) -> INTO
where INTO: CastVector<Self>,

Cast that saturates (clamps) out-of-range values to the destination element range, rather than wrapping (integers) or producing a backend-defined value (float-to-int) like cast. Read more
Source§

impl<V: HasIsa> HasIsa for Compensated<V>

Source§

const ISA: InstructionSet = V::ISA

The instruction set this backend implements. Read more
Source§

type Native = <V as HasIsa>::Native

The backend this type executes on. Read more
Source§

impl<V: CompensatedFloatVector> Interleave for Compensated<V>

Source§

fn interleave(self, other: Self) -> (Self, Self)

Unpack and interleave elements from two vectors. Read more
Source§

fn deinterleave(self, other: Self) -> (Self, Self)

Pack and deinterleave elements from two vectors. This is the inverse operation of interleave. Read more
Source§

impl<V: ScalarValue> Mul for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Self) -> Self::Output

Performs the * operation. Read more
Source§

impl<V: ScalarValue> Mul<V> for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: V) -> Self

Performs the * operation. Read more
Source§

impl<V: Copy, A, B> MulAddAssignExt<A, B> for Compensated<V>
where Self: MulAddExt<A, B, Output = Self>,

Source§

fn mul_add_assign(&mut self, a: A, b: B)

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub_assign(&mut self, a: A, b: B)

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add_assign(&mut self, a: A, b: B)

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub_assign(&mut self, a: A, b: B)

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde_assign(&mut self, a: A, b: B)

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn mul_sube_assign(&mut self, a: A, b: B)

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

fn nmul_adde_assign(&mut self, a: A, b: B)

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn nmul_sube_assign(&mut self, a: A, b: B)

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

impl<V: CompensatedFloatVector, A, B> MulAddAssignExtMasked<<V as GenericVector>::Mask, A, B> for Compensated<V>
where Compensated<V>: MulAddExt<A, B, Output = Self>,

Source§

fn mul_add_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_add_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_add_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn mul_sub_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn mul_sub_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_add_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_add_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn nmul_sub_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn nmul_sub_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_adde_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_adde_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_assign_c(&mut self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_assign_m(&mut self, src: Self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_assign_z(&mut self, mask: V::Mask, a: A, b: B)

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

impl<V: ScalarValue> MulAddExt for Compensated<V>

Source§

const HAS_NATIVE_FMA: Tribool = tribool::True

Whether the implementation uses native fused-multiply-add instructions, as three-valued logic: True = fused single instructions, False = definitely separate multiply and add, Indeterminate = decided at runtime (e.g. the wasm relaxed-madd canary). Read more
Source§

type Output = Compensated<V>

The result of the fused operation.
Source§

fn mul_add(self, b: Self, c: Self) -> Self

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub(self, b: Self, c: Self) -> Self::Output

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add(self, a: Self, b: Self) -> Self::Output

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub(self, a: Self, b: Self) -> Self::Output

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde(self, a: Self, b: Self) -> Self::Output

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn mul_sube(self, a: Self, b: Self) -> Self::Output

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

fn nmul_adde(self, a: Self, b: Self) -> Self::Output

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn nmul_sube(self, a: Self, b: Self) -> Self::Output

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

impl<V: ScalarValue> MulAddExt<Compensated<V>, V> for Compensated<V>

Source§

const HAS_NATIVE_FMA: Tribool = tribool::True

Whether the implementation uses native fused-multiply-add instructions, as three-valued logic: True = fused single instructions, False = definitely separate multiply and add, Indeterminate = decided at runtime (e.g. the wasm relaxed-madd canary). Read more
Source§

type Output = Compensated<V>

The result of the fused operation.
Source§

fn mul_add(self, a: Self, b: V) -> Self::Output

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub(self, b: Self, c: V) -> Self::Output

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add(self, a: Self, b: V) -> Self::Output

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub(self, a: Self, b: V) -> Self::Output

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde(self, a: Self, b: V) -> Self::Output

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn mul_sube(self, a: Self, b: V) -> Self::Output

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

fn nmul_adde(self, a: Self, b: V) -> Self::Output

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn nmul_sube(self, a: Self, b: V) -> Self::Output

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

impl<V: ScalarValue> MulAddExt<V> for Compensated<V>

Source§

const HAS_NATIVE_FMA: Tribool = tribool::True

Whether the implementation uses native fused-multiply-add instructions, as three-valued logic: True = fused single instructions, False = definitely separate multiply and add, Indeterminate = decided at runtime (e.g. the wasm relaxed-madd canary). Read more
Source§

type Output = Compensated<V>

The result of the fused operation.
Source§

fn mul_add(self, b: V, c: Self) -> Self::Output

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub(self, b: V, c: Self) -> Self::Output

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add(self, a: V, b: Self) -> Self::Output

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub(self, a: V, b: Self) -> Self::Output

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde(self, a: V, b: Self) -> Self::Output

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn mul_sube(self, a: V, b: Self) -> Self::Output

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

fn nmul_adde(self, a: V, b: Self) -> Self::Output

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA.
Source§

fn nmul_sube(self, a: V, b: Self) -> Self::Output

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA.
Source§

impl<V: CompensatedFloatVector, A, B> MulAddExtMasked<<V as GenericVector>::Mask, A, B> for Compensated<V>
where Compensated<V>: MulAddExt<A, B, Output = Self>,

Source§

fn mul_add_c(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_add_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_add_z(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-add operation. Read more
Source§

fn mul_sub_c(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn mul_sub_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn mul_sub_z(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-multiply-subtract operation. Read more
Source§

fn nmul_add_c(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_add_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_add_z(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-add operation. Read more
Source§

fn nmul_sub_c(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn nmul_sub_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn nmul_sub_z(self, mask: V::Mask, a: A, b: B) -> Self

Guaranteed fused-negated-multiply-subtract operation. Read more
Source§

fn mul_adde_c(self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_adde_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_adde_z(self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_c(self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn mul_sube_z(self, mask: V::Mask, a: A, b: B) -> Self

Fused-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_c(self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_adde_z(self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-add operation where possible. May gracefully degrade to separate multiply and add if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_c(self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_m(self, src: Self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

fn nmul_sube_z(self, mask: V::Mask, a: A, b: B) -> Self

Fused-negated-multiply-subtract operation where possible. May gracefully degrade to separate multiply and subtract if the target architecture does not support native FMA. Read more
Source§

impl<V: Copy, T> MulAssign<T> for Compensated<V>
where Self: Mul<T, Output = Self>,

Source§

fn mul_assign(&mut self, rhs: T)

Performs the *= operation. Read more
Source§

impl<V: CompensatedFloatVector, Rhs> MulAssignMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Mul<Rhs, Output = Self>,

Source§

fn mul_assign_c(&mut self, mask: V::Mask, rhs: Rhs)

Computes MulAssign with rhs where mask is true.
Source§

fn mul_assign_m(&mut self, src: Self, mask: V::Mask, rhs: Rhs)

Merges MulAssign with src using mask, assigning src where mask is false.
Source§

fn mul_assign_z(&mut self, mask: V::Mask, rhs: Rhs)

Computes MulAssign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector, Rhs> MulMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Mul<Rhs, Output = Self>,

Source§

fn mul_c(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Mul with rhs where mask is true.
Source§

fn mul_m(self, src: Self, mask: V::Mask, rhs: Rhs) -> Self

Merges Mul with src using mask, returning src where mask is false.
Source§

fn mul_z(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Mul masked (zeroed where mask is false).
Source§

impl<V: ScalarValue> Neg for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the - operator.
Source§

fn neg(self) -> Self::Output

Performs the unary - operation. Read more
Source§

impl<V: CompensatedFloatVector> NegMasked<<V as GenericVector>::Mask> for Compensated<V>

Source§

fn neg_c(self, mask: V::Mask) -> Self

Computes Neg where mask is true, does nothing where false.
Source§

fn neg_m(self, src: Self, mask: V::Mask) -> Self

Merges Neg with src using mask, returning src where mask is false.
Source§

fn neg_z(self, mask: V::Mask) -> Self

Computes Neg masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector> NewVector<Compensated<<V as GenericVector>::Element>, <V as GenericVector>::Lanes> for Compensated<V>

Source§

type New<T: NewConst<Compensated<V::Element>, V::Lanes>> = CompensatedNewImpl

For a given array carrier T, the type exposing the constructed vector constant via VectorValue.
Source§

impl<V: CompensatedFloatVector> NumericVector for Compensated<V>

Source§

fn sort_by<O: SortOrder>(self) -> Self

Lane sorts are keyed on the lexicographic (value, error) order, which is exactly cmp_lt here, so the key IS the comparison and ties are deterministic. Each compare-exchange derives one routing mask from it and moves both components through the same permutation and select (thermite::sort::sort_lanes_by_key).

Source§

const ZERO: Self

A vector of the value “0” in the element type.
Source§

const ONE: Self

A vector of the value “1” in the element type.
Source§

const TWO: Self

A vector of the value “2” in the element type.
Source§

const MIN: Self

A vector of the minimum value the element type of this vector can represent.
Source§

const MAX: Self

A vector of the maximum value the element type of this vector can represent.
Source§

fn to_signed_integer(self) -> Self::Signed

Convert each lane to the companion signed integer type, with as semantics - round toward zero, saturating at the bounds, NaN to zero. Read more
Source§

fn from_signed_integer(v: Self::Signed) -> Self

Convert each lane from the companion signed integer type, with as semantics. Read more
Source§

fn to_unsigned_integer(self) -> Self::Unsigned

Convert each lane to the companion unsigned integer type, with as semantics. See to_signed_integer.
Source§

fn from_unsigned_integer(v: Self::Unsigned) -> Self

Convert each lane from the companion unsigned integer type, with as semantics. See from_signed_integer.
Source§

fn bitonic_clean_by<O: SortOrder>(self) -> Self

Sort the lanes of a bitonic vector in O order - one that rises then falls, or a rotation of one. Read more
Source§

fn is_zero(self) -> Self::Mask

For each element in the vector, return a mask indicating whether that element is zero.
Source§

fn is_all_zero(self) -> bool

Returns true if all elements in the vector are zero, false otherwise. Read more
Source§

fn min(self, other: Self) -> Self

Return the minimum of two vectors, element-wise.
Source§

fn max(self, other: Self) -> Self

Return the maximum of two vectors, element-wise.
Source§

fn clamp(self, min: Self, max: Self) -> Self

Clamps the elements of the vector between the given minimum and maximum values.
Source§

fn min_element(self) -> Self::Element

Returns the minimum value in the vector. Read more
Source§

fn max_element(self) -> Self::Element

Returns the maximum value in the vector. Read more
Source§

fn sum_elements(self) -> Self::Element

Returns the sum of all elements in the vector. Read more
Source§

fn prod_elements(self) -> Self::Element

Returns the product of all elements in the vector. Read more
Source§

fn prefix_sum(self) -> Self

Inclusive forward prefix sum (“running total”): out[i] = self[0] + .. + self[i]. Read more
Source§

fn reverse_prefix_sum(self) -> Self

Inclusive reverse (suffix) sum: out[i] = self[i] + .. + self[LANES-1].
Source§

fn prefix_min(self) -> Self

Inclusive forward prefix minimum: out[i] = min(self[0], .., self[i]). Read more
Source§

fn prefix_max(self) -> Self

Inclusive forward prefix maximum: out[i] = max(self[0], .., self[i]). Read more
Source§

fn reverse_prefix_min(self) -> Self

Inclusive reverse (suffix) minimum: out[i] = min(self[i], .., self[LANES-1]). Read more
Source§

fn reverse_prefix_max(self) -> Self

Inclusive reverse (suffix) maximum: out[i] = max(self[i], .., self[LANES-1]). Read more
Source§

fn offset() -> Self

Returns a vector whose every lane equals LANES, converted into the element type. Read more
Source§

fn indexed() -> Self

Returns a vector where each lane holds its own index, cast to the element type: [0, 1, 2, ..., LANES-1]. Read more
Source§

fn min_c(self, mask: Self::Mask, rhs: Self) -> Self

Return the minimum of two vectors, element-wise. Computes min when mask is true, returns self where false.
Source§

fn min_m(self, src: Self, mask: Self::Mask, rhs: Self) -> Self

Return the minimum of two vectors, element-wise. Merges min with src using mask.
Source§

fn min_z(self, mask: Self::Mask, rhs: Self) -> Self

Return the minimum of two vectors, element-wise. Computes min masked (zeroed where mask is false).
Source§

fn max_c(self, mask: Self::Mask, rhs: Self) -> Self

Return the maximum of two vectors, element-wise. Computes max when mask is true, returns self where false.
Source§

fn max_m(self, src: Self, mask: Self::Mask, rhs: Self) -> Self

Return the maximum of two vectors, element-wise. Merges max with src using mask.
Source§

fn max_z(self, mask: Self::Mask, rhs: Self) -> Self

Return the maximum of two vectors, element-wise. Computes max masked (zeroed where mask is false).
Source§

fn scale(self, factor: Self::Element) -> Self

Scales each element in the vector by the given factor. Read more
Source§

fn scale_c(self, mask: Self::Mask, factor: Self::Element) -> Self

Scales each element in the vector by the given factor. Read more
Source§

fn scale_m(self, src: Self, mask: Self::Mask, factor: Self::Element) -> Self

Scales each element in the vector by the given factor. Read more
Source§

fn scale_z(self, mask: Self::Mask, factor: Self::Element) -> Self

Scales each element in the vector by the given factor. Read more
Source§

fn pairwise_sum(lo: Self, hi: Self) -> Self

Sums adjacent lane pairs from lo and hi, returning a vector of the same width. Read more
Source§

fn relaxed_pairwise_sum(lo: Self, hi: Self) -> Self

Like pairwise_sum, but may return a relaxed (implementation-defined) lane ordering for performance. Treat this as if randomly shuffling the result of pairwise_sum, with better performance than pairwise_sum. Read more
Source§

fn min_max_element(self) -> (Self::Element, Self::Element)

Returns both the minimum and maximum values in the vector simultaneously. Read more
Source§

fn arg_minmax(self) -> (usize, usize)

Returns the indices of the minimum and maximum elements in the vector, respectively.
Source§

fn fast_to_signed_integer(self) -> Self::Signed

Like to_signed_integer, but may relax IEEE corner cases (out-of-range and NaN inputs) for speed. Defaults to the exact form.
Source§

fn fast_to_unsigned_integer(self) -> Self::Unsigned

Like to_unsigned_integer, but may relax IEEE corner cases. Defaults to the exact form.
Source§

fn sort(self) -> Self

Sort the lanes ascending. Shorthand for sort_by::<Ascending>.
Source§

fn bitonic_clean(self) -> Self

Sort the lanes of a bitonic vector ascending. Shorthand for bitonic_clean_by::<Ascending>.
Source§

impl<V: PartialEq> PartialEq for Compensated<V>

Source§

fn eq(&self, other: &Compensated<V>) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<V: PartialOrd> PartialOrd for Compensated<V>

Source§

fn partial_cmp(&self, other: &Compensated<V>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<V: CompensatedFloatVector> PartialOrdVector for Compensated<V>

Source§

fn cmp_eq(self, other: Self) -> Self::Mask

Lane-wise self == other.
Source§

fn cmp_ne(self, other: Self) -> Self::Mask

Lane-wise self != other.
Source§

fn cmp_lt(self, other: Self) -> Self::Mask

Lane-wise self < other.
Source§

fn cmp_gt(self, other: Self) -> Self::Mask

Lane-wise self > other.
Source§

fn cmp_le(self, other: Self) -> Self::Mask

Lane-wise self <= other.
Source§

fn cmp_ge(self, other: Self) -> Self::Mask

Lane-wise self >= other.
Source§

fn group_by_value(self, valid: Self::Mask) -> ValueGroups<Self>

Partition the lanes selected by valid into groups of equal value. Read more
Source§

impl<V: ScalarValue> Product for Compensated<V>

Source§

fn product<I: Iterator<Item = Self>>(iter: I) -> Self

Takes an iterator and generates Self from the elements by multiplying the items.
Source§

impl<V: ScalarValue> Rem for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: Self) -> Self

Performs the % operation. Read more
Source§

impl<V: ScalarValue> Rem<V> for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: V) -> Self

Performs the % operation. Read more
Source§

impl<V: Copy, T> RemAssign<T> for Compensated<V>
where Self: Rem<T, Output = Self>,

Source§

fn rem_assign(&mut self, rhs: T)

Performs the %= operation. Read more
Source§

impl<V: CompensatedFloatVector, Rhs> RemAssignMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Rem<Rhs, Output = Self>,

Source§

fn rem_assign_c(&mut self, mask: V::Mask, rhs: Rhs)

Computes RemAssign with rhs where mask is true.
Source§

fn rem_assign_m(&mut self, src: Self, mask: V::Mask, rhs: Rhs)

Merges RemAssign with src using mask, assigning src where mask is false.
Source§

fn rem_assign_z(&mut self, mask: V::Mask, rhs: Rhs)

Computes RemAssign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector, Rhs> RemMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Rem<Rhs, Output = Self>,

Source§

fn rem_c(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Rem with rhs where mask is true.
Source§

fn rem_m(self, src: Self, mask: V::Mask, rhs: Rhs) -> Self

Merges Rem with src using mask, returning src where mask is false.
Source§

fn rem_z(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Rem masked (zeroed where mask is false).
Source§

impl<E: ScalarValue + SignedElement> SignedElement for Compensated<E>

Source§

fn abs(self) -> Self

Source§

fn signum(self) -> Self

Source§

impl<V: CompensatedFloatVector> SignedVector for Compensated<V>

Source§

const NEG_ONE: Self

A vector of the value “-1” in the element type.
Source§

const MIN_POSITIVE: Self

A vector of the smallest positive (non-zero) value in the element type.
Source§

fn abs(self) -> Self

Take the absolute value of the vector, element-wise.
Source§

fn signum(self) -> Self

For each element in the vector, return a new vector where each element is either -1 or +1 depending on the sign of the element. Read more
Source§

fn is_positive(self) -> Self::Mask

For each element in the vector, return a mask indicating whether that element is negative.
Source§

fn is_negative(self) -> Self::Mask

For each element in the vector, return a mask indicating whether that element is positive.
Source§

fn select_negative(self, if_neg: Self, if_pos: Self) -> Self

Based on if self is negative, select between if_neg and if_pos.
Source§

fn copysign(self, sign: Self) -> Self

For each element in the vector, set the sign of that element to the sign of the corresponding element in the other vector.
Source§

fn abs_c(self, mask: Self::Mask) -> Self

Take the absolute value of the vector, element-wise. Computes abs when mask is true, returns self where false.
Source§

fn abs_m(self, src: Self, mask: Self::Mask) -> Self

Take the absolute value of the vector, element-wise. Merges abs with src using mask.
Source§

fn abs_z(self, mask: Self::Mask) -> Self

Take the absolute value of the vector, element-wise. Computes abs masked (zeroed where mask is false).
Source§

fn copysign_c(self, mask: Self::Mask, sign: Self) -> Self

For each element in the vector, set the sign of that element to the sign of the corresponding element in the other vector. Computes copysign when mask is true, returns self where false.
Source§

fn copysign_m(self, src: Self, mask: Self::Mask, sign: Self) -> Self

For each element in the vector, set the sign of that element to the sign of the corresponding element in the other vector. Merges copysign with src using mask.
Source§

fn copysign_z(self, mask: Self::Mask, sign: Self) -> Self

For each element in the vector, set the sign of that element to the sign of the corresponding element in the other vector. Computes copysign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector> SortKey<Compensated<V>> for Compensated<V>

The lane-sort key: strictly-before under the lexicographic (value, error) order, i.e. cmp_lt. See thermite::sort::SortKey for why this is a static trait method and not a closure.

Source§

fn key_lt(a: Self, b: Self) -> V::Mask

Which lanes of a sort strictly before those of b, by the key.
Source§

impl<V> SpecializedCoreMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

fn inverse_sqrt<P: Policy>(self) -> Self

Source§

fn poly_n_primal<P, N>(self, coeffs: &GenericArray<Self::Primal, N>) -> Self
where P: Policy, N: ArrayLength,

Backing definition of CoreMath::poly_n_primal. Read more
Source§

fn poly_rev_n_primal<P, N>(self, coeffs: &GenericArray<Self::Primal, N>) -> Self
where P: Policy, N: ArrayLength,

Backing definition of CoreMath::poly_rev_n_primal. Read more
Source§

fn poly_primal<P>(self, coeffs: &[Self::Primal]) -> Self
where P: Policy,

Backing definition of CoreMath::poly_primal. Read more
Source§

fn poly_rev_primal<P>(self, coeffs: &[Self::Primal]) -> Self
where P: Policy,

Backing definition of CoreMath::poly_rev_primal. Read more
Source§

fn mul_add_primal<P>(self, m: Self, a: Self::Primal) -> Self
where P: Policy,

One Horner step against a primal addend: self * m + a. Read more
Source§

fn nmul_add_primal<P>(self, m: Self, a: Self::Primal) -> Self
where P: Policy,

-(self * m) + a, the negated twin of mul_add_primal. Read more
Source§

fn difference_of_products<P>(self, b: Self, c: Self, d: Self) -> Self
where P: Policy,

The naive form, the fallback for composite arithmetics only. Read more
Source§

fn sum_of_products<P>(self, b: Self, c: Self, d: Self) -> Self
where P: Policy,

The naive form, the fallback for composite arithmetics only. See difference_of_products.
Source§

fn poly<P>(self, coeffs: &[E]) -> Self
where P: Policy,

Source§

fn poly_rev<P>(self, coeffs: &[E]) -> Self
where P: Policy,

Source§

fn poly_n<P, const N: usize>(self, coeffs: &[E; N]) -> Self
where P: Policy,

Source§

fn poly_rev_n<P, const N: usize>(self, coeffs: &[E; N]) -> Self
where P: Policy,

Source§

fn poly_rational_n<P, const N: usize, const D: usize>( self, numerator: &[E; N], denominator: &[E; D], ) -> Self
where P: Policy,

Source§

fn approx_reciprocal<P>(self) -> Self
where P: Policy,

Source§

fn approx_div<P>(self, rhs: Self) -> Self
where P: Policy,

Source§

fn approx_div_sqrt<P>(self, denom: Self) -> Self
where P: Policy,

$a/\sqrt{b}$, spelled a.approx_div_sqrt(b), as one kernel rather than a divide bolted onto a square root. Read more
Source§

fn inv_sum_inv_direct<P, const N: usize>(values: [Self; N], numer: Self) -> Self
where P: Policy,

numer / sum(1/x_i) the direct way, backing both harmonic_mean and inv_sum_inv, which differ only in whether the numerator is N or 1. Read more
Source§

fn harmonic_mean_n<P, const N: usize>(values: [Self; N]) -> Self
where P: Policy,

Source§

fn inv_sum_inv_n<P, const N: usize>(values: [Self; N]) -> Self
where P: Policy,

Source§

fn inv_sum_inv<P>(values: &[Self]) -> Self
where P: Policy,

$1/\sum_i 1/x_i$ over a runtime-length slice. Read more
Source§

fn harmonic_mean<P>(values: &[Self]) -> Self
where P: Policy,

$N/\sum_i 1/x_i$ over a runtime-length slice. Read more
Source§

fn reciprocal_adde<P>(self, a: Self) -> Self
where P: Policy,

Source§

fn powi<P>(self, e: i32) -> Self
where P: Policy,

Source§

fn powic<P, const N: i32>(self) -> Self
where P: Policy,

Source§

fn powiv<P>(self, e: Self::Signed) -> Self
where P: Policy,

Source§

impl<V> SpecializedPrimalMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

impl<V> SpecializedRealMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

fn atan2<P: Policy>(self, x: Self) -> Self

Source§

fn tolerance<P>() -> Self
where P: Policy,

Source§

fn to_degrees<P>(self) -> Self
where P: Policy,

Source§

fn entr<P>(self) -> Self
where P: Policy,

-x ln x, 0 at zero, -inf below it. The zero case rides the shared guard, since ln 0 is the same 0 * -inf that xlogy exists to absorb. Only the negative branch is specific to this one.
Source§

fn ln_ratio<P>(x: Self, y: Self) -> Self
where P: Policy,

ln(x/y) for positive x and y, accurate near x = y where the plain ratio is not. The shared core of rel_entr and kl_div. Read more
Source§

fn rel_entr<P>(self, y: Self) -> Self
where P: Policy,

x ln(x/y), the Kullback-Leibler summand, extended by 0 at x = 0, y >= 0 and +inf everywhere else in the plane.
Source§

fn kl_div<P>(self, y: Self) -> Self
where P: Policy,

rel_entr plus the Bregman tail -x + y, which is what makes this non-negative for unnormalized arguments. Note the x = 0 case is y, not 0: the tail survives when the log term vanishes. Read more
Source§

fn to_radians<P>(self) -> Self
where P: Policy,

Source§

fn wrap_angle<P>(self) -> Self
where P: Policy,

Source§

fn angle_diff<P>(self, other: Self) -> Self
where P: Policy,

Source§

fn step<P>(self, t: Self) -> Self
where P: Policy,

Source§

fn lerp<P>(self, a: Self, b: Self) -> Self
where P: Policy,

Source§

fn rescale<P>( self, in_min: Self, in_max: Self, out_min: Self, out_max: Self, ) -> Self
where P: Policy,

Source§

fn logaddexp<P>(self, other: Self) -> Self
where P: Policy,

Source§

fn logmean<P>(self, other: Self) -> Self
where P: Policy,

Source§

fn logsumexp<P>(values: &[Self]) -> Self
where P: Policy,

Source§

fn logsumexp_n<P, const N: usize>(values: [Self; N]) -> Self
where P: Policy,

Source§

fn logsubexp<P>(self, other: Self) -> Self
where P: Policy,

Source§

fn smoothstep<P, const N: usize>(self, edges: Option<(Self, Self)>) -> Self
where P: Policy,

Source§

fn smoothstep_derivative<P, const N: usize>( self, edges: Option<(Self, Self)>, ) -> Self
where P: Policy,

Source§

fn inverse_smoothstep<P, const N: usize>( y: Self, edges: Option<(Self, Self)>, ) -> Self
where P: Policy,

Source§

fn smooth_interpolator<P>(x: Self, edges: Option<(Self, Self)>, k: Self) -> Self
where P: Policy,

Source§

fn smooth_interpolator_inverse<P>( y: Self, edges: Option<(Self, Self)>, k: Self, ) -> Self
where P: Policy,

Source§

impl<V> SpecializedRealPrimalMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Available on crate feature special only.
Source§

fn langevin_d<P: Policy>(self) -> (Self, Self)

L(x) and L'(x). The derivative falls out of the value’s own intermediates on both branches (see generic::langevin), so there is no default here that would recompute it.
Source§

fn spherical_harmonics_d_with<P, const L: usize, const N: usize>( table: &ShTable<Self, N>, x: Self, y: Self, z: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], ddz: &mut [Self; N], )
where P: Policy,

spherical_harmonics_with plus the ambient Cartesian gradients, from a prebuilt table.
Source§

fn spherical_harmonics_d<P, const L: usize, const N: usize, const CS: bool>( x: Self, y: Self, z: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], ddz: &mut [Self; N], )
where P: Policy,

spherical_harmonics plus the ambient Cartesian gradient of every harmonic. See sh_d_impl for the gradient semantics.
Source§

fn zernike_basis_d<P, const L: usize, const NORM: u8, const N: usize>( x: Self, y: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], )
where P: Policy,

zernike_basis plus the Cartesian gradient of every mode. See zernike_basis_d_impl for the algorithm.
Source§

fn softplus_d<P>(self, k: Self, rcp_k: Self) -> (Self, Self)
where P: Policy,

Source§

fn gelu_d<P>(self, alpha: Self) -> (Self, Self)
where P: Policy,

Source§

fn swish_d<P>(self, beta: Self) -> (Self, Self)
where P: Policy,

Source§

fn algebraic_sigmoid_d_n<P, const N: usize>(self) -> (Self, Self)
where P: Policy,

Source§

fn algebraic_sigmoid_d<P>(self, n: u32) -> (Self, Self)
where P: Policy,

The runtime twin of algebraic_sigmoid_d_n.
Source§

fn algebraic_swish_d<P>(self) -> (Self, Self)
where P: Policy,

Source§

impl<V> SpecializedRealSpecialMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Available on crate feature special only.
Source§

fn erfinv<P: Policy>(self) -> Self

Source§

fn probit<P: Policy>(self) -> Self

Source§

fn lgamma_r<P: Policy>(self) -> (Self, Self)

Source§

fn langevin<P: Policy>(self) -> Self

Source§

fn langevin_1m<P: Policy>(self) -> Self

Source§

fn inv_langevin<P: Policy>(self) -> Self

Source§

fn inv_langevin_1m<P: Policy>(self) -> Self

Source§

fn ndtr<P>(self) -> Self
where P: Policy,

erfc(-x/sqrt 2)/2, the standard normal CDF.
Source§

fn log_ndtr<P>(self) -> Self
where P: Policy,

ln(ndtr(x)), finite wherever x is: ln(erfc) in the moderate region, erfcx with -x^2/2 kept in the log domain in the tail, ln_1p of the complement on the right. See generic::ndtr. Element types without a Weideman table (Compensated) inherit their direct erfcx’s range, about |x| < 37.
Source§

fn logerfc<P>(self) -> Self
where P: Policy,

ln(erfc(x)) on the same construction as log_ndtr, with the tail on the right and ln_1p(+-erf(|x|)) on the bounded side.
Source§

fn log_ndtr_with_deriv<P>(self) -> (Self, Self)
where P: Policy,

(ln ndtr(x), phi(x)/ndtr(x)), the value with the inverse Mills ratio, which is its derivative. What inv_log_ndtr’s Newton and Dual both need.
Source§

fn inv_log_ndtr<P>(self) -> Self
where P: Policy,

The x with ln ndtr(x) = y. Newton on log_ndtr.
Source§

fn inv_digamma<P>(self) -> Self
where P: Policy,

The x > 0 with digamma(x) = y. Newton on digamma with trigamma, and the Stirling fixed point above y = 6.
Source§

fn wright_omega<P>(self) -> Self
where P: Policy,

The w > 0 with w + ln w = x. Newton, and the Lagrange series below x = -7.
Source§

fn fresnel<P>(self) -> (Self, Self)
where P: Policy,

(S(x), C(x)), the Fresnel integrals. See generic::fresnel. Read more
Source§

fn sici<P>(self) -> (Self, Self)
where P: Policy,

(Si(x), Ci(x)), the trigonometric integrals. See generic::sici. Read more
Source§

fn fresnel_c<P>(self) -> Self
where P: Policy,

C(x) alone. Unlike the Airy singles this is genuinely the pair with one half dead: the two share the argument reduction, the phase and both auxiliaries, so only one Chebyshev series and one reconstruction fall out. They are pure, so they do fall out.
Source§

fn fresnel_s<P>(self) -> Self
where P: Policy,

S(x) alone. See fresnel_c.
Source§

fn sinint<P>(self) -> Self
where P: Policy,

Si(x) alone. See fresnel_c for what is and is not saved.
Source§

fn cosint<P>(self) -> Self
where P: Policy,

Ci(x) alone. See fresnel_c.
Source§

fn bessel_i_ratio<P>(self, _nu: Self) -> Self
where P: Policy,

I_nu(x) / I_{nu-1}(x), the vMF mean resultant length. See generic::bessel_ratio. Read more
Source§

fn inv_bessel_i_ratio<P>(self, _nu: Self) -> Self
where P: Policy,

The kappa with I_nu(kappa) / I_{nu-1}(kappa) = r. Newton on the ratio. Same arrangement as bessel_i_ratio.
Source§

fn bessel_i_ratio_1m<P>(self, _nu: Self) -> Self
where P: Policy,

1 - I_nu(x) / I_{nu-1}(x), accurate where the ratio is within an ulp of 1.
Source§

fn inv_bessel_i_ratio_1m<P>(self, _nu: Self) -> Self
where P: Policy,

The kappa with 1 - I_nu(kappa) / I_{nu-1}(kappa) = t, the complement form.
Source§

fn bessel_ratio<P, F>(self, nu: Self) -> Self

bessel::ratio::<F>(nu): see BesselRatioFamily.
Source§

fn inv_bessel_ratio<P, F>(self, nu: Self) -> Self

inv_bessel::ratio::<F>(r).
Source§

fn bessel_ratio_1m<P, F>(self, nu: Self) -> Self

bessel_ratio_1m::<F>(nu).
Source§

fn inv_bessel_ratio_1m<P, F>(self, nu: Self) -> Self

inv_bessel_ratio_1m::<F>(t).
Source§

fn gauss_legendre<P>(self, n: u32) -> (Self, Self)
where P: Policy,

(x_k, w_k) of the n-point Gauss-Legendre rule, the index k per lane. See generic::quadrature.
Source§

fn gauss_hermite<P>(self, n: u32) -> (Self, Self)
where P: Policy,

(x_k, w_k) of the n-point Gauss-Hermite rule, the index k per lane.
Source§

fn gauss_laguerre<P>(self, alpha: Self, n: u32) -> (Self, Self)
where P: Policy,

(x_k, w_k) of the n-point Gauss-Laguerre rule with weight x^alpha e^{-x}, the index k and alpha per lane.
Source§

fn agm<P>(a: Self, b: Self) -> Self
where P: Policy,

AGM(a, b), sharing its recurrence with the complete elliptic integrals.
Source§

fn pochhammer<P>(z: Self, m: Self) -> Self
where P: Policy,

zeta(s) - 1, the primitive of the pair: the Euler-Maclaurin sum’s leading term is the 1, so omitting it is exact where subtracting it afterwards is not. Read more
Source§

fn jacobi_elliptic<P>(u: Self, k: Self) -> (Self, Self, Self)
where P: Policy,

(sn, cn, dn) by the arithmetic-only descending Landen transformation. Read more
Source§

fn boxcox<P>(self, lambda: Self) -> Self
where P: Policy,

(x^lambda - 1)/lambda, ln x at lambda = 0. Read more
Source§

fn boxcox_1p<P>(self, lambda: Self) -> Self
where P: Policy,

((1 + x)^lambda - 1)/lambda, ln(1 + x) at lambda = 0. Read more
Source§

fn inv_boxcox<P>(self, lambda: Self) -> Self
where P: Policy,

(lambda*y + 1)^(1/lambda), e^y at lambda = 0. The inverse of boxcox. Read more
Source§

fn inv_boxcox_1p<P>(self, lambda: Self) -> Self
where P: Policy,

(lambda*y + 1)^(1/lambda) - 1, e^y - 1 at lambda = 0. The inverse of boxcox_1p. Read more
Source§

fn yeo_johnson<P>(self, lambda: Self) -> Self
where P: Policy,

The Yeo-Johnson transform of y = self with parameter lambda. Read more
Source§

fn inv_yeo_johnson<P>(self, lambda: Self) -> Self
where P: Policy,

The inverse Yeo-Johnson transform. The same sign fold as yeo_johnson, over inv_boxcox_1p. Read more
Source§

fn gelu<P>(self, alpha: Self) -> Self
where P: Policy,

Source§

fn swish<P>(self, beta: Self) -> Self
where P: Policy,

Source§

fn algebraic_sigmoid_n<P, const N: usize>(self) -> Self
where P: Policy,

Source§

fn algebraic_sigmoid<P>(self, n: u32) -> Self
where P: Policy,

The runtime twin of algebraic_sigmoid_n, same arithmetic.
Source§

fn algebraic_swish<P>(self) -> Self
where P: Policy,

Source§

fn gaussian_integral<P>(x0: Self, x1: Self, a: Self, c: Self) -> Self
where P: Policy,

Source§

fn spherical_harmonics_table<P, const L: usize, const N: usize, const CS: bool>( table: &mut ShTable<Self::Primal, N>, )
where P: Policy,

Fills a runtime coefficient table for degree L and phase CS. See sh_impl for the conventions, layout, and algorithm. Read more
Source§

fn spherical_harmonics_with<P, const L: usize, const N: usize>( table: &ShTable<Self::Primal, N>, x: Self, y: Self, z: Self, out: &mut [Self; N], )
where P: Policy,

Evaluates all harmonics through degree L from a table built by spherical_harmonics_table. Read more
Source§

fn spherical_harmonics<P, const L: usize, const N: usize, const CS: bool>( x: Self, y: Self, z: Self, out: &mut [Self; N], )
where P: Policy,

The one-shot form: build a table and evaluate it. Read more
Source§

impl<V> SpecializedSpatialMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

fn l2_norm_squared<P: Policy>(self) -> Self

Source§

fn l2_norm<P: Policy>(self) -> Self

Source§

fn l1_norm<P: Policy>(self) -> Self

Source§

fn hypot_n<P, const N: usize>(values: [Self; N]) -> Self
where P: Policy,

Source§

fn hypot<P>(self, y: Self) -> Self
where P: Policy,

The two-argument spelling, and nothing more than a spelling. Read more
Source§

fn inv_hypot_n<P, const N: usize>(values: [Self; N]) -> Self
where P: Policy,

Source§

fn hypot_s<P>(values: &[Self]) -> Self
where P: Policy,

Source§

fn inv_hypot<P>(values: &[Self]) -> Self
where P: Policy,

Source§

impl<V> SpecializedSpecialMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Available on crate feature special only.
Source§

fn polygamma<P: Policy>(self, n: u32) -> Self

n = 0 and n = 1 reach the tuned double-double digamma/trigamma. n >= 2 returns NaN: no double-double algorithm exists for the higher orders yet, and silently routing through an f64-precision path would put 53 good bits in a 106-bit container, the same reason Compensated refuses the shared Lanczos tables. NaN over quiet precision loss, like the real kernel’s unimplemented regions.

Source§

type ExpIntDetails = Compensated<V>

Per-arithmetic details of the expint kernel. Almost always Self, with an empty ExpIntDetails impl taking every default.
Source§

fn erf<P: Policy>(self) -> Self

Source§

fn erfc<P: Policy>(self) -> Self

Source§

fn tgamma<P: Policy>(self) -> Self

Source§

fn beta<P: Policy>(a: Self, b: Self) -> Self

Source§

fn lambert_w<P: Policy>(self) -> (Self, Self)

Source§

fn lgamma<P: Policy>(self) -> Self

Source§

fn digamma<P: Policy>(self) -> Self

Source§

fn trigamma<P: Policy>(self) -> Self

The trigamma function psi_1(x) = d/dx psi(x), the second derivative of ln Gamma. Read more
Source§

fn exp_two_sum(a: Self, b: Self) -> (Self, Self)

TwoSum for exponent assembly: (a + b, the rounding it discarded). Internal to this trait; it is a lowering detail of the Poisson exponent. Read more
Source§

const LAGUERRE_PRODUCT_SEED_CAP: i32 = 0

Largest integer weight for which laguerre_function_i seeds by the direct product x^{alpha/2} / sqrt(alpha!) (a scalar factorial, powi, at most one sqrt) instead of the general exp(alpha/2 ln x - lgamma(alpha+1)/2). 0 disables it. Read more
Source§

fn erfcx<P>(self) -> Self
where P: Policy,

$e^{x^2}\operatorname{erfc}(x)$, which does not underflow where erfc does. Read more
Source§

fn expint_n<P, const N: usize>(self) -> Self
where P: Policy,

Computes the exponential integral E_N(x) for integer order N.
Source§

fn expint_primal_n<P, const N: usize>(self) -> (Self, Self)
where P: Policy,

Computes $E_N(x)$ together with the adjacent lower order $E_{N-1}(x)$. Read more
Source§

fn expint<P>(self, n: u32) -> Self
where P: Policy,

The runtime-order twin of expint_n.
Source§

fn expint_primal<P>(self, n: u32) -> (Self, Self)
where P: Policy,

The runtime-order twin of expint_primal_n: the same E_1 core, the same recurrence with the order as a value.
Source§

fn logistic_sigmoid<P>(self) -> Self
where P: Policy,

Source§

fn softplus<P>(self, k: Self, rcp_k: Self) -> Self
where P: Policy,

Source§

fn zetac<P>(self) -> Self
where P: Policy,

Compensated keeps the default: the Euler-Maclaurin coefficients are tabulated to f64, so a double-double built from them would carry 53 real bits and noise, the same reason it has no GammaPrimalTables impl. Dual overrides it through zeta_with_deriv.
Source§

fn zeta<P>(self) -> Self
where P: Policy,

zeta(s), as 1 + zetac(s). Defaulted for the same reason as zetac.
Source§

fn polylog<P>( self, order: PolylogOrder<E, <Self::Signed as GenericVector>::Element>, ) -> Self
where P: Policy,

Li_s(z) at a scalar order. Defaulted for the same reason as zetac: the coefficient precompute is f64, so a double-double has nothing to reach for. Dual overrides it through the order-lowering identity Li_s' = Li_{s-1}/z.
Source§

fn zeta_with_deriv<P, const ZETAC: bool>(self) -> (Self, Self)
where P: Policy,

(zeta(s), zeta'(s)), or (zeta(s) - 1, zeta'(s)) when ZETAC is set: the two functions differ by a constant, so one derivative serves both. Read more
Source§

fn bessel_i<P, const N: i32>(self) -> Self
where P: Policy,

I_N(x), or e^{-|x|} I_N(x) when SCALED: the modified Bessel function of the first kind at compile-time integer order. Read more
Source§

fn bessel_i_scaled<P, const N: i32>(self) -> Self
where P: Policy,

e^{-|x|} I_N(x). Not a wrapper over bessel_i: above the series threshold the coefficient tables are the scaled value, so this form skips the exponential the unscaled one pays for, and stays finite where I_N overflows.
Source§

fn bessel_k<P, const N: i32>(self) -> Self
where P: Policy,

K_N(x), the modified Bessel function of the second kind at compile-time integer order. Defaulted for the same reason as bessel_i.
Source§

fn bessel_k_scaled<P, const N: i32>(self) -> Self
where P: Policy,

e^{x} K_N(x). Not a wrapper: above the series threshold the tables are natively the scaled quantity, so this form skips the exponential the unscaled one pays for, and stays in range where K_N has decayed to zero.
Source§

fn bessel_j<P, const N: i32>(self) -> Self
where P: Policy,

J_N(x), the oscillatory Bessel function of the first kind. Orders 0 and 1 only for now. Higher orders want a recurrence that is not written yet.
Source§

fn bessel_y<P, const N: i32>(self) -> Self
where P: Policy,

Y_N(x), the oscillatory Bessel function of the second kind.
Source§

fn bessel_i_with_deriv<P, const N: i32, const SCALED: bool>( self, ) -> (Self, Self)
where P: Policy,

(I_N(x), d/dx I_N(x)), or the scaled pair when SCALED. Read more
Source§

fn bessel_k_with_deriv<P, const N: i32, const SCALED: bool>( self, ) -> (Self, Self)
where P: Policy,

(K_N(x), d/dx K_N(x)). See bessel_i_with_deriv.
Source§

fn bessel_j_with_deriv<P, const N: i32>(self) -> (Self, Self)
where P: Policy,

(J_N(x), d/dx J_N(x)). See bessel_i_with_deriv.
Source§

fn bessel_y_with_deriv<P, const N: i32>(self) -> (Self, Self)
where P: Policy,

(Y_N(x), d/dx Y_N(x)). See bessel_i_with_deriv.
Source§

fn bessel_iv<P, const SCALED: bool>( self, _order: BesselOrder<Self, Self::Signed>, ) -> Self
where P: Policy,

I_n(x) with a per-lane order. See bessel_i.
Source§

fn bessel_kv<P, const SCALED: bool>( self, _order: BesselOrder<Self, Self::Signed>, ) -> Self
where P: Policy,

K_n(x) with a per-lane order. See bessel_k.
Source§

fn bessel_jv<P>(self, _order: BesselOrder<Self, Self::Signed>) -> Self
where P: Policy,

J_n(x) with a per-lane order. See bessel_j.
Source§

fn bessel_yv<P>(self, _order: BesselOrder<Self, Self::Signed>) -> Self
where P: Policy,

Y_n(x) with a per-lane order. See bessel_y.
Source§

fn sph_bessel_j_n<P, const N: usize>(self) -> Self
where P: Policy,

j_n(x), the spherical Bessel function of the first kind. See sph_bessel_j.
Source§

fn sph_bessel_y_n<P, const N: usize>(self) -> Self
where P: Policy,

y_n(x). See sph_bessel_y.
Source§

fn sph_bessel_i_n<P, const N: usize>(self) -> Self
where P: Policy,

i_n(x). See sph_bessel_i.
Source§

fn sph_bessel_i_scaled_n<P, const N: usize>(self) -> Self
where P: Policy,

e^{-x} i_n(x). See sph_bessel_i_scaled.
Source§

fn sph_bessel_k_n<P, const N: usize>(self) -> Self
where P: Policy,

k_n(x). See sph_bessel_k.
Source§

fn sph_bessel_k_scaled_n<P, const N: usize>(self) -> Self
where P: Policy,

e^{x} k_n(x). See sph_bessel_k_scaled.
Source§

fn sph_bessel_j_with_deriv_n<P, const N: usize>(self) -> (Self, Self)
where P: Policy,

(j_n(x), j_n'(x)), both from one walk. Read more
Source§

fn sph_bessel_y_with_deriv_n<P, const N: usize>(self) -> (Self, Self)
where P: Policy,

(y_n(x), y_n'(x)). See sph_bessel_j_with_deriv.
Source§

fn sph_bessel_i_with_deriv_n<P, const N: usize, const SCALED: bool>( self, ) -> (Self, Self)
where P: Policy,

(i_n(x), i_n'(x)), scaled by e^{-x} when SCALED, in which case the derivative is the scaled function’s own, d/dx(e^{-x} i_n) = e^{-x}(i_n' - i_n).
Source§

fn sph_bessel_k_with_deriv_n<P, const N: usize, const SCALED: bool>( self, ) -> (Self, Self)
where P: Policy,

(k_n(x), k_n'(x)), scaled by e^{x} when SCALED.
Source§

fn sph_bessel_j<P>(self, n: u32) -> Self
where P: Policy,

j_n(x) for a runtime order. See sph_bessel_j.
Source§

fn sph_bessel_y<P>(self, n: u32) -> Self
where P: Policy,

y_n(x) for a runtime order.
Source§

fn sph_bessel_i<P>(self, n: u32) -> Self
where P: Policy,

i_n(x) for a runtime order.
Source§

fn sph_bessel_i_scaled<P>(self, n: u32) -> Self
where P: Policy,

e^{-x} i_n(x) for a runtime order.
Source§

fn sph_bessel_k<P>(self, n: u32) -> Self
where P: Policy,

k_n(x) for a runtime order.
Source§

fn sph_bessel_k_scaled<P>(self, n: u32) -> Self
where P: Policy,

e^{x} k_n(x) for a runtime order.
Source§

fn sph_bessel_j_with_deriv<P>(self, n: u32) -> (Self, Self)
where P: Policy,

(j_n(x), j_n'(x)) for a runtime order. See sph_bessel_j_with_deriv_n.
Source§

fn sph_bessel_y_with_deriv<P>(self, n: u32) -> (Self, Self)
where P: Policy,

(y_n(x), y_n'(x)) for a runtime order.
Source§

fn sph_bessel_i_with_deriv<P, const SCALED: bool>(self, n: u32) -> (Self, Self)
where P: Policy,

(i_n(x), i_n'(x)) for a runtime order, scaled by e^{-x} when SCALED.
Source§

fn sph_bessel_k_with_deriv<P, const SCALED: bool>(self, n: u32) -> (Self, Self)
where P: Policy,

(k_n(x), k_n'(x)) for a runtime order, scaled by e^{x} when SCALED.
Source§

fn bessel_n<P, F, const N: i32>(self) -> Self
where P: Policy, F: BesselFamily,

bessel_n::<F, N>(): see BesselFamily.
Source§

fn bessel<P, F>(self, order: BesselOrder<Self, Self::Signed>) -> Self
where P: Policy, F: BesselFamily,

bessel::<F>(order): see BesselFamily.
Source§

fn sph_bessel_n<P, F, const N: usize>(self) -> Self
where P: Policy, F: BesselFamily,

sph_bessel_n::<F, N>().
Source§

fn sph_bessel<P, F>(self, n: u32) -> Self
where P: Policy, F: BesselFamily,

sph_bessel::<F>(n).
Source§

fn airy<P, W>(self) -> Self
where P: Policy, W: AiryFn,

airy::<W>(): see AiryFn.
Source§

fn airy_all<P, const SCALED: bool>(self) -> (Self, Self, Self, Self)
where P: Policy,

The four Airy values, scaled on the positive axis when SCALED.
Source§

fn bessel_jv_scaled<P>(self, order: BesselOrder<Self, Self::Signed>) -> Self
where P: Policy,

Scaled(J) at runtime order: e^{-|Im z|} J_nu(z), SciPy’s jve. The scale factor is 1 on the real axis, so the default is the unscaled value. Complex overrides.
Source§

fn bessel_yv_scaled<P>(self, order: BesselOrder<Self, Self::Signed>) -> Self
where P: Policy,

Scaled(Y) at runtime order, the Y twin of bessel_jv_scaled.
Source§

fn airy_tuple<P>(self) -> (Self, Self, Self, Self)
where P: Policy,

(Ai, Ai', Bi, Bi'). See airy. Read more
Source§

fn airy_tuple_scaled<P>(self) -> (Self, Self, Self, Self)
where P: Policy,

(Ai, Ai', Bi, Bi') with the exponential factored out on the positive axis. Not a wrapper over airy: it is the form the kernel produces natively, and the unscaled one is the wrapper. See airy with a Scaled marker.
Source§

fn airy_ai<P>(self) -> Self
where P: Policy,

Ai(x) alone: a cheaper evaluation than airy, not a projection of it. See airy_ai.
Source§

fn airy_ai_scaled<P>(self) -> Self
where P: Policy,

e^zeta Ai(x) on the positive axis. See airy_ai_scaled.
Source§

fn airy_bi<P>(self) -> Self
where P: Policy,

Bi(x) alone. See airy_bi.
Source§

fn airy_bi_scaled<P>(self) -> Self
where P: Policy,

e^-zeta Bi(x) on the positive axis. See airy_bi_scaled.
Source§

fn airy_ai_prime<P>(self) -> Self
where P: Policy,

Ai'(x) alone. See airy_ai_prime.
Source§

fn airy_ai_prime_scaled<P>(self) -> Self
where P: Policy,

e^zeta Ai'(x) on the positive axis. See airy_ai_prime_scaled.
Source§

fn airy_bi_prime<P>(self) -> Self
where P: Policy,

Bi'(x) alone. See airy_bi_prime.
Source§

fn airy_bi_prime_scaled<P>(self) -> Self
where P: Policy,

e^-zeta Bi'(x) on the positive axis. See airy_bi_prime_scaled.
Source§

fn hermite_n<P, const N: usize>(x: Self) -> Self
where P: Policy,

Source§

fn hermitev<P>(x: Self, n: Self::Unsigned) -> Self
where P: Policy,

Source§

fn hermite<P>(self, n: u32) -> Self
where P: Policy,

A uniform runtime degree is hermitev with the degree splatted. Nothing cheaper is correct.
Source§

fn hermite_function_n<P, const N: usize>(x: Self) -> Self
where P: Policy,

Source§

fn hermite_function<P>(x: Self, n: u32) -> Self
where P: Policy,

Source§

fn hermite_function_series_n<P, const N: usize>( self, coeffs: &[Self::Element; N], ) -> Self
where P: Policy,

Source§

fn hermite_function_series<P>(self, coeffs: &[Self::Element]) -> Self
where P: Policy,

Source§

fn laguerre_n<P, const N: usize>(x: Self, alpha: Self) -> Self
where P: Policy,

Source§

fn laguerrev<P>(x: Self, alpha: Self, n: Self::Unsigned) -> Self
where P: Policy,

Source§

fn laguerre<P>(self, alpha: Self, n: u32) -> Self
where P: Policy,

A uniform runtime degree is laguerrev with the degree splatted.
Source§

fn laguerre_function_n<P, const N: usize>(x: Self, alpha: Self) -> Self
where P: Policy,

Source§

fn laguerre_function<P>(x: Self, alpha: Self, n: u32) -> Self
where P: Policy,

Source§

fn laguerre_function_i_n<P, const N: usize>(x: Self, alpha: i32) -> Self
where P: Policy,

Source§

fn laguerre_function_i<P>(x: Self, alpha: i32, n: u32) -> Self
where P: Policy,

Source§

fn poisson_pmf<P>(self, lambda: Self) -> Self
where P: Policy,

Source§

fn poisson_log_pmf<P>(self, lambda: Self) -> Self
where P: Policy,

Source§

fn laguerre_function_series_n<P, const N: usize>( self, alpha: Self, coeffs: &[Self::Element; N], ) -> Self
where P: Policy,

Source§

fn laguerre_function_series_i_n<P, const N: usize>( self, alpha: i32, coeffs: &[Self::Element; N], ) -> Self
where P: Policy,

Source§

fn laguerre_function_series<P>( self, alpha: Self, coeffs: &[Self::Element], ) -> Self
where P: Policy,

Source§

fn laguerre_function_series_i<P>( self, alpha: i32, coeffs: &[Self::Element], ) -> Self
where P: Policy,

Source§

fn chebyshev<P, const K: usize>(self, coeffs: &[Self::Element]) -> Self
where P: Policy,

Source§

fn chebyshev_n<P, const K: usize, const N: usize>( self, coeffs: &[Self::Element; N], ) -> Self
where P: Policy,

Source§

fn jacobi<P>(x: Self, alpha: Self, beta: Self, n: u32, m: u32) -> Self
where P: Policy,

Source§

fn gaussian<P>(x: Self, a: Self, c: Self) -> Self
where P: Policy,

Source§

fn lbeta<P>(a: Self, b: Self) -> Self
where P: Policy,

Source§

fn logit<P>(self) -> Self
where P: Policy,

Source§

fn logit_1m<P>(self) -> Self
where P: Policy,

Source§

fn planck<P>(self) -> Self
where P: Policy,

Source§

fn legendre0<P, const N: u32>(x: Self, n: u32) -> Self
where P: Policy,

Source§

fn legendre<P>(x: Self, n: u32, m: u32) -> Self
where P: Policy,

Source§

fn legendre_series_n<P, const N: usize>( self, coeffs: &[Self::Element; N], ) -> Self
where P: Policy,

Source§

fn legendre_series<P>(self, coeffs: &[Self::Element]) -> Self
where P: Policy,

Source§

fn zernike_r<P>(rho: Self, n: u32, m: u32) -> Self
where P: Policy,

Source§

fn zernike<P, const NORM: u8>(rho: Self, theta: Self, n: u32, m: i32) -> Self
where P: Policy,

Source§

fn zernike_basis<P, const L: usize, const NORM: u8, const N: usize>( x: Self, y: Self, out: &mut [Self; N], )
where P: Policy,

Source§

fn phi_n<P, const N: usize>(self) -> Self
where P: Policy,

Source§

fn phi<P>(self, n: u32) -> Self
where P: Policy,

The runtime-order twin of phi_n. The f32/f64 backends override it with a term count worked out from n per call.
Source§

impl<V> SpecializedTranscendentalMath<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

fn sincos_pi<P: Policy>(self) -> (Self, Self)

$(\sin \pi x, \cos \pi x)$, reducing before multiplying by pi.

The inherited default is sin_cos(self * PI), which throws away most of what this type exists for. Forming x * PI rounds the product, so the argument handed to sin_cos already carries an absolute error of about |x| * 2^-106; at x = -1000.5 (an ordinary argument for the gamma reflection) that is three or four digits gone before any trigonometry happens.

Reducing first avoids it entirely. sin(pi(n + r)) = (-1)^n sin(pi r) for integer n, and x - round(x) is exact, so the only rounded product is r * PI with |r| <= 1/2. Same for cosine, with the same sign flip.

Source§

fn atanhc<P: Policy>(self) -> Self

atanh(x)/x, the cardinal form of atanh: same structure as sinc below, with the even series 1 + x^2/3 + x^4/5. Domain [-1, 1], where both ends are +inf.

Source§

fn sinhc<P: Policy>(self) -> Self

sinh(x)/x, the hyperbolic twin of sinc above and structurally identical to it: the series 1 + x^2/6 + x^4/120 adds where sinc subtracts, and the limit at infinity is +inf rather than zero.

Source§

fn ln1m_expnx_ext<P: Policy>(self, _lnx: Self) -> Self

The _ext form exists so a caller who already has ln(x) can hand it to the low-precision approximation instead of paying for it twice. The compensated path never takes that approximation (it evaluates ln(1 - e^-x) exactly), so there is nothing to reuse and the hint is dropped, the same way the f64 kernel (math/specialized/pd.rs) and Complex do.

Source§

fn sin_cos<P: Policy>(self) -> (Self, Self)

Source§

fn sinc<P: Policy>(self) -> Self

Source§

fn sinh_cosh<P: Policy>(self) -> (Self, Self)

Source§

fn sinh<P: Policy>(self) -> Self

Source§

fn cosh<P: Policy>(self) -> Self

Source§

fn tanh<P: Policy>(self) -> Self

Source§

fn asin<P: Policy>(self) -> Self

Source§

fn acos<P: Policy>(self) -> Self

Source§

fn atan<P: Policy>(self) -> Self

Source§

fn asinh<P: Policy>(self) -> Self

Source§

fn acosh<P: Policy>(self) -> Self

Source§

fn atanh<P: Policy>(self) -> Self

Source§

fn exp<P: Policy>(self) -> Self

Source§

fn exph<P: Policy>(self) -> Self

Source§

fn exp2<P: Policy>(self) -> Self

Source§

fn exp10<P: Policy>(self) -> Self

Source§

fn exp_m1<P: Policy>(self) -> Self

Source§

fn exp2_m1<P: Policy>(self) -> Self

Source§

fn exp10_m1<P: Policy>(self) -> Self

Source§

fn powf<P: Policy>(self, e: Self) -> Self

Source§

fn cbrt<P: Policy>(self) -> Self

Source§

fn ln<P: Policy>(self) -> Self

Source§

fn ln_1p<P: Policy>(self) -> Self

Source§

fn log2<P: Policy>(self) -> Self

Source§

fn log10<P: Policy>(self) -> Self

Source§

fn log_n_n<P: Policy, const N: usize>(self) -> Self

Source§

fn log_n<P: Policy>(self, n: u32) -> Self

The runtime twin of log_n_n. This default goes through log. The real f32/f64 vectors override it with the same table lookup the const form uses, so the two agree to the bit there.
Source§

fn sin<P>(self) -> Self
where P: Policy,

Source§

fn cos<P>(self) -> Self
where P: Policy,

Source§

fn tan<P>(self) -> Self
where P: Policy,

Source§

fn sin_pi<P>(self) -> Self
where P: Policy,

Source§

fn cos_pi<P>(self) -> Self
where P: Policy,

Source§

fn tan_pi<P>(self) -> Self
where P: Policy,

Source§

fn sinc_pi<P>(self) -> Self
where P: Policy,

Source§

fn xlog_guarded(x: Self, y: Self, ln_y: Self) -> Self

x * ln_of_y, with x == 0 winning over an infinite log but a NaN y winning over both. Shared by xlogy, xlog1py and entr; the other two members of the family guard on the sign of both arguments instead and cannot use it. Read more
Source§

fn xlogy<P>(self, y: Self) -> Self
where P: Policy,

Source§

fn xlog1py<P>(self, y: Self) -> Self
where P: Policy,

Source§

fn cosh_m1<P>(self) -> Self
where P: Policy,

cosh(x) - 1 = 2 sinh^2(x/2), an exact identity, so no type needs to override this: the composition inherits whatever accuracy that type’s sinh has, and near zero sinh(x/2) is already x/2 to full relative precision, giving x^2/2 with no cancellation anywhere. Same treatment as versin above.
Source§

fn sqrt1pm1<P>(self) -> Self
where P: Policy,

Source§

fn sqrt1mexp<P>(self) -> Self
where P: Policy,

Source§

fn compound<P>(self, n: Self) -> Self
where P: Policy,

Source§

fn powf_m1<P>(self, e: Self) -> Self
where P: Policy,

Source§

fn compound_m1<P>(self, n: Self) -> Self
where P: Policy,

Source§

fn haversin<P>(self) -> Self
where P: Policy,

Source§

fn versin<P>(self) -> Self
where P: Policy,

Source§

fn versinc<P>(self) -> Self
where P: Policy,

Source§

fn cos_m1<P>(self) -> Self
where P: Policy,

Source§

fn nth_root_n<P, const N: usize>(self) -> Self
where P: Policy,

Source§

fn nth_root<P>(self, n: u32) -> Self
where P: Policy,

The runtime twin of nth_root_n: the same arithmetic with the degree as a value, so the two agree to the bit at every n. The special cases are one uniform branch on n rather than a compile-time fold.
Source§

fn log2_p1<P>(self) -> Self
where P: Policy,

Source§

fn log10_p1<P>(self) -> Self
where P: Policy,

Source§

fn log1pmx<P>(self) -> Self
where P: Policy,

The direct form, which cancels near zero (see the trait method’s docs). Real f32/f64 vectors override this with generic::log1pmx_internal. The default exists so that ordered-comparison-free types (Complex above all, which cannot select a window at all) still get a correct answer rather than blocking the whole method.
Source§

fn log<P>(self, base: Self) -> Self
where P: Policy,

Source§

fn ln1m_expnx<P>(self) -> Self
where P: Policy,

ln(1 - e^(-x))
Source§

impl<V: CompensatedFloatVector> SplatVector<Compensated<<V as GenericVector>::Element>> for Compensated<V>

Source§

type Splat<T: SplatConst<Compensated<V::Element>>> = Compensated<V>

For a given constant carrier T, the type exposing the splatted vector constant via VectorValue.
Source§

impl<V: ScalarValue> Square for Compensated<V>

Source§

type Output = Compensated<V>

The squared value. Not always Self: a type may widen to hold the product.
Source§

fn square(self) -> Self

Computes self * self.
Source§

impl<V: CompensatedFloatVector> SquareMasked<<V as GenericVector>::Mask> for Compensated<V>

Source§

fn square_c(self, mask: V::Mask) -> Self::Output

Computes Square where mask is true, does nothing where false.
Source§

fn square_m(self, src: Self, mask: V::Mask) -> Self::Output

Merges Square with src using mask, returning src where mask is false.
Source§

fn square_z(self, mask: V::Mask) -> Self::Output

Computes Square masked (zeroed where mask is false).
Source§

impl<V: PartialEq> StructuralPartialEq for Compensated<V>

Source§

impl<V: ScalarValue> Sub for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Self) -> Self::Output

Performs the - operation. Read more
Source§

impl<V: ScalarValue> Sub<V> for Compensated<V>

Source§

type Output = Compensated<V>

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: V) -> Self::Output

Performs the - operation. Read more
Source§

impl<V: Copy, T> SubAssign<T> for Compensated<V>
where Self: Sub<T, Output = Self>,

Source§

fn sub_assign(&mut self, rhs: T)

Performs the -= operation. Read more
Source§

impl<V: CompensatedFloatVector, Rhs> SubAssignMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Sub<Rhs, Output = Self>,

Source§

fn sub_assign_c(&mut self, mask: V::Mask, rhs: Rhs)

Computes SubAssign with rhs where mask is true.
Source§

fn sub_assign_m(&mut self, src: Self, mask: V::Mask, rhs: Rhs)

Merges SubAssign with src using mask, assigning src where mask is false.
Source§

fn sub_assign_z(&mut self, mask: V::Mask, rhs: Rhs)

Computes SubAssign masked (zeroed where mask is false).
Source§

impl<V: CompensatedFloatVector, Rhs> SubMasked<<V as GenericVector>::Mask, Rhs> for Compensated<V>
where Compensated<V>: Sub<Rhs, Output = Self>,

Source§

fn sub_c(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Sub with rhs where mask is true.
Source§

fn sub_m(self, src: Self, mask: V::Mask, rhs: Rhs) -> Self

Merges Sub with src using mask, returning src where mask is false.
Source§

fn sub_z(self, mask: V::Mask, rhs: Rhs) -> Self

Computes Sub masked (zeroed where mask is false).
Source§

impl<V: ScalarValue> Sum for Compensated<V>

Source§

fn sum<I: Iterator<Item = Self>>(iter: I) -> Self

Takes an iterator and generates Self from the elements by “summing up” the items.
Source§

impl<V: CompensatedFloatVector> Swizzle<<V as GenericVector>::Lanes> for Compensated<V>

Source§

fn swizzle_const<I: SwizzleIndices<V::Lanes>>(self, other: Self) -> Self

Swizzle lanes from two vectors according to compile-time indices.
Source§

fn permutev_const<I: SwizzleIndices<V::Lanes>>(self) -> Self

Permute lanes of a single vector according to compile-time indices.
Source§

impl<V: CompensatedFloatVector, E: SplatConst<Compensated<V::Element>>> VectorValue<E, Compensated<V>> for Compensated<V>

Source§

const VALUE: Compensated<V>

The materialized vector constant.

Auto Trait Implementations§

§

impl<V> Freeze for Compensated<V>
where V: Freeze,

§

impl<V> RefUnwindSafe for Compensated<V>
where V: RefUnwindSafe,

§

impl<V> Send for Compensated<V>
where V: Send,

§

impl<V> Sync for Compensated<V>
where V: Sync,

§

impl<V> Unpin for Compensated<V>
where V: Unpin,

§

impl<V> UnsafeUnpin for Compensated<V>
where V: UnsafeUnpin,

§

impl<V> UnwindSafe for Compensated<V>
where V: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<V, Mask, Rhs> AssignMaskedNumOps<Mask, Rhs> for V
where V: AddAssignMasked<Mask, Rhs> + SubAssignMasked<Mask, Rhs> + MulAssignMasked<Mask, Rhs> + DivAssignMasked<Mask, Rhs> + RemAssignMasked<Mask, Rhs>,

Source§

impl<V> BernoulliMath for V

Source§

fn bernoulli_numbers(b1: Self::Element) -> BernoulliSequence<Self>

The sequence $B_0, B_1, B_2, \ldots$ as splatted vectors, zeros included. Read more
Source§

impl<E, V> BesselDetails<V> for V
where E: FloatElement, V: FloatVector<Element = E> + SpecializedPrimalMath<E>,

Source§

fn near(z: V) -> <V as GenericVector>::Mask

Lanes in the small-argument region, |z| <= 2, where K comes from Temme’s series.
Source§

fn beyond( z: V, threshold: <V as PrimalProjection>::Primal, ) -> <V as GenericVector>::Mask

Lanes with |z| >= threshold, per lane: where I takes the asymptotic series.
Source§

fn valid(z: V) -> <V as GenericVector>::Mask

Lanes inside the kernel’s domain: the open positive axis, or the closed right half-plane less the origin. The origin itself is selected to its limits by the kernel. Everything else outside this mask is NaN.
Source§

fn exp_far( z: V, threshold: <V as PrimalProjection>::Primal, ) -> <V as GenericVector>::Mask

Lanes where a single e^z overflows before e^z * a does, so the exponential is halved and applied twice: Re z >= threshold.
Source§

const ASYM_TWO_TERMS: bool = false

Whether the large-argument expansion of I carries its second exponential. Read more
Source§

fn asym_second_exponent(z: V, _nu: <V as PrimalProjection>::Primal) -> V

The exponent of that second term in the scaled domain, $-2z \pm (\nu+1/2)\pi i$ with the sign of Im z. Only read when ASYM_TWO_TERMS.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> CompensatedGammaOps for T

§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<M> CoreMath for M

Source§

fn poly_n_primal<N>(self, coeffs: &GenericArray<Self::Primal, N>) -> Self
where N: ArrayLength,

poly with the coefficients held in Primal form. Read more
Source§

fn poly_rev_n_primal<N>(self, coeffs: &GenericArray<Self::Primal, N>) -> Self
where N: ArrayLength,

poly_rev with the coefficients held in Primal form. Read more
Source§

fn poly_primal(self, coeffs: &[Self::Primal]) -> Self

poly_n_primal over a runtime-length slice. Read more
Source§

fn poly_rev_primal(self, coeffs: &[Self::Primal]) -> Self

poly_rev_n_primal over a runtime-length slice. Read more
Source§

fn poly(self, coeffs: &[Self::Element]) -> Self

Computes the polynomial with the given coefficients at self. Read more
Source§

fn poly_rev(self, coeffs: &[Self::Element]) -> Self

Computes the polynomial with the given coefficients at self, but with the coefficients in reverse order. Read more
Source§

fn poly_n<const N: usize>(self, coeffs: &[Self::Element; N]) -> Self

Computes the polynomial with the given coefficients at self. Read more
Source§

fn poly_rev_n<const N: usize>(self, coeffs: &[Self::Element; N]) -> Self

Computes the polynomial with the given coefficients at self, but with the coefficients in reverse order. Read more
Source§

fn poly_rational_n<const N: usize, const D: usize>( self, numerator: &[Self::Element; N], denominator: &[Self::Element; D], ) -> Self

Computes the ratio of two polynomials at self, given the numerator and denominator coefficients. Read more
Source§

fn approx_reciprocal(self) -> Self

Returns the multiplicative inverse of self, which is 1 / self. Read more
Source§

fn approx_div(self, divisor: Self) -> Self

Returns the result of dividing self by divisor, i.e., self / divisor. Read more
Source§

fn approx_div_sqrt(self, denom: Self) -> Self

Returns $a/\sqrt{b}$, spelled a.approx_div_sqrt(b), as one kernel rather than a divide bolted onto a square root. Read more
Source§

fn difference_of_products(self, b: Self, c: Self, d: Self) -> Self

$ab - cd$, spelled a.difference_of_products(b, c, d), evaluated so the two products cannot cancel catastrophically. Read more
Source§

fn sum_of_products(self, b: Self, c: Self, d: Self) -> Self

$ab + cd$, spelled a.sum_of_products(b, c, d). Read more
Source§

fn harmonic_mean_n<const N: usize>(values: [Self; N]) -> Self

The harmonic mean of N values, $N / \sum_i 1/x_i$. Read more
Source§

fn harmonic_mean(values: &[Self]) -> Self

harmonic_mean_n over a runtime-length slice. Read more
Source§

fn inv_sum_inv_n<const N: usize>(values: [Self; N]) -> Self

$1 / \sum_i 1/x_i$, the reciprocal of the sum of reciprocals of N values. Read more
Source§

fn inv_sum_inv(values: &[Self]) -> Self

inv_sum_inv_n over a runtime-length slice. Read more
Source§

fn inverse_sqrt(self) -> Self

Returns the inverse square root of self, which is 1 / sqrt(self). Read more
Source§

fn powi(self, e: i32) -> Self

Returns self raised to the signed integer power of e.
Source§

fn powiv(self, e: Self::Signed) -> Self

Returns self raised to the signed integer power of each element in e.
Source§

impl<E, V> CoreMathWithPolicy for V

Source§

fn poly_n_primal_p<P, N>( self, coeffs: &GenericArray<<V as PrimalProjection>::Primal, N>, ) -> V
where P: Policy, N: ArrayLength,

poly with the coefficients held in Primal form.

The augmented fields of a constant (a Dual’s derivatives, a Complex’s imaginary part) are identically zero, so carrying coefficients in Self stores those zeros and then adds them at every Horner step. Neither the storage nor the addition can be optimized away: x + 0.0 is not x when x is -0.0, so the adds survive to run time.

Taking them as Self::Primal removes both. The coefficient array shrinks by the augmentation factor (4x for Dual<V, 3>, 2x for Complex), and each Horner step adds to the primal component alone.

For a type that is its own primal this is exactly poly with pre-splatted coefficients, and the default impl reduces to it.

Coefficients are vectors, not elements: a caller with a constant table has usually splatted it once already, and the composites that benefit most are the ones for which splatting per call would be the expensive part.

The length is a typenum length rather than a const N: usize so that a coefficient table can be supplied by a type that knows its own length only as an associated type. Literal call sites spell it [GenericArray::from_array].

Source§

fn poly_rev_n_primal_p<P, N>( self, coeffs: &GenericArray<<V as PrimalProjection>::Primal, N>, ) -> V
where P: Policy, N: ArrayLength,

poly_rev with the coefficients held in Primal form.

Same trade as poly_n_primal (the constants carry no augmented fields to store or add), with the coefficients in reverse order.

Source§

fn poly_primal_p<P>(self, coeffs: &[<V as PrimalProjection>::Primal]) -> V
where P: Policy,

poly_n_primal over a runtime-length slice.

A plain slice rather than a GenericArray, since the length is no longer carried in the type, which is also why this one has no reason to reach for typenum. Same primal-Horner step and the same saving on the addend. What the runtime length costs is the unrolling and, for real vectors, the ILP lowering, exactly as in poly.

The empty polynomial is 0.

Source§

fn poly_rev_primal_p<P>(self, coeffs: &[<V as PrimalProjection>::Primal]) -> V
where P: Policy,

poly_rev_n_primal over a runtime-length slice.

Same trade as poly_primal, coefficients descending.

Source§

fn poly_p<P>(self, coeffs: &[<V as GenericVector>::Element]) -> V
where P: Policy,

Computes the polynomial with the given coefficients at self.

This will use fused multiply-add instructions where available for improved performance and accuracy, but falls back to standard operations if not.

If you know the length of your coefficient array at compile time, strongly consider using poly_n instead, which can be optimized more aggressively.

Source§

fn poly_rev_p<P>(self, coeffs: &[<V as GenericVector>::Element]) -> V
where P: Policy,

Computes the polynomial with the given coefficients at self, but with the coefficients in reverse order.

This will use fused multiply-add instructions where available for improved performance and accuracy, but falls back to standard operations if not.

If you know the length of your coefficient array at compile time, strongly consider using poly_rev_n instead, which can be optimized more aggressively.

Source§

fn poly_n_p<P, const N: usize>( self, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Computes the polynomial with the given coefficients at self.

This will use fused multiply-add instructions where available for improved performance and accuracy, but falls back to standard operations if not.

Source§

fn poly_rev_n_p<P, const N: usize>( self, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Computes the polynomial with the given coefficients at self, but with the coefficients in reverse order.

This will use fused multiply-add instructions where available for improved performance and accuracy, but falls back to standard operations if not.

Source§

fn poly_rational_n_p<P, const N: usize, const D: usize>( self, numerator: &[<V as GenericVector>::Element; N], denominator: &[<V as GenericVector>::Element; D], ) -> V
where P: Policy,

Computes the ratio of two polynomials at self, given the numerator and denominator coefficients.

Equivalent to poly_n(numerator) / poly_n(denominator), but with improved numerical stability in some cases.

This will use fused multiply-add instructions where available for improved performance and accuracy, but falls back to standard operations if not.

Source§

fn approx_reciprocal_p<P>(self) -> V
where P: Policy,

Returns the multiplicative inverse of self, which is 1 / self.

approx_ because the fast precision tiers take the hardware reciprocal estimate (refined by one Newton step above Worst) where one exists. Best and above, Preserve denormal policies, and backends without an estimate all get the exact 1 / self.

If using the policy version, you may select lower precision policies for extra performance, at the cost of accuracy.

Source§

fn approx_div_p<P>(self, divisor: V) -> V
where P: Policy,

Returns the result of dividing self by divisor, i.e., self / divisor.

Depending on the precision policy and available features, this may be optimized to use approximate reciprocal and multiplication for better performance, at the cost of accuracy.

Source§

fn approx_div_sqrt_p<P>(self, denom: V) -> V
where P: Policy,

Returns $a/\sqrt{b}$, spelled a.approx_div_sqrt(b), as one kernel rather than a divide bolted onto a square root.

Reach for this wherever a quantity is normalized by a root: a direction divided by its length, a value divided by a standard deviation, a weight divided by $\sqrt{n}$. Writing a / b.sqrt() gets the same answer at the top precision tier and a strictly worse one everywhere else, because the separate spelling cannot use the hardware reciprocal-square-root estimate.

Depending on the precision policy and available features this is either a multiply by the hardware reciprocal-square-root estimate (refined by one Newton step above the lowest tier), or an exact square root and divide. At Best and above it is exactly a / b.sqrt(), since a hardware divide already returns that correctly rounded and there is nothing left for the kernel to add.

$b = 0$ gives infinity and $b < 0$ gives NaN, inherited from the root.

Source§

fn difference_of_products_p<P>(self, b: V, c: V, d: V) -> V
where P: Policy,

$ab - cd$, spelled a.difference_of_products(b, c, d), evaluated so the two products cannot cancel catastrophically.

Reach for this wherever an expression’s correctness argument is “the two errors cancel by symmetry”: cross products and perp-dots, 2x2 determinants and matrix adjugates, discriminants $b^2 - 4ac$, the $ac - bd$ of a complex multiply, and every sign test built on one of those.

Longhand gets this wrong in two ways. Naive a * b - c * d loses the whole difference when the products are close. A one-sided fused spelling (a.mul_sube(b, c * d)) looks like the fix and is worse for the case that usually matters, because it leaves one product exact and rounds the other, so $ab - ba$ comes back as a small non-zero rather than exactly zero. It does that only on hardware with FMA, which makes it a portability bug as much as an accuracy one: the same source gives a self-cross-product of zero on baseline x86 and a denormal on AArch64.

Three lowerings, chosen at compile time from the FMA capability and the precision policy:

conditionevaluated ascost
no true FMAa * b - c * d3 ops
true FMA, precision below Averagefma(a, b, -cd)2 ops
true FMA, precision Average or aboveKahan’s compensated form4 ops

Kahan’s form recovers the discarded rounding of $cd$ with a second FMA and adds it back, for ~1.5 ulp, correctly signed, and exact whenever the two products are equal. Average is the default policy’s tier, so that is what an unsuffixed call gets. Without FMA the naive form is both the cheapest available and the only one with the exactness property, so it runs at every precision rather than emulating a fused multiply.

Source§

fn sum_of_products_p<P>(self, b: V, c: V, d: V) -> V
where P: Policy,

$ab + cd$, spelled a.sum_of_products(b, c, d).

The companion to difference_of_products, with the same three lowerings and the same reasoning. A sum of products cancels exactly as badly as a difference when the two terms have opposite signs, which is the ordinary case for the imaginary half of a complex multiply.

Source§

fn harmonic_mean_n_p<P, const N: usize>(values: [V; N]) -> V
where P: Policy,

The harmonic mean of N values, $N / \sum_i 1/x_i$.

The mean that averages rates: harmonic over speeds gives the average speed of a journey, over resistances the value each resistor could be replaced by, over precision and recall the F1 score. Dominated by the smallest element, which is the property that makes it the right average for anything that behaves like a bottleneck.

Evaluated by scaling every reciprocal by the smallest element before summing, so the sum lands in [1, N] and no term can overflow whatever the spread of the inputs. Written directly as $N/\sum 1/x_i$ a single denormal input sends its reciprocal to infinity and collapses the answer to zero. Scaled, an input range of 5e-324 to 1e300 is still exact. Below Average precision the direct form runs, with approximate reciprocals, and that failure comes back.

A zero anywhere in the input gives 0, which is the limit rather than a special case. An infinite element simply contributes nothing.

Source§

fn harmonic_mean_p<P>(values: &[V]) -> V
where P: Policy,

harmonic_mean_n over a runtime-length slice.

Same evaluation and same edge cases. The length simply is not a constant, so the loops cannot unroll and the reduction is serial rather than log-depth. If you know the count at compile time, prefer harmonic_mean_n.

The mean of no values is NaN (0/0), matching the empty-average convention rather than inventing a value.

Source§

fn inv_sum_inv_n_p<P, const N: usize>(values: [V; N]) -> V
where P: Policy,

$1 / \sum_i 1/x_i$, the reciprocal of the sum of reciprocals of N values.

harmonic_mean_n without the N, and the quantity most physical “combine these” laws actually want: resistors in parallel, capacitors in series, spring compliances, the reduced mass $m_1 m_2/(m_1+m_2)$ of a two-body problem, thermal contact conductances, and the effective conductivity of a layered medium. Each of those is this function, not the harmonic mean, which is N times larger, a factor that silently multiplies through an entire model if the two are confused.

The distinguishing identity: inv_sum_inv of N copies of x is $x/N$, while the harmonic mean of them is $x$.

Same scaled evaluation and same edge cases as harmonic_mean_n.

Source§

fn inv_sum_inv_p<P>(values: &[V]) -> V
where P: Policy,

inv_sum_inv_n over a runtime-length slice.

Same evaluation and same edge cases as harmonic_mean, with the same loss of unrolling. The empty input gives $1/0 =$ infinity, the identity of the parallel-combination law this implements.

Source§

fn inverse_sqrt_p<P>(self) -> V
where P: Policy,

Returns the inverse square root of self, which is 1 / sqrt(self).

If using the policy version, you may select lower precision policies for extra performance, at the cost of accuracy.

Source§

fn powi_p<P>(self, e: i32) -> V
where P: Policy,

Returns self raised to the signed integer power of e.

Source§

fn powiv_p<P>(self, e: <V as GenericVector>::Signed) -> V
where P: Policy,

Returns self raised to the signed integer power of each element in e.

Source§

impl<T> ElementExt for T
where T: Element,

§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<V> GenericVector2 for V
where V: GenericVector<Lanes = UInt<UInt<UTerm, B1>, B0>>,

Source§

fn x(&self) -> Self::Element

Returns the value of lane 0.
Source§

fn y(&self) -> Self::Element

Returns the value of lane 1.
Source§

impl<V> GenericVector3 for V
where V: GenericVector<Lanes = UInt<UInt<UTerm, B1>, B1>>,

Source§

fn x(&self) -> Self::Element

Returns the value of lane 0.
Source§

fn y(&self) -> Self::Element

Returns the value of lane 1.
Source§

fn z(&self) -> Self::Element

Returns the value of lane 2.
Source§

impl<V> GenericVector4 for V
where V: GenericVector<Lanes = UInt<UInt<UInt<UTerm, B1>, B0>, B0>>,

Source§

fn x(&self) -> Self::Element

Returns the value of lane 0.
Source§

fn y(&self) -> Self::Element

Returns the value of lane 1.
Source§

fn z(&self) -> Self::Element

Returns the value of lane 2.
Source§

fn w(&self) -> Self::Element

Returns the value of lane 3.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> LowerBounded for T
where T: Bounded,

Source§

fn min_value() -> T

Returns the smallest finite number this type can represent
Source§

impl<T, A, B> MaskInteroperable<A, B> for T

Source§

impl<V, Mask, Rhs> MaskedNumOps<Mask, Rhs> for V
where V: AddMasked<Mask, Rhs> + SubMasked<Mask, Rhs> + MulMasked<Mask, Rhs> + DivMasked<Mask, Rhs> + RemMasked<Mask, Rhs>,

Source§

impl<T, Rhs> NumAssignOps<Rhs> for T
where T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>,

Source§

impl<T, Rhs, Output> NumOps<Rhs, Output> for T
where T: Sub<Rhs, Output = Output> + Mul<Rhs, Output = Output> + Div<Rhs, Output = Output> + Add<Rhs, Output = Output> + Rem<Rhs, Output = Output>,

Source§

impl<V, A, B> PartiallyInteroperable<A, B> for V

§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<M> PrimalMath for M

Source§

impl<E, V> PrimalMathWithPolicy for V
where E: FloatElement, V: FloatVector<Element = E> + RealMathWithPolicy<Primal = V> + PrimalProjection + SpecializedPrimalMath<E>,

Source§

impl<E, V> PrimalProjection for V
where E: FloatElement, V: FloatVector<Element = E> + SpecializedPrimalMath<E>,

Source§

type Primal = V

The unaugmented value type of Self. See the trait docs.
Source§

fn from_primal(p: <V as PrimalProjection>::Primal) -> V

Embeds a primal value as a constant of Self: every non-primal field (derivative parts, imaginary part) is initialized to zero. The identity for primal types. Read more
Source§

fn to_primal(self) -> <V as PrimalProjection>::Primal

Projects self down to its primal value, discarding every non-primal field. The identity for primal types. Read more
Source§

impl<M> RealMath for M

Source§

fn tolerance() -> Self

Returns the precision tolerance based on the selected policy. This is a good default tolerance to use for numerical methods.
Source§

fn to_degrees(self) -> Self

Converts angles from radians to degrees.
Source§

fn to_radians(self) -> Self

Converts angles from degrees to radians.
Source§

fn wrap_angle(self) -> Self

Wraps the angle (radians) in self to the range [-π, π). Read more
Source§

fn angle_diff(self, other: Self) -> Self

Computes the smallest difference between two angles (in radians), taking into account angle wrapping. Read more
Source§

fn atan2(self, x: Self) -> Self

Returns the four-quadrant arctangent of self and x. Read more
Source§

fn lerp(self, a: Self, b: Self) -> Self

Linearly interpolates between a and b based on the value of self. Read more
Source§

fn rescale( self, in_min: Self, in_max: Self, out_min: Self, out_max: Self, ) -> Self

Scales self from the input range [in_min, in_max] to the output range [out_min, out_max]. Read more
Source§

fn logaddexp(self, other: Self) -> Self

Returns $\ln(e^{a} + e^{b})$ computed in a numerically stable way that avoids overflow, where a = self and b = other. Read more
Source§

fn logmean(self, other: Self) -> Self

The logarithmic mean $L(x, y) = \frac{x - y}{\ln x - \ln y}$, for positive x and y. Read more
Source§

fn logsumexp_n<const N: usize>(values: [Self; N]) -> Self

Returns $\ln\left(\sum_{i} e^{x_i}\right)$ over N values, computed in a numerically stable way that avoids overflow. Read more
Source§

fn logsumexp(values: &[Self]) -> Self

logsumexp_n over a runtime-length slice. Read more
Source§

fn logsubexp(self, other: Self) -> Self

Returns $\ln(e^{a} - e^{b})$ where a = self and b = other, computed in a numerically stable way that avoids overflow. Read more
Source§

fn entr(self) -> Self

The entropy term $-x \ln x$ of self, extended to the closed half-line. Read more
Source§

fn rel_entr(self, y: Self) -> Self

The relative-entropy term $x \ln(x/y)$, with x = self. Read more
Source§

fn kl_div(self, y: Self) -> Self

The convex-programming Kullback-Leibler divergence term, with x = self. Read more
Source§

fn smoothstep<const N: usize>(self, edges: Option<(Self, Self)>) -> Self

Generalized smoothstep function of Order 2N-1. Note: The “smoothness” for higher order is in terms of the number of continuous derivatives, not in terms of visual smoothness, though they are related in some ways. Read more
Source§

fn inverse_smoothstep<const N: usize>(self, edges: Option<(Self, Self)>) -> Self

Returns the inverse smoothstep of self, which is the value that would produce self when passed to smoothstep. Read more
Source§

fn smoothstep_derivative<const N: usize>( self, edges: Option<(Self, Self)>, ) -> Self

Derivative of the smoothstep function of order 2N-1, at the given point.
Source§

fn smooth_interpolator(self, edges: Option<(Self, Self)>, k: Self) -> Self

C∞-smooth interpolation factor between the given edges (defaulting to 0 and 1). Read more
Source§

fn smooth_interpolator_inverse( self, edges: Option<(Self, Self)>, k: Self, ) -> Self

Source§

fn step(self, edge: Self) -> Self

Returns 1 if self is greater than or equal to edge, otherwise returns 0.
Source§

impl<E, V> RealMathWithPolicy for V

Source§

fn tolerance_p<P>() -> V
where P: Policy,

Returns the precision tolerance based on the selected policy. This is a good default tolerance to use for numerical methods.

Source§

fn to_degrees_p<P>(self) -> V
where P: Policy,

Converts angles from radians to degrees.

Source§

fn to_radians_p<P>(self) -> V
where P: Policy,

Converts angles from degrees to radians.

Source§

fn wrap_angle_p<P>(self) -> V
where P: Policy,

Wraps the angle (radians) in self to the range [-π, π).

The formula for this is self - floor((self + π) / 2π) * 2π

Source§

fn angle_diff_p<P>(self, other: V) -> V
where P: Policy,

Computes the smallest difference between two angles (in radians), taking into account angle wrapping.

To get the “distance” between two angles, use the absolute value of the result.

Source§

fn atan2_p<P>(self, x: V) -> V
where P: Policy,

Returns the four-quadrant arctangent of self and x.

This method is only defined for real-valued types.

Source§

fn lerp_p<P>(self, a: V, b: V) -> V
where P: Policy,

Linearly interpolates between a and b based on the value of self.

This operation is not clamped.

Source§

fn rescale_p<P>(self, in_min: V, in_max: V, out_min: V, out_max: V) -> V
where P: Policy,

Scales self from the input range [in_min, in_max] to the output range [out_min, out_max].

This operation is not clamped.

Source§

fn logaddexp_p<P>(self, other: V) -> V
where P: Policy,

Returns $\ln(e^{a} + e^{b})$ computed in a numerically stable way that avoids overflow, where a = self and b = other.

Evaluated as $\max(a, b) + \ln(1 + e^{-|a - b|})$, so the result is accurate even when a and b are large. This is the workhorse of stable log-domain probability arithmetic (e.g. the two-argument log-sum-exp).

Source§

fn logmean_p<P>(self, other: V) -> V
where P: Policy,

The logarithmic mean $L(x, y) = \frac{x - y}{\ln x - \ln y}$, for positive x and y.

Sits between the geometric and arithmetic means, and is the mean that arises whenever a quantity varies exponentially across an interval, the log-mean temperature difference of a heat exchanger being the standard example.

The defining form cancels in both the numerator and the denominator as x approaches y, which is the common case rather than a corner. Evaluated here as $\frac{x - y}{2\,\mathrm{atanh}\!\left(\frac{x-y}{x+y}\right)}$, which is stable throughout. For nearby arguments the subtraction is exact by Sterbenz’s lemma and atanh is accurate near zero. Equal arguments return x, the limiting value.

Source§

fn logsumexp_n_p<P, const N: usize>(values: [V; N]) -> V
where P: Policy,

Returns $\ln\left(\sum_{i} e^{x_i}\right)$ over N values, computed in a numerically stable way that avoids overflow.

The N-ary logaddexp: normalizing a set of log-weights, the denominator of a log-softmax, the forward pass of an HMM. The largest term is factored out first, so no intermediate exponential can overflow whatever the inputs are.

N = 0 gives -inf, the empty sum and the identity of logaddexp, so folding this over any partition of the inputs agrees with running it over all of them at once. Above the Worst precision policy the non-dominant terms go through ln_1p, which keeps the answer accurate when one weight dominates.

§Examples
use thermite::prelude::*;

type V = Vector<f64>;

// Overflows outright if evaluated as `ln(e^1000 + e^1001 + e^999)`.
let y = V::logsumexp_n([V::splat(1000.0), V::splat(1001.0), V::splat(999.0)]);
assert!((y.extract::<0>() - 1001.4076059644443).abs() < 1e-12);
Source§

fn logsumexp_p<P>(values: &[V]) -> V
where P: Policy,

logsumexp_n over a runtime-length slice.

Same shifted evaluation and the same overflow safety. The length simply is not a constant, so the max and the sum are serial folds rather than tree reductions and the N = 1/N = 2 shortcuts are runtime branches. If you know the count at compile time, prefer logsumexp_n.

The empty input gives -inf, the identity of logaddexp, so folding this over any partition of the inputs agrees.

Source§

fn logsubexp_p<P>(self, other: V) -> V
where P: Policy,

Returns $\ln(e^{a} - e^{b})$ where a = self and b = other, computed in a numerically stable way that avoids overflow.

The subtractive counterpart of logaddexp, for removing a term from a log-domain sum (a leave-one-out normalizer, a difference of cumulative distribution functions in log space). Evaluated as $a + \ln(1 - e^{-(a - b)})$ via ln1m_expnx, so no intermediate exponential overflows and the precision ladder is that kernel’s.

At Average precision and above, $\ln(1 - e^{-x})$ is split into two regimes at $\ln 2$, keeping the subtraction inside exp_m1 below the split and inside ln_1p above it, which is accurate at both ends of the gap. A single $(1 - e^{-x})$ followed by a log loses the small gaps to cancellation and the large ones to $1 - e^{-x}$ rounding to exactly 1. Below Average, ln1m_expnx’s cheaper forms apply, with the accuracy losses those tiers accept.

The result exists only for a >= b, and is -inf at a == b. An a < b input is out of domain and gives NaN at Average precision and above.

Source§

fn entr_p<P>(self) -> V
where P: Policy,

The entropy term $-x \ln x$ of self, extended to the closed half-line.

\mathrm{entr}(x) = \begin{cases} -x \ln x & x > 0 \\ 0 & x = 0 \\ -\infty & x < 0\end{cases}

The $x = 0$ value is the limit. The $-\infty$ below zero is not a limit but a convention, the extended-value form that keeps entr concave over all of $\mathbb{R}$ so a convex solver can use it as a barrier. SciPy, CVXPY and Convex.jl all define it this way. Summing entr over a distribution gives its Shannon entropy in nats.

Source§

fn rel_entr_p<P>(self, y: V) -> V
where P: Policy,

The relative-entropy term $x \ln(x/y)$, with x = self.

\mathrm{rel\_entr}(x, y) = \begin{cases} x \ln(x/y) & x > 0,\; y > 0 \\ 0 & x = 0,\; y \ge 0 \\ +\infty & \text{otherwise}\end{cases}

This is the Kullback-Leibler summand: $D_{KL}(P \Vert Q)$ is the sum of rel_entr over the two distributions, and kl_div is the one that carries extra terms, not this. The naming is SciPy’s and catches people out in both directions.

The $+\infty$ covers $y = 0$ at positive x (an event the model assigns zero probability but the data observed, which is genuinely infinite surprise) as well as negative inputs, which are out of domain.

Source§

fn kl_div_p<P>(self, y: V) -> V
where P: Policy,

The convex-programming Kullback-Leibler divergence term, with x = self.

\mathrm{kl\_div}(x, y) = \begin{cases} x \ln(x/y) - x + y & x > 0,\; y > 0 \\ y & x = 0,\; y \ge 0 \\ +\infty & \text{otherwise}\end{cases}

The $-x + y$ tail is not part of the Kullback-Leibler divergence. It is what makes this the Bregman divergence generated by $x \ln x$, which is non-negative and zero only at $x = y$ even when the arguments are unnormalized, the property a solver needs and that the bare summand lacks. For the divergence itself use rel_entr, whose sum over a normalized pair equals this one’s because the tails cancel.

That tail is also why the written form cannot be evaluated as written. With $y = x(1+u)$ the log term is $-xu + xu^2/2$ and the tail is $+xu$: two first-order quantities cancelling to a second-order answer, so near $x = y$ the direct spelling is not imprecise but entirely wrong. Evaluated here as the identity $-x \cdot \mathrm{log1pmx}((y-x)/x)$, which moves the cancellation inside log1pmx, where it belongs. Same identity as the Poisson deviance; bd0 in thermite-special is this function under another name.

Source§

fn smoothstep_p<P, const N: usize>(self, edges: Option<(V, V)>) -> V
where P: Policy,

Generalized smoothstep function of Order 2N-1. Note: The “smoothness” for higher order is in terms of the number of continuous derivatives, not in terms of visual smoothness, though they are related in some ways.

For N=0, this is equivalent to the step function.
For N=1, this is a linear line between 0 and 1.
For N=2, this is equivalent to the standard 3rd-order smoothstep function.
For N=3, this is equivalent to the 5th-order “smootherstep” function.

For single precision, N can go up to 10, whereas for double precision, N can go up to 20.

See smooth_interpolator for a more advanced interpolator with infinite differentiability.

§Examples
use thermite::prelude::*;

type V = Vector<f64>;

// Standard 3rd-order smoothstep (N = 2) over the default [0, 1] edges:
// 3t^2 - 2t^3
let y = V::splat(0.25).smoothstep::<2>(None);
assert!((y.extract::<0>() - 0.15625).abs() < 1e-15);
Source§

fn inverse_smoothstep_p<P, const N: usize>(self, edges: Option<(V, V)>) -> V
where P: Policy,

Returns the inverse smoothstep of self, which is the value that would produce self when passed to smoothstep.

N from 0..=2 have fast closed-form solutions, while higher N use numerical root-finding methods, which will inherently be much slower.

§Examples

Round-trips smoothstep, even at high orders where the inverse must be found numerically:

use thermite::prelude::*;

type V = Vector<f64>;

let x = V::splat(1.0 / 16.0);
let y = x.smoothstep::<12>(None);
let x_back = y.inverse_smoothstep::<12>(None);
assert!((x_back.extract::<0>() - x.extract::<0>()).abs() < 1e-9);
Source§

fn smoothstep_derivative_p<P, const N: usize>(self, edges: Option<(V, V)>) -> V
where P: Policy,

Derivative of the smoothstep function of order 2N-1, at the given point.

Source§

fn smooth_interpolator_p<P>(self, edges: Option<(V, V)>, k: V) -> V
where P: Policy,

C∞-smooth interpolation factor between the given edges (defaulting to 0 and 1).

Constructs a smooth transition function using:

f(x) = e^(-1 / (k * x))
g(x) = f(x) / (f(x) + f(1 - x))

The result is C∞-differentiable (infinitely smooth), with all derivatives vanishing at both endpoints, so it beats polynomial smoothstep wherever flatness at the edges is what matters.

The k parameter controls the shape of the transition:

  • k < 1: sharpens the curve, concentrating the transition near the midpoint.
  • k = 1: the standard balanced sigmoid-like transition.
  • k > 1: stretches the transition region, so the curve is more gradual.
  • $k \approx 2/\sqrt{3}$ (~1.1547): the function becomes bimodal. Use with caution above this value.
Source§

fn smooth_interpolator_inverse_p<P>(self, edges: Option<(V, V)>, k: V) -> V
where P: Policy,

Inverse of smooth_interpolator.

Given an output value y in [0, 1], recovers the input x such that smooth_interpolator(x, edges, k) ≈ y.

Source§

fn step_p<P>(self, edge: V) -> V
where P: Policy,

Returns 1 if self is greater than or equal to edge, otherwise returns 0.

Source§

impl<M> RealPrimalMath for M

Source§

fn spherical_harmonics_d<const L: usize, const N: usize, const CS: bool>( x: Self, y: Self, z: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], ddz: &mut [Self; N], )

spherical_harmonics plus the ambient Cartesian gradient of every harmonic, into ddx/ddy/ddz. Read more
Source§

fn zernike_basis_d<const L: usize, const NORM: u8, const N: usize>( x: Self, y: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], )

zernike_basis plus $\partial Z_n^m/\partial x$ and $\partial Z_n^m/\partial y$ for every mode, in the same ANSI layout. Read more
Source§

fn spherical_harmonics_d_with<const L: usize, const N: usize>( table: &ShTable<Self, N>, x: Self, y: Self, z: Self, out: &mut [Self; N], ddx: &mut [Self; N], ddy: &mut [Self; N], ddz: &mut [Self; N], )

spherical_harmonics_with plus the ambient Cartesian gradients, from a prebuilt table.
Source§

fn softplus_d(self, k: Self, rcp_k: Self) -> (Self, Self)

softplus together with its derivative w.r.t. x (the logistic sigmoid $\sigma(kx)$).
Source§

fn gelu_d(self, alpha: Self) -> (Self, Self)

gelu together with its derivative w.r.t. x.
Source§

fn swish_d(self, beta: Self) -> (Self, Self)

swish together with its derivative w.r.t. x.
Source§

fn algebraic_sigmoid_d_n<const N: usize>(self) -> (Self, Self)

algebraic_sigmoid together with its derivative w.r.t. x.
Source§

fn algebraic_sigmoid_d(self, n: u32) -> (Self, Self)

algebraic_sigmoid_d_n for a degree known only at runtime.
Source§

fn algebraic_swish_d(self) -> (Self, Self)

algebraic_swish together with its derivative w.r.t. x.
Source§

fn langevin_d(self) -> (Self, Self)

langevin together with its derivative $L'(x) = \frac{1}{x^2} - \operatorname{csch}^2 x$. Read more
Source§

impl<E, V> RealPrimalMathWithPolicy for V

Source§

fn spherical_harmonics_d_p<P, const L: usize, const N: usize, const CS: bool>( x: V, y: V, z: V, out: &mut [V; N], ddx: &mut [V; N], ddy: &mut [V; N], ddz: &mut [V; N], )
where P: Policy,

spherical_harmonics plus the ambient Cartesian gradient of every harmonic, into ddx/ddy/ddz.

Lives on RealPrimalMath rather than RealSpecialMath, so Dual does not get it, and should not want it. If you need $\partial/\partial(x,y,z)$, call this directly rather than evaluating spherical_harmonics on a Dual<V, 3> seeded with an identity Jacobian: this shares the recurrence between the value and all three gradients, whereas dual arithmetic carries a derivative through every operation and costs roughly twice as much.

Dual earns its keep on the value form instead, where (x, y, z) are themselves functions of upstream parameters and the chain rule has real work to do. Even there, going the other way (contracting these three gradients against an upstream Jacobian) loses: spherical harmonics cost about two operations per harmonic to evaluate but three per harmonic per parameter to contract, because one recurrence produces the whole basis.

The derivatives are those of the polynomial form at the given (unit) input. Project out the radial component (g - (g . n) n) for the tangential gradient. Shares all recurrence work with the value pass, since the gradients come from tabulated norm ratios, not new recurrences.

Source§

fn zernike_basis_d_p<P, const L: usize, const NORM: u8, const N: usize>( x: V, y: V, out: &mut [V; N], ddx: &mut [V; N], ddy: &mut [V; N], )
where P: Policy,

zernike_basis plus $\partial Z_n^m/\partial x$ and $\partial Z_n^m/\partial y$ for every mode, in the same ANSI layout.

This is what a Shack-Hartmann wavefront reconstruction integrates against. The sensor measures local wavefront slopes, not the wavefront itself, so the fit matrix is built from the gradient basis and the value basis never appears in it.

Lives on RealPrimalMath rather than SpecialMath for the same reason spherical_harmonics_d does: Dual should not get it and should not want it. Seeding a Dual<V, 2> and calling the value form carries two derivative components through every operation of the whole ladder, where this differentiates only the two factors that depend on the point and shares the radial recurrence between the value and both gradients.

The gradient is finite everywhere, including the pupil centre. That is the practical dividend of the Cartesian formulation: the polar $\partial_\theta Z/\rho$ is singular there, and hand-rolled polar implementations guard the origin with a special case.

N must equal (L+1)(L+2)/2, and NORM is as on zernike_basis. All three output buffers are written in full.

Source§

fn spherical_harmonics_d_with_p<P, const L: usize, const N: usize>( table: &ShTable<V, N>, x: V, y: V, z: V, out: &mut [V; N], ddx: &mut [V; N], ddy: &mut [V; N], ddz: &mut [V; N], )
where P: Policy,

spherical_harmonics_with plus the ambient Cartesian gradients, from a prebuilt table.

Source§

fn softplus_d_p<P>(self, k: V, rcp_k: V) -> (V, V)
where P: Policy,

softplus together with its derivative w.r.t. x (the logistic sigmoid $\sigma(kx)$).

Source§

fn gelu_d_p<P>(self, alpha: V) -> (V, V)
where P: Policy,

gelu together with its derivative w.r.t. x.

Source§

fn swish_d_p<P>(self, beta: V) -> (V, V)
where P: Policy,

swish together with its derivative w.r.t. x.

Source§

fn algebraic_sigmoid_d_n_p<P, const N: usize>(self) -> (V, V)
where P: Policy,

algebraic_sigmoid together with its derivative w.r.t. x.

Source§

fn algebraic_sigmoid_d_p<P>(self, n: u32) -> (V, V)
where P: Policy,

algebraic_sigmoid_d_n for a degree known only at runtime.

Source§

fn algebraic_swish_d_p<P>(self) -> (V, V)
where P: Policy,

algebraic_swish together with its derivative w.r.t. x.

Source§

fn langevin_d_p<P>(self) -> (V, V)
where P: Policy,

langevin together with its derivative $L'(x) = \frac{1}{x^2} - \operatorname{csch}^2 x$.

The derivative shares every intermediate with the value, so this costs a handful of arithmetic ops over langevin alone.

Source§

impl<M> RealSpecialMath for M

Source§

fn erfinv(self) -> Self

Computes the inverse error function.
Source§

fn probit(self) -> Self

Computes the Probit function, the inverse of the cumulative distribution function of the standard normal distribution.
Source§

fn ndtr(self) -> Self

Computes the cumulative distribution function of the standard normal distribution, the inverse of probit: Read more
Source§

fn log_ndtr(self) -> Self

Computes $\ln \Phi(x)$, the logarithm of the standard normal CDF, finite for every finite x. Read more
Source§

fn logerfc(self) -> Self

Computes $\ln \operatorname{erfc}(x)$, finite for every finite x. Read more
Source§

fn fresnel(self) -> (Self, Self)

The Fresnel integrals $S(x) = \int_0^x \sin(\pi t^2/2)\,dt$ and $C(x) = \int_0^x \cos(\pi t^2/2)\,dt$, together. Read more
Source§

fn fresnel_c(self) -> Self

$C(x)$ alone. See fresnel. Read more
Source§

fn fresnel_s(self) -> Self

$S(x)$ alone. See fresnel_c.
Source§

fn sici(self) -> (Self, Self)

The trigonometric integrals $\mathrm{Si}(x) = \int_0^x \frac{\sin t}{t}\,dt$ and $\mathrm{Ci}(x) = \gamma + \ln x + \int_0^x \frac{\cos t - 1}{t}\,dt$, together. Returns (Si, Ci). Read more
Source§

fn sinint(self) -> Self

$\mathrm{Si}(x)$ alone. See sici, and fresnel_c for what a single accessor saves.
Source§

fn cosint(self) -> Self

$\mathrm{Ci}(x)$ alone. See sici.
Source§

fn inv_log_ndtr(self) -> Self

Computes the inverse of log_ndtr: the x with $\ln \Phi(x) = y$, for y <= 0. The quantile of a log-probability. Read more
Source§

fn inv_digamma(self) -> Self

Computes the inverse of the digamma function on $(0, \infty)$: the x with $\psi(x) = y$. Read more
Source§

fn wright_omega(self) -> Self

Computes the Wright omega function, the $\omega > 0$ with $\omega + \ln \omega = x$. Read more
Source§

fn bessel_ratio<F>(self, nu: Self) -> Self

Computes the modified Bessel ratio $A_\nu(x) = I_\nu(x) / I_{\nu-1}(x)$ for nu >= 1, odd in x. Read more
Source§

fn inv_bessel_ratio<F>(self, nu: Self) -> Self

Computes the inverse of bessel_ratio: the concentration $\kappa$ with $I_\nu(\kappa)/I_{\nu-1}(\kappa) = r$, for 0 <= r < 1, odd in r. Read more
Source§

fn bessel_ratio_1m<F>(self, nu: Self) -> Self

Computes $1 - A_\nu(x)$, the complement of bessel_ratio, to full relative accuracy where the ratio itself is within an ulp of 1. Read more
Source§

fn inv_bessel_ratio_1m<F>(self, nu: Self) -> Self

Computes the inverse of bessel_ratio_1m: the concentration $\kappa$ with $1 - I_\nu(\kappa)/I_{\nu-1}(\kappa) = t$, for 0 < t <= 2 (t = 1 - r). Read more
Source§

fn gauss_legendre(self, n: u32) -> (Self, Self)

Computes the k-th node and weight of the n-point Gauss-Legendre quadrature rule on $[-1, 1]$, with the root index k taken per lane. Read more
Source§

fn gauss_hermite(self, n: u32) -> (Self, Self)

Computes the k-th node and weight of the n-point Gauss-Hermite rule, for $\int_{-\infty}^{\infty} f(x) e^{-x^2}\,dx \approx \sum_k w_k f(x_k)$, the root index k per lane (k = 0 the largest root, $x_{n-1-k} = -x_k$). Read more
Source§

fn gauss_laguerre(self, alpha: Self, n: u32) -> (Self, Self)

Computes the k-th node and weight of the n-point Gauss-Laguerre rule, for $\int_0^{\infty} f(x)\, x^\alpha e^{-x}\,dx \approx \sum_k w_k f(x_k)$, the root index k and alpha > -1 per lane (k = 0 the largest root). Read more
Source§

fn pochhammer(self, m: Self) -> Self

Computes the Pochhammer symbol $(z)_m = \dfrac{\Gamma(z+m)}{\Gamma(z)}$. Read more
Source§

fn jacobi_elliptic(self, k: Self) -> (Self, Self, Self)

Computes the Jacobi elliptic functions $(\mathrm{sn}, \mathrm{cn}, \mathrm{dn})$ at argument self and modulus k, all three from one evaluation. Read more
Source§

fn agm(self, other: Self) -> Self

Computes the arithmetic-geometric mean $\mathrm{AGM}(a, b)$ of two non-negative arguments. Read more
Source§

fn langevin(self) -> Self

Computes the Langevin function $L(x) = \coth x - \frac{1}{x}$. Read more
Source§

fn inv_langevin(self) -> Self

Computes the inverse Langevin function $L^{-1}(y)$ for |y| < 1. Read more
Source§

fn langevin_1m(self) -> Self

Computes 1 - L(x), the complement of the Langevin function, accurately where L(x) is within rounding of 1. Read more
Source§

fn inv_langevin_1m(self) -> Self

Computes L^-1(1 - t) from the complement t directly. Read more
Source§

fn gelu(self, alpha: Self) -> Self

GELU activation function, defined as $\tfrac{1}{2} x \left(1 + \operatorname{erf}\!\left(\frac{\alpha x}{\sqrt{2}}\right)\right)$, where alpha helps control the shape of the curve. The standard GELU function is recovered when alpha is 1. Read more
Source§

fn swish(self, beta: Self) -> Self

Swish activation function, defined as $x\,\sigma(\beta x) = \frac{x}{1 + e^{-\beta x}}$, where beta controls the sharpness of the gate. The standard Swish/SiLU function is recovered when beta is 1. As beta -> 0, the output approaches x/2 (half-identity); as beta -> inf, Swish approaches ReLU. Read more
Source§

fn algebraic_sigmoid_n<const N: usize>(self) -> Self

Computes the algebraic sigmoid function, defined as $\frac{x}{(1 + |x|^N)^{1/N}}$, where N is a positive integer parameter that controls the steepness of the curve. Read more
Source§

fn algebraic_sigmoid(self, n: u32) -> Self

The algebraic sigmoid for a degree known only at runtime. The runtime twin of algebraic_sigmoid_n, same arithmetic.
Source§

fn algebraic_swish(self) -> Self

Algebraic analogue of the Swish activation, defined as $x\left(\frac{1}{2} + \frac{x}{2\sqrt{1 + x^2}}\right)$. Equivalent to gating x by (1 + algebraic_sigmoid_n::<2>(x)) / 2, the [0, 1]-rescaled N=2 algebraic sigmoid. Read more
Source§

fn lgamma_r(self) -> (Self, Self)

Computes the natural log of the Gamma function ($\ln|\Gamma(x)|$) for any real input, for each value in a vector, and returns the sign of the Gamma function from before the absolute value was taken.
Source§

fn gaussian_integral(x0: Self, x1: Self, a: Self, c: Self) -> Self

Computes the definite integral of the Gaussian function from x0 to x1, with amplitude a and standard deviation c. This is more efficient than evaluating the indefinite integral at both limits and subtracting. Read more
Source§

fn boxcox(self, lambda: Self) -> Self

The Box-Cox transform of x = self with parameter lambda. Read more
Source§

fn boxcox_1p(self, lambda: Self) -> Self

The Box-Cox transform of $1 + x$, where x = self. Read more
Source§

fn inv_boxcox(self, lambda: Self) -> Self

The inverse Box-Cox transform of y = self with parameter lambda, undoing boxcox. Read more
Source§

fn inv_boxcox_1p(self, lambda: Self) -> Self

The inverse of boxcox_1p. Read more
Source§

fn yeo_johnson(self, lambda: Self) -> Self

The Yeo-Johnson transform of y = self with parameter lambda. Read more
Source§

fn inv_yeo_johnson(self, lambda: Self) -> Self

Source§

fn spherical_harmonics<const L: usize, const N: usize, const CS: bool>( x: Self, y: Self, z: Self, out: &mut [Self; N], )

Evaluates all real spherical harmonics through degree L at the unit direction (x, y, z), into out[l * (l + 1) + m] for m in -l..=l. Read more
Source§

fn spherical_harmonics_table<const L: usize, const N: usize, const CS: bool>( table: &mut ShTable<Self::Primal, N>, )

Builds the runtime coefficient table that spherical_harmonics_with and spherical_harmonics_d_with evaluate. Read more
Source§

fn spherical_harmonics_with<const L: usize, const N: usize>( table: &ShTable<Self::Primal, N>, x: Self, y: Self, z: Self, out: &mut [Self; N], )

Evaluates all harmonics through degree L from a prebuilt table. Read more
Source§

impl<E, V> RealSpecialMathWithPolicy for V

Source§

fn erfinv_p<P>(self) -> V
where P: Policy,

Computes the inverse error function.

Source§

fn probit_p<P>(self) -> V
where P: Policy,

Computes the Probit function, the inverse of the cumulative distribution function of the standard normal distribution.

Source§

fn ndtr_p<P>(self) -> V
where P: Policy,

Computes the cumulative distribution function of the standard normal distribution, the inverse of probit:

\Phi(x) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{x} e^{-t^2/2}\,dt
        = \tfrac12 \operatorname{erfc}\!\left(-\frac{x}{\sqrt 2}\right)

The probability that a standard normal variable falls below x: z-scores to p-values, the N(d_1)/N(d_2) terms of Black-Scholes, the probit link, and x * ndtr(x) is GELU. The name is Cephes/SciPy’s.

Underflows to zero below about x = -38.6 (f64) and -14.4 (f32). When the tail probability itself is the quantity of interest, use log_ndtr, which is finite there.

Source§

fn log_ndtr_p<P>(self) -> V
where P: Policy,

Computes $\ln \Phi(x)$, the logarithm of the standard normal CDF, finite for every finite x.

ln(ndtr(x)) is -inf below x ~ -38.6 in f64 (-14.4 in f32), exactly where a probit or censored-regression likelihood, a truncated-normal density, or an expected-improvement acquisition needs the tail: log_ndtr(-100) is an ordinary -5004.6. The kernel keeps $-x^2/2$ in the log domain and takes the rest from erfcx, which has no underflow, so the left tail carries full relative accuracy to the largest x whose square is representable. On the right it is ln_1p of the complement, so log_ndtr(10) = -7.6e-24 rather than a rounded zero.

Costs one erfcx, one ln_1p, and an exp for the lanes with x > 0.

Source§

fn logerfc_p<P>(self) -> V
where P: Policy,

Computes $\ln \operatorname{erfc}(x)$, finite for every finite x.

erfc underflows at x ~ 27 (f64) / 9.3 (f32) and its logarithm does not: logerfc(100) = -10004.8. This is the log-domain form of a Gaussian tail wherever erfc rather than the normal CDF is the natural quantity (Ewald sums, Gaussian-smeared edges, the Mills ratio in the log domain), and it is log_ndtr with x = -\sqrt 2 x'. Built on erfcx with $-x^2$ kept in the log domain. On the left, where erfc(x) is between 1 and 2, it is ln_1p(erf(|x|)), so the result stays accurate down to logerfc(-1e-20) = 1.13e-20.

Source§

fn fresnel_p<P>(self) -> (V, V)
where P: Policy,

The Fresnel integrals $S(x) = \int_0^x \sin(\pi t^2/2)\,dt$ and $C(x) = \int_0^x \cos(\pi t^2/2)\,dt$, together.

Returns (S, C), the same order as SciPy’s fresnel and this crate’s own sici.

Both are odd, both tend to 1/2, and both stay in [0.32, 0.72] past the first oscillation. Measured against a 45-digit oracle over x from 1e-4 to 1e15: 2.80 ulp (C) and 2.64 (S) in f64, 2.14 and 3.40 in f32 out to 1e7.

The phase $\pi x^2/2$ is carried in two words and reduced exactly, which is not a refinement but the whole of the large-argument accuracy: computed the obvious way as x*x*0.5, the phase is already 5.3e-6 wrong at x = 98765 and returns the wrong sign by $x \approx 10^9$, and since C and S are 1/2 plus a term of size $1/(\pi x)$ that error lands straight on the result. Below Average the residual is dropped and that behaviour returns.

Above x = 1.147e16 (f64) / 2.136e7 (f32) the oscillating correction is under half an ulp of 1/2, and both are exactly 1/2.

Source§

fn fresnel_c_p<P>(self) -> V
where P: Policy,

$C(x)$ alone. See fresnel.

Unlike airy::<Ai> this is not a cheaper evaluation by much: C and S share the argument reduction, the phase and both auxiliaries, so asking for one drops a single Chebyshev series and one reconstruction: roughly a third, not three quarters.

Source§

fn fresnel_s_p<P>(self) -> V
where P: Policy,

$S(x)$ alone. See fresnel_c.

Source§

fn sici_p<P>(self) -> (V, V)
where P: Policy,

The trigonometric integrals $\mathrm{Si}(x) = \int_0^x \frac{\sin t}{t}\,dt$ and $\mathrm{Ci}(x) = \gamma + \ln x + \int_0^x \frac{\cos t - 1}{t}\,dt$, together. Returns (Si, Ci).

Si is odd. Ci is real only on the positive axis ($\mathrm{Ci}(-x) = \mathrm{Ci}(x) + i\pi$), so this returns Ci(|x|), dropping the imaginary part, which is what SciPy’s sici does. Ci(0) is $-\infty$.

Measured 2.03 ulp (Si) and 1.42 (Ci, against its envelope) in f64 over x from 1e-4 to 1e15. In f32, 1.34 and 1.99.

Two things worth knowing before relying on Ci:

  • It has zeros, the first near x = 0.6165, and no algorithm is relatively accurate at one. The accuracy above is relative to $\lvert\gamma + \ln x\rvert + \lvert\mathrm{Cin}\rvert$ below the crossover and to the $1/x$ envelope above it.
  • Its large-argument accuracy is sin_cos’s: for Ci the oscillation is the value, so a phase error is a relative error, and full argument reduction is a Best-tier property. Si is insulated, tending to $\pi/2$ with the oscillation only a $1/x$ correction, and is $\pi/2$ exactly above x = 1.147e16 (f64) / 2.136e7 (f32). Ci has no such cutoff: it decays like $1/x$ and stays representable for every finite x.
Source§

fn sinint_p<P>(self) -> V
where P: Policy,

$\mathrm{Si}(x)$ alone. See sici, and fresnel_c for what a single accessor saves.

Source§

fn cosint_p<P>(self) -> V
where P: Policy,

$\mathrm{Ci}(x)$ alone. See sici.

Source§

fn inv_log_ndtr_p<P>(self) -> V
where P: Policy,

Computes the inverse of log_ndtr: the x with $\ln \Phi(x) = y$, for y <= 0. The quantile of a log-probability.

probit of $e^y$ stops working once $e^y$ underflows (y < -745 in f64), which is exactly where a log-likelihood, a truncated-normal EM step or an extreme-value fit needs the quantile. This inverts log_ndtr directly, by Newton with the inverse Mills ratio as the derivative, from a probit(e^y) seed one precision tier down where that exists and from the tail asymptotic below. Within a few ulp of the true inverse of the given y over the whole domain. y = 0 gives +inf, y = -inf gives -inf, and y > 0 is NaN.

Source§

fn inv_digamma_p<P>(self) -> V
where P: Policy,

Computes the inverse of the digamma function on $(0, \infty)$: the x with $\psi(x) = y$.

The maximum-likelihood estimate of a gamma shape or a Dirichlet concentration is this function of a mean log. Newton on digamma with trigamma from Minka’s seed ($e^y + 1/2$ above y = -2.22, $-1/(y + \gamma)$ below). Above y = 6 the Stirling series is solved for x directly, since there Newton on digamma cannot see past digamma’s own rounding. +inf maps to +inf and -inf to 0.

Source§

fn wright_omega_p<P>(self) -> V
where P: Policy,

Computes the Wright omega function, the $\omega > 0$ with $\omega + \ln \omega = x$.

This is $W_0(e^x)$, the principal Lambert W of an exponential, evaluated without forming $e^x$: $W_0(e^x)$ overflows past x = 709 where $\omega(x) \approx x - \ln x$ is ordinary. Newton on $\omega + \ln \omega - x$ from a cheap seed per region. Below x = -7 the Lagrange series in $e^x$ is the answer outright.

Source§

fn bessel_ratio_p<P, F>(self, nu: V) -> V

Computes the modified Bessel ratio $A_\nu(x) = I_\nu(x) / I_{\nu-1}(x)$ for nu >= 1, odd in x.

With $p = 2\nu$ this is the mean resultant length of a von Mises-Fisher distribution on $S^{p-1}$ at concentration x. nu = 1 is the von Mises circle $I_1/I_0$, and nu = 3/2 is the langevin function. Never forms the two Bessel functions where they would underflow: a series pair for small x, the continued fraction for the ratio in the middle, and the scaled quotient only where x dominates the order. The order is a plain vector, but whole and half-integer orders reach their fast Bessel kernels through the order simplifier.

Source§

fn inv_bessel_ratio_p<P, F>(self, nu: V) -> V

Computes the inverse of bessel_ratio: the concentration $\kappa$ with $I_\nu(\kappa)/I_{\nu-1}(\kappa) = r$, for 0 <= r < 1, odd in r.

The maximum-likelihood concentration of a von Mises-Fisher distribution from its observed mean resultant length, in any dimension $p = 2\nu$. Banerjee’s $r(p - r^2)/(1 - r^2)$ seeds a Newton whose derivative is the closed form $1 - A^2 - (2\nu - 1)A/\kappa$, so each step is one ratio evaluation. r = 1 gives +inf, r > 1 NaN.

As r -> 1 the problem itself is ill-conditioned: $\kappa \sim (p-1)/(2(1-r))$, and an ulp of r is a relative $2\kappa\epsilon/(p-1)$ of $\kappa$. The result is the exact inverse of the given r to that extent.

Source§

fn bessel_ratio_1m_p<P, F>(self, nu: V) -> V

Computes $1 - A_\nu(x)$, the complement of bessel_ratio, to full relative accuracy where the ratio itself is within an ulp of 1.

1 - bessel::ratio::<I>(x) is gone once $A$ rounds to 1 (x past 1e16 (p-1)/2), and is only accurate to $\epsilon/(1 - A)$ before that. This evaluates the complement directly for x >= 8 nu, from the Hankel expansions at a reduced order and the ratio recurrence walked upward in complement form. $A$ is odd, so $1 - A(-x) = 2 - (1 - A(x))$.

Source§

fn inv_bessel_ratio_1m_p<P, F>(self, nu: V) -> V

Computes the inverse of bessel_ratio_1m: the concentration $\kappa$ with $1 - I_\nu(\kappa)/I_{\nu-1}(\kappa) = t$, for 0 < t <= 2 (t = 1 - r).

The complement form of inv_bessel_ratio for nearly concentrated data: $\kappa \sim (p-1)/(2t)$ as t -> 0. This form keeps full relative accuracy there instead of losing $2\kappa\epsilon/(p-1)$ to the rounding of r. It is the inv_langevin_1m move in every dimension. t = 0 gives +inf. t in (1, 2] is a negative r and returns the mirrored $\kappa$.

Source§

fn gauss_legendre_p<P>(self, n: u32) -> (V, V)
where P: Policy,

Computes the k-th node and weight of the n-point Gauss-Legendre quadrature rule on $[-1, 1]$, with the root index k taken per lane.

The rule integrates every polynomial through degree $2n - 1$ exactly: $\int_{-1}^{1} f \approx \sum_k w_k f(x_k)$, $x_k$ the roots of $P_n$ in descending order (k = 0 is the largest, $x_{n-1-k} = -x_k$) and $w_k = 2 / ((1 - x_k^2) P_n'(x_k)^2)$. The packet is the rule: sweep k over 0..n in packets of consecutive indices and store the two vectors. Every lane runs the same O(n) recurrence, so a packet of roots costs one root.

Tricomi’s $\cos(\pi(k + 3/4)/(n + 1/2))$ seeds a Newton on $P_n$ from the recurrence, and nodes land within a few $\epsilon$ absolute. A non-integer or out-of-range k gives NaN in both.

let n = 16;
for base in (0..n).step_by(V::LANES) {
    let k = V::from_array(core::array::from_fn(|i| (base + i) as f64));
    let (x, w) = k.gauss_legendre(n as u32); // lanes past n - 1 are NaN
}
Source§

fn gauss_hermite_p<P>(self, n: u32) -> (V, V)
where P: Policy,

Computes the k-th node and weight of the n-point Gauss-Hermite rule, for $\int_{-\infty}^{\infty} f(x) e^{-x^2}\,dx \approx \sum_k w_k f(x_k)$, the root index k per lane (k = 0 the largest root, $x_{n-1-k} = -x_k$).

Same shape as gauss_legendre: a packet of consecutive indices is the rule. Seeded from the WKB phase of the Hermite equation and finished by Newton on $H_n/n!$, whose recurrence stays in range where the raw $H_n$ overflows at degree 48. The weights are the unscaled ones, which reach $e^{-x_k^2}$ at the outer nodes. The scalar factor in them underflows past n = 170 in f64 and n = 40 in f32, which bounds the rule.

Source§

fn gauss_laguerre_p<P>(self, alpha: V, n: u32) -> (V, V)
where P: Policy,

Computes the k-th node and weight of the n-point Gauss-Laguerre rule, for $\int_0^{\infty} f(x)\, x^\alpha e^{-x}\,dx \approx \sum_k w_k f(x_k)$, the root index k and alpha > -1 per lane (k = 0 the largest root).

Same shape as gauss_legendre. Seeded from the WKB phase of the Laguerre equation, whose phase count between the turning points carries the Bessel-zero offset on the left and the Airy offset on the right, and finished by Newton on the raw $L_n^\alpha$ with Hildebrand’s weight $\Gamma(n+\alpha+1)/(n!\,x_k\,L_n^{\alpha\prime}(x_k)^2)$. Unscaled weights, which reach $e^{-x_k}$ at the outer nodes. $L_{n-1}$ at the largest root grows like $e^{x/2}$, which bounds the rule near n = 170 in f64 and n = 20 in f32.

Source§

fn pochhammer_p<P>(self, m: V) -> V
where P: Policy,

Computes the Pochhammer symbol $(z)_m = \dfrac{\Gamma(z+m)}{\Gamma(z)}$.

Combinatorics calls this the rising factorial, and for a non-negative integer m it is exactly the ascending product $z(z+1)\cdots(z+m-1)$. The name here is the special-function one because the function is not restricted to integers: m is any real, which is what the hypergeometric series need and what “factorial” would misdescribe.

Note that the notation $(z)_m$ is ambiguous in the literature: it means the rising factorial in special functions and the falling factorial through much of combinatorics and statistics. This function is the rising one. The falling factorial is pochhammer(z - n + 1, n), and the two are related by $z^{(\bar n)} = (-1)^n (-z)^{(\underline n)}$. Neither is shipped separately, being an argument transform away.

§Accuracy

The obvious spelling exp(lgamma(z+m) - lgamma(z)) cancels catastrophically whenever m is small beside z: at z = 1e8, m = 1e-4 it has no correct digits. This does not use it.

At Average precision and above (which includes the default policy), integer m up to 20 in absolute value takes an exact product, 0.00 ulp median and 4.2 worst. That path also covers negative z and returns exact zeros at the poles: $(-2)_3$ is 0.

Below Average it is compiled out and integer m goes through the Stirling difference like anything else, which measures 4.2 ulp median and 172 worst. The difference that shows is the exactness rather than the ulp count: $(3)_1$ comes back as 3.0000000000000018 there, and $(200)_2$ as 40200.00000000002.

Any other m with z and z+m both positive takes a Stirling difference arranged so nothing large is ever subtracted from anything large. Its error is the floor for anything exponentiating a logarithm, tracking $|\ln (z)_m|\cdot\epsilon$. Over 6924 measured points with z in [0.1, 8.9] that is a median of 2.6 ulp and a 99th percentile of 25. Individual points scale with the result’s own logarithm, reaching 259 ulp where the value is near 1e163, and falling to nothing as the result approaches 1.

A non-integer m with z or z+m non-positive (a ratio taken across Gamma’s poles) has no cheap rearrangement and does fall back to the logarithmic form, inheriting its cancellation.

Source§

fn jacobi_elliptic_p<P>(self, k: V) -> (V, V, V)
where P: Policy,

Computes the Jacobi elliptic functions $(\mathrm{sn}, \mathrm{cn}, \mathrm{dn})$ at argument self and modulus k, all three from one evaluation.

All three are made from a single angle, the amplitude $\varphi = \mathrm{am}(u, k)$, defined by $F(\varphi, k) = u$, so this function inverts the incomplete integral of the first kind that ellint evaluates:

\mathrm{sn}(u, k) = \sin\varphi, \qquad
\mathrm{cn}(u, k) = \cos\varphi, \qquad
\mathrm{dn}(u, k) = \sqrt{1 - k^2 \sin^2\varphi}

Hence their names: sine amplitude, cosine amplitude and delta amplitude. At k = 0 the amplitude is u and they collapse to $(\sin u, \cos u, 1)$. At k = 1 they stop being periodic and become $(\tanh u, \operatorname{sech} u, \operatorname{sech} u)$.

§Why one function and not three

The triple is closed under differentiation in u, each derivative a product of the other two:

\frac{d\,\mathrm{sn}}{du} = \mathrm{cn}\,\mathrm{dn}, \qquad
\frac{d\,\mathrm{cn}}{du} = -\mathrm{sn}\,\mathrm{dn}, \qquad
\frac{d\,\mathrm{dn}}{du} = -k^2\,\mathrm{sn}\,\mathrm{cn}

so they are one object the way $(\sin, \cos)$ are, and Dual differentiates them without touching the iteration underneath. It also costs nothing to return all three: they share the entire computation, and only the last few operations differ.

The other nine Jacobi functions in Glaisher’s notation (ns, nc, nd, sc, sd, cs, cd, ds, dc) are reciprocals and ratios of these three, so this gives all twelve.

§Domain and accuracy

Only $k^2$ enters, so the sign of k does not matter. |k| > 1 is out of domain and gives NaN. Worst absolute error measured against mpmath at 40 digits over |u| <= 8 and k in [0, 1) is 8.3 eps for sn, 4.1 for cn and 3.8 for dn. Absolute is the meaningful metric: all three are bounded by 1 and all three have zeros, so relative accuracy at a zero depends on how well that zero’s location is known, exactly as for sin. For the same reason accuracy falls off slowly with |u|, that being the argument of the single trigonometric call inside.

Source§

fn agm_p<P>(self, other: V) -> V
where P: Policy,

Computes the arithmetic-geometric mean $\mathrm{AGM}(a, b)$ of two non-negative arguments.

Iterating $a \mapsto (a + b)/2$ against $b \mapsto \sqrt{ab}$ drives the two sequences to a common limit, quadratically: the pair closes to within a factor of a few in a handful of passes from any starting ratio, and the correct digits then double per pass. The loop is branchless and costs one sqrt per iteration, with no transcendentals anywhere, which is why it is also the engine behind the complete elliptic integrals, $K(k) = \pi / (2\,\mathrm{AGM}(1, k'))$, reached through ellint rather than by calling this directly.

Symmetric in its arguments and homogeneous, $\mathrm{AGM}(ca, cb) = c\,\mathrm{AGM}(a, b)$. AGM(a, 0) is 0 and AGM(inf, b) is inf. A negative argument is outside the domain (the geometric mean’s sign becomes ambiguous after the first pass) and returns NaN under overflow checking, as does a zero paired with an infinity.

The geometric mean is formed as one product, so two arguments both above $\sqrt{\text{MAX}}$ (about 1.3e154 in f64, 1.8e19 in f32) overflow to infinity even where the mean is representable. Scale both by a common power of two first if that range matters. Homogeneity makes it exact.

Source§

fn langevin_p<P>(self) -> V
where P: Policy,

Computes the Langevin function $L(x) = \coth x - \frac{1}{x}$.

Odd, strictly increasing, L(0) = 0, L'(0) = 1/3, L(x) -> 1 as x -> ∞. This is the mean resultant length $A_3(\kappa)$ of a von Mises-Fisher distribution on the sphere, and the freely-jointed-chain force-extension law in polymer physics.

Evaluated as an odd minimax polynomial for |x| <= 2 (the direct form coth x - 1/x cancels catastrophically there, losing 3u/x^2), and as 1 - 1/x + 2/(e^{2x} - 1) beyond. Both branches are accurate to a few ulp at every precision policy. The policy mainly selects the exp.

To also obtain the derivative L'(x), use langevin_d.

Source§

fn inv_langevin_p<P>(self) -> V
where P: Policy,

Computes the inverse Langevin function $L^{-1}(y)$ for |y| < 1.

Odd, with a simple pole at y = 1: L^-1(y) ~ 1/(1-y). |y| = 1 returns ±∞, and |y| > 1 returns NaN under overflow checking (an unspecified value otherwise). Its condition number is 1/(1-y), so near the pole the result cannot be more accurate than that, however exact the arithmetic. A consumer that knows 1 - y should form it before rounding.

A rational seed (the same family as Cohen’s Pade approximant, which the vMF literature knows as the Banerjee et al. concentration estimator) is refined by Newton (f32) or Halley (f64) steps whose count follows the precision policy:

precisionstepsrelative error
Worst0~2e-5
Medium, Average, Best1full (a few ulp)
Reference2full
Source§

fn langevin_1m_p<P>(self) -> V
where P: Policy,

Computes 1 - L(x), the complement of the Langevin function, accurately where L(x) is within rounding of 1.

1 - L(x) ~ 1/x, so once x > 1/u (sharpness ~1e7 in f32, ~1e16 in f64) langevin(x) rounds to exactly 1 and its complement is gone. This returns it to full relative precision at any x, from the same intermediates. Same cost as langevin. Negative x gives 1 + L(|x|).

Pairs with inv_langevin_1m: the vMF convolution kappa' = L^-1(L(k1) L(k2)) should be formed as inv_langevin_1m(a + b - a*b) with a = langevin_1m(k1), b = langevin_1m(k2), which is cancellation-free at every sharpness.

Source§

fn inv_langevin_1m_p<P>(self) -> V
where P: Policy,

Computes L^-1(1 - t) from the complement t directly.

The inverse Langevin function has a pole at y = 1 and a condition number of 1/(1-y), so a caller that knows 1 - y (see langevin_1m) should pass it here rather than form y and lose its low digits: this entry point works in t throughout and is accurate to a few ulp at any sharpness. t = 0 returns +∞, t > 1 gives the negative branch, and t < 0 is out of the domain (NaN under overflow checking). Same cost as inv_langevin.

Source§

fn gelu_p<P>(self, alpha: V) -> V
where P: Policy,

GELU activation function, defined as $\tfrac{1}{2} x \left(1 + \operatorname{erf}\!\left(\frac{\alpha x}{\sqrt{2}}\right)\right)$, where alpha helps control the shape of the curve. The standard GELU function is recovered when alpha is 1.

For f32 vectors, this remains decently accurate even with the Medium and Worst precision policies, thanks to good erf implementations at the various precision levels. See erf for more details.

To also obtain the derivative with respect to x (which shares most of the computation), use gelu_d.

Source§

fn swish_p<P>(self, beta: V) -> V
where P: Policy,

Swish activation function, defined as $x\,\sigma(\beta x) = \frac{x}{1 + e^{-\beta x}}$, where beta controls the sharpness of the gate. The standard Swish/SiLU function is recovered when beta is 1. As beta -> 0, the output approaches x/2 (half-identity); as beta -> inf, Swish approaches ReLU.

To also obtain the derivative with respect to x, use swish_d.

Source§

fn algebraic_sigmoid_n_p<P, const N: usize>(self) -> V
where P: Policy,

Computes the algebraic sigmoid function, defined as $\frac{x}{(1 + |x|^N)^{1/N}}$, where N is a positive integer parameter that controls the steepness of the curve.

This also has the unique behavior where for N=0, the function is just the identity function, and for N=1 it is the softsign function.

Note: This function uses $|x|^N$ (the real absolute value), so it is non-holomorphic and only meaningful for real-valued inputs.

To also obtain the derivative with respect to x, use algebraic_sigmoid_d.

Source§

fn algebraic_sigmoid_p<P>(self, n: u32) -> V
where P: Policy,

The algebraic sigmoid for a degree known only at runtime. The runtime twin of algebraic_sigmoid_n, same arithmetic.

Source§

fn algebraic_swish_p<P>(self) -> V
where P: Policy,

Algebraic analogue of the Swish activation, defined as $x\left(\frac{1}{2} + \frac{x}{2\sqrt{1 + x^2}}\right)$. Equivalent to gating x by (1 + algebraic_sigmoid_n::<2>(x)) / 2, the [0, 1]-rescaled N=2 algebraic sigmoid.

Like standard Swish/SiLU, this is smooth and non-monotonic (it dips slightly below zero for moderately negative x before rising) and shares the same asymptotes (f(x) -> x as x -> ∞, f(x) -> 0 as x -> -∞). Unlike Swish, it requires no exp or log, which is substantially cheaper on hardware without fast transcendentals.

To also obtain the derivative with respect to x (which shares most of the underlying computation, notably $1/\sqrt{1 + x^2}$), use algebraic_swish_d.

§Historical note

Algebraic gating functions of this form are effectively unknown in modern deep learning, which standardized on exp-based activations (sigmoid, Swish/SiLU, GELU) once GPUs made exp essentially free, a single-cycle special-function-unit op on most modern hardware. On CPUs the calculus is different: a vectorized exp still costs ~20+ cycles even with good polynomial approximations, while sqrt/rsqrt are cheap hardware ops (often approximated in 4-7 cycles). For CPU-side inference, training on CPU, or embedded targets without a transcendental SFU, this remains a competitive Swish-shaped activation at a fraction of the cost.

Source§

fn lgamma_r_p<P>(self) -> (V, V)
where P: Policy,

Computes the natural log of the Gamma function ($\ln|\Gamma(x)|$) for any real input, for each value in a vector, and returns the sign of the Gamma function from before the absolute value was taken.

Source§

fn gaussian_integral_p<P>(x0: V, x1: V, a: V, c: V) -> V
where P: Policy,

Computes the definite integral of the Gaussian function from x0 to x1, with amplitude a and standard deviation c. This is more efficient than evaluating the indefinite integral at both limits and subtracting.

The position b is assumed to be zero, so offset the limits accordingly for a non-zero position.

Source§

fn boxcox_p<P>(self, lambda: V) -> V
where P: Policy,

The Box-Cox transform of x = self with parameter lambda.

\mathrm{boxcox}(x, \lambda) = \begin{cases} \dfrac{x^\lambda - 1}{\lambda} & \lambda \ne 0 \\[6pt] \ln x & \lambda = 0\end{cases}

The variance-stabilizing power transform of applied statistics: $\lambda$ is fitted to make skewed data as close to normal as possible before a model sees it, and the family interpolates the transforms people otherwise pick by hand: $\lambda = 1$ leaves the data alone up to a shift, $1/2$ is a square root, $0$ a logarithm, $-1$ a reciprocal. A fixture of statistical software since Box and Cox introduced it in 1964.

The two cases are one function: $\ln x$ is the limit as $\lambda \to 0$, not a separate rule. Written out, $(x^\lambda - 1)/\lambda$ is $0/0$ there, and the trouble is not confined to the point. Computing $x^\lambda$ and subtracting one cancels, so the naive form is already wrong in the fifth digit at $\lambda = 10^{-12}$ and returns a flat zero by $10^{-300}$. That matters because a fitting routine searches $\lambda$ near zero, which is the usual answer for right-skewed data.

Evaluated as powf_m1(x, lambda)/lambda, which forms $x^\lambda - 1$ without ever forming $x^\lambda$, so there is nothing to cancel and no series or crossover is needed. Measured against a 60-digit oracle, it holds a few ulp from $\lambda = 10^{-300}$ to $\lambda = \pm 8$. Only the exact $\lambda = 0$ is selected apart.

Domain is $x > 0$, and a negative x gives NaN. At $x = 0$ the limits are taken: $-1/\lambda$ for $\lambda > 0$ and $-\infty$ otherwise, which is the conventional choice. That needs no special case: powf_m1(0, lambda) is $-1$ above zero and $+\infty$ below, and the division does the rest.

Source§

fn boxcox_1p_p<P>(self, lambda: V) -> V
where P: Policy,

The Box-Cox transform of $1 + x$, where x = self.

\mathrm{boxcox1p}(x, \lambda) = \begin{cases} \dfrac{(1 + x)^\lambda - 1}{\lambda} & \lambda \ne 0 \\[6pt] \ln (1 + x) & \lambda = 0\end{cases}

The shifted form exists for the same reason ln_1p does: when x is small, $1 + x$ rounds it away, and every digit of the answer with it. Calling boxcox(1 + x, lambda) loses x entirely once $|x| < \varepsilon$, where this returns $\lambda x$ to full precision. Built on compound_m1, which forms $(1 + x)^\lambda - 1$ without forming either $1 + x$ or $(1+x)^\lambda$.

This is also the kernel underneath yeo_johnson, whose argument is data centered near zero by construction.

Domain is $x > -1$; below that the result is NaN. At $x = -1$ the limits are $-1/\lambda$ for $\lambda > 0$ and $-\infty$ otherwise.

Source§

fn inv_boxcox_p<P>(self, lambda: V) -> V
where P: Policy,

The inverse Box-Cox transform of y = self with parameter lambda, undoing boxcox.

\mathrm{boxcox}^{-1}(y, \lambda) = \begin{cases} (\lambda y + 1)^{1/\lambda} & \lambda \ne 0 \\[6pt] e^y & \lambda = 0\end{cases}

Wanted by anyone who uses the forward transform: a model fitted on transformed data predicts in transformed units, and the prediction has to come back.

Evaluated as $\exp\!\left(\ln(1 + \lambda y)/\lambda\right)$ rather than as a literal power, which is not merely a rearrangement. The whole point of boxcox is that it stays accurate as $\lambda \to 0$, and $\lambda$ fitted near zero is the common case. There $\lambda y$ is tiny, so forming $\lambda y + 1$ and raising it to the power $1/\lambda$ throws away exactly the digits the forward transform took care to keep. Through ln_1p the exponent tends smoothly to y, so the $\lambda = 0$ case is the limit rather than a discontinuity, and only the exact zero is selected apart.

The range of the forward transform is $\lambda y + 1 > 0$. Outside it the result is NaN, and on the boundary it is $0$ for $\lambda > 0$ and $+\infty$ below.

Source§

fn inv_boxcox_1p_p<P>(self, lambda: V) -> V
where P: Policy,

The inverse of boxcox_1p.

\mathrm{boxcox1p}^{-1}(y, \lambda) = \begin{cases} (\lambda y + 1)^{1/\lambda} - 1 & \lambda \ne 0 \\[6pt] e^y - 1 & \lambda = 0\end{cases}

The same exponent as inv_boxcox with expm1 outside it instead of exp, so a result near zero keeps its relative accuracy, which, this being the inverse of a transform applied to data centered near zero, is the ordinary case rather than an edge one. Also the kernel underneath inv_yeo_johnson.

Source§

fn yeo_johnson_p<P>(self, lambda: V) -> V
where P: Policy,

The Yeo-Johnson transform of y = self with parameter lambda.

\psi(y, \lambda) = \begin{cases}
  \dfrac{(y + 1)^\lambda - 1}{\lambda} & y \ge 0,\ \lambda \ne 0 \\[6pt]
  \ln(y + 1) & y \ge 0,\ \lambda = 0 \\[6pt]
  -\dfrac{(1 - y)^{2 - \lambda} - 1}{2 - \lambda} & y < 0,\ \lambda \ne 2 \\[6pt]
  -\ln(1 - y) & y < 0,\ \lambda = 2
\end{cases}

Box-Cox’s sibling, and the one that gets used more, since it is defined on the whole real line rather than on $x > 0$. Same job (fit $\lambda$ by maximum likelihood to make skewed data as close to normal as a power transform can) without the “add a constant to make everything positive first” step, which is an arbitrary choice that changes the fitted $\lambda$. Introduced by Yeo and Johnson in 2000.

§One kernel, not four

The four cases are one function seen twice. The $y < 0$ branch is the $y \ge 0$ branch applied to $|y|$ with $\lambda$ reflected to $2 - \lambda$ and the result negated, which is what makes $\psi$ smooth in $\lambda$ across $y = 0$ in the first place. Folding the sign out first therefore collapses the two logarithmic special cases ($\lambda = 0$ above zero, $\lambda = 2$ below) into the single seam that boxcox_1p already handles, and the whole transform is $\pm\,\mathrm{boxcox1p}(|y|, \lambda\ \mathrm{or}\ 2 - \lambda)$.

That the kernel is the 1p form and not boxcox applied to $1 + |y|$ matters here more than anywhere else. $\psi(y, \lambda) \approx y$ near the origin for every $\lambda$, and the origin is where the data is: the transform’s reason for existing is samples that straddle zero. Forming $1 + |y|$ would round away everything below $\varepsilon$ and return a flat zero there.

The value is finite for every finite y, so there is nothing to guard: the two domain edges of the kernel are at $|y| = -1$, which the fold never reaches.

Source§

fn inv_yeo_johnson_p<P>(self, lambda: V) -> V
where P: Policy,

The inverse Yeo-Johnson transform, undoing yeo_johnson.

\psi^{-1}(z, \lambda) = \begin{cases}
  (\lambda z + 1)^{1/\lambda} - 1 & z \ge 0,\ \lambda \ne 0 \\[6pt]
  e^z - 1 & z \ge 0,\ \lambda = 0 \\[6pt]
  1 - \left((\lambda - 2) z + 1\right)^{1/(2 - \lambda)} & z < 0,\ \lambda \ne 2 \\[6pt]
  1 - e^{-z} & z < 0,\ \lambda = 2
\end{cases}

The same sign fold as the forward transform, over inv_boxcox_1p. $\psi$ is increasing and fixes the origin, so the branch on the way back is the sign of the transformed value, which is the sign of y.

Unlike the forward direction this one has a range to respect: for $\lambda > 0$ the transform’s image is bounded below by $-1/\lambda$, and a z past that came from no y. Such an input gives NaN rather than a plausible-looking number.

Source§

fn spherical_harmonics_p<P, const L: usize, const N: usize, const CS: bool>( x: V, y: V, z: V, out: &mut [V; N], )
where P: Policy,

Evaluates all real spherical harmonics through degree L at the unit direction (x, y, z), into out[l * (l + 1) + m] for m in -l..=l.

Orthonormal real harmonics. Evaluation is pure polynomial arithmetic: no trigonometry, no division, O(L^2) FMAs total, exact zeros for every m != 0 harmonic at the poles, fully unrolled at compile time for each L up to MAX_SH_DEGREE (above that it takes the rolled general path, which is correct at any degree but roughly 10x slower).

CS picks the phase convention. false gives the standard real-SH tables ($Y_{11} = \sqrt{3/4\pi}\,x$); true applies the Condon-Shortley $(-1)^{|m|}$ phase, negating every odd-|m| harmonic to match Sloan’s SHEval and the physics convention ($Y_{11} = -\sqrt{3/4\pi}\,x$). The choice is baked into a constant table, so neither costs an instruction, but mixing the two silently corrupts any projection/reconstruction round-trip, which is why it must be named.

N must equal (L + 1)^2 (compile-time checked). The direction is assumed unit-length, and nothing renormalizes. See sh_impl for the full convention, algorithm, and domain notes.

use thermite::prelude::*;
use thermite_special::RealSpecialMath;

type V = Vector<f64>;
let (x, y, z) = (V::splat(0.6), V::splat(0.0), V::splat(0.8));

let mut sh = [V::ZERO; 9];
V::spherical_harmonics::<2, 9, false>(x, y, z, &mut sh);
// Y(1,1) = sqrt(3/4pi) * x
assert!((sh[3].extract::<0>() - 0.48860251190292 * 0.6).abs() < 1e-14);

// Condon-Shortley negates odd |m|, and agrees on even |m|.
let mut cs = [V::ZERO; 9];
V::spherical_harmonics::<2, 9, true>(x, y, z, &mut cs);
assert_eq!(cs[3].extract::<0>(), -sh[3].extract::<0>());
assert_eq!(cs[8].extract::<0>(), sh[8].extract::<0>());
Source§

fn spherical_harmonics_table_p<P, const L: usize, const N: usize, const CS: bool>( table: &mut ShTable<<V as PrimalProjection>::Primal, N>, )
where P: Policy,

Builds the runtime coefficient table that spherical_harmonics_with and spherical_harmonics_d_with evaluate.

The table depends only on L and CS, never on the direction, so a caller sweeping many directions should build it once rather than calling the one-shot spherical_harmonics per direction. The phase is baked in here, which is why the evaluators take no CS.

The table is typed by Self::Primal, the unaugmented value type: the recurrence coefficients are constants, so a Dual’s derivative parts and a Complex’s imaginary part would only store zeros. For plain vectors and Compensated the primal is Self and nothing changes. For Dual the table is a fraction of the size and its entries multiply as reals.

use thermite::prelude::*;
use thermite_special::{RealSpecialMath, ShTable};

type V = Vector<f64>;
const L: usize = 3;
const N: usize = (L + 1) * (L + 1);

let mut table = ShTable::<V, N>::zeroed();
V::spherical_harmonics_table::<L, N, false>(&mut table);

let mut sh = [V::ZERO; N];
for &(x, y, z) in &[(1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] {
    V::spherical_harmonics_with::<L, N>(
        &table, V::splat(x), V::splat(y), V::splat(z), &mut sh,
    );
}
assert!((sh[1].extract::<0>() - 0.48860251190292).abs() < 1e-14);
Source§

fn spherical_harmonics_with_p<P, const L: usize, const N: usize>( table: &ShTable<<V as PrimalProjection>::Primal, N>, x: V, y: V, z: V, out: &mut [V; N], )
where P: Policy,

Evaluates all harmonics through degree L from a prebuilt table.

The table holds Self::Primal coefficients. See spherical_harmonics_table for how to build it and why, and spherical_harmonics for the conventions and layout.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<M> SpatialMath for M

Source§

fn hypot(self, other: Self) -> Self

Computes the Euclidean norm (hypotenuse) of self and other, i.e., sqrt(self^2 + other^2). Read more
Source§

fn hypot_n<const N: usize>(values: [Self; N]) -> Self

Computes the Euclidean norm (hypotenuse) of N values, i.e., $\sqrt{x_1^2 + x_2^2 + \dots + x_N^2}$. Read more
Source§

fn inv_hypot_n<const N: usize>(values: [Self; N]) -> Self

Computes the inverse Euclidean norm (inverse hypotenuse) of N values, i.e., $1/\sqrt{x_1^2 + x_2^2 + \dots + x_N^2}$. Read more
Source§

fn hypot_s(values: &[Self]) -> Self

hypot_n over a runtime-length slice. Read more
Source§

fn inv_hypot(values: &[Self]) -> Self

inv_hypot_n over a runtime-length slice. Read more
Source§

fn l1_norm(self) -> Self

L1 Norm, or the “Manhattan” distance from the origin. Read more
Source§

fn l2_norm(self) -> Self

L2 Norm, or the “Euclidean” distance from the origin. Read more
Source§

fn l2_norm_squared(self) -> Self

Squared L2 Norm, or the squared “Euclidean” distance from the origin. Read more
Source§

impl<E, V> SpatialMathWithPolicy for V

Source§

fn hypot_p<P>(self, other: V) -> V
where P: Policy,

Computes the Euclidean norm (hypotenuse) of self and other, i.e., sqrt(self^2 + other^2).

This is not higher performance than the naive implementation, but is more resistant to overflow and underflow. If using the worst precision policy, it becomes equivalent to the naive implementation.

Check out hypot_n for N values known at compile time, and hypot_s for a runtime-length slice.

Source§

fn hypot_n_p<P, const N: usize>(values: [V; N]) -> V
where P: Policy,

Computes the Euclidean norm (hypotenuse) of N values, i.e., $\sqrt{x_1^2 + x_2^2 + \dots + x_N^2}$.

This is typically higher performance than naively computing the sum of squares and then taking the square root, especially for larger N, and is more resistant to overflow and underflow when using average or higher precision policies.

N = 2 is written out as its own arm in every lowering, so hypot is this function at that length rather than a separate kernel.

Source§

fn inv_hypot_n_p<P, const N: usize>(values: [V; N]) -> V
where P: Policy,

Computes the inverse Euclidean norm (inverse hypotenuse) of N values, i.e., $1/\sqrt{x_1^2 + x_2^2 + \dots + x_N^2}$.

This is typically higher performance than naively computing the sum of squares, taking the square root, and then inverting, especially for larger N, and is more resistant to overflow and underflow when using average or higher precision policies.

At lower precision policies, we can take advantage of fast approximate inverse square root implementations for better performance.

Source§

fn hypot_s_p<P>(values: &[V]) -> V
where P: Policy,

hypot_n over a runtime-length slice.

Same scaling and the same range safety. The length simply is not a constant, so the two passes cannot unroll and the N = 1/N = 2 shortcuts are runtime branches. If you know the count at compile time, prefer hypot_n.

The norm of no values is 0.

Source§

fn inv_hypot_p<P>(values: &[V]) -> V
where P: Policy,

inv_hypot_n over a runtime-length slice.

Same trade as hypot_s. The inverse norm of no values is infinity, matching 1/0.

Source§

fn l1_norm_p<P>(self) -> V
where P: Policy,

L1 Norm, or the “Manhattan” distance from the origin.

For 1D vectors, this is equivalent to the absolute value.

Source§

fn l2_norm_p<P>(self) -> V
where P: Policy,

L2 Norm, or the “Euclidean” distance from the origin.

For 1D vectors, this is equivalent to the absolute value.

Source§

fn l2_norm_squared_p<P>(self) -> V
where P: Policy,

Squared L2 Norm, or the squared “Euclidean” distance from the origin.

For 1D vectors, this is equivalent to squaring the value.

Source§

impl<M> SpecialMath for M

Source§

fn erf(self) -> Self

Computes the error function. Read more
Source§

fn erfc(self) -> Self

Computes the complementary error function. Read more
Source§

fn erfcx(self) -> Self

Computes the scaled complementary error function, $\operatorname{erfcx}(x) = e^{x^2}\operatorname{erfc}(x)$. Read more
Source§

fn logistic_sigmoid(self) -> Self

Computes the Logistic sigmoid function, defined as $\sigma(x) = \frac{1}{1 + e^{-x}}$. Read more
Source§

fn logit(self) -> Self

Computes the logit $\ln\!\frac{p}{1-p}$, the inverse of logistic_sigmoid. Read more
Source§

fn logit_1m(self) -> Self

Computes $\mathrm{logit}(1 - q) = \ln\!\frac{1-q}{q}$ from the complement q directly. Read more
Source§

fn softplus(self, k: Self, rcp_k: Self) -> Self

Computes the softplus function, defined as $\frac{1}{k}\ln(1 + e^{kx})$. Read more
Source§

fn tgamma(self) -> Self

Computes the Gamma function ($\Gamma(z)$) for any real input, for each value in a vector. Read more
Source§

fn lgamma(self) -> Self

Computes the natural log of the Gamma function ($\ln|\Gamma(x)|$) for any real input, for each value in a vector.
Source§

fn poisson_pmf(self, lambda: Self) -> Self

The Poisson probability mass $P(k; \lambda) = e^{-\lambda}\lambda^k / k!$ at k = self, for real $k \ge 0$ and mean $\lambda \ge 0$. Read more
Source§

fn poisson_log_pmf(self, lambda: Self) -> Self

$\ln P(k; \lambda)$, the log of poisson_pmf, formed directly (no exp then ln) so it stays finite far in the tails where the mass itself underflows.
Source§

fn digamma(self) -> Self

Computes the digamma function $\psi(x) = \frac{\mathrm{d}}{\mathrm{d}x}\ln\Gamma(x) = \frac{\Gamma'(x)}{\Gamma(x)}$ for any real input, for each value in a vector. Read more
Source§

fn trigamma(self) -> Self

Computes the trigamma function $\psi_1(x) = \frac{\mathrm{d}}{\mathrm{d}x}\psi(x)$, the second derivative of $\ln\Gamma$. Read more
Source§

fn polygamma(self, n: u32) -> Self

Computes the polygamma function $\psi_n(x) = \frac{\mathrm{d}^n}{\mathrm{d}x^n}\psi(x)$, the n-th derivative of digamma (n = 0 is digamma, n = 1 is trigamma). Read more
Source§

fn zeta(self) -> Self

Computes the Riemann zeta function $\zeta(s) = \sum_{n\ge1} n^{-s}$. Read more
Source§

fn zetac(self) -> Self

Computes $\zeta(s) - 1$, accurately where $\zeta(s)$ is within rounding of 1. Read more
Source§

fn polylog( self, order: PolylogOrder<Self::Element, <Self::Signed as GenericVector>::Element>, ) -> Self

Computes the polylogarithm $\mathrm{Li}_s(z) = \sum_{k \ge 1} z^k / k^s$, continued to the whole plane, at a scalar real order given as a PolylogOrder. Read more
Source§

fn bessel_n<F, const N: i32>(self) -> Self
where F: BesselFamily,

A cylindrical Bessel function at compile-time order, selected by family marker: J, Y, I, K, or any of them under Scaled. N is signed and the families reflect at negative order ($J_{-n} = (-1)^n J_n$, $I_{-n} = I_n$). Read more
Source§

fn bessel<F>(self, order: BesselOrder<Self, Self::Signed>) -> Self
where F: BesselFamily,

bessel_n with the order taken per lane, at runtime, as a BesselOrder of any class. Read more
Source§

fn sph_bessel_n<F, const N: usize>(self) -> Self
where F: BesselFamily,

A spherical Bessel function at compile-time order, the twin of bessel_n for $j_n$, $y_n$, $i_n$, $k_n$. Read more
Source§

fn sph_bessel<F>(self, n: u32) -> Self
where F: BesselFamily,

sph_bessel_n for an order known only at runtime.
Source§

fn airy<W>(self) -> Self
where W: AiryFn,

One Airy function selected by marker: Ai, AiPrime, Bi, BiPrime, or any of them under Scaled. Read more
Source§

fn airy_all<const SCALED: bool>(self) -> (Self, Self, Self, Self)

$(\mathrm{Ai}, \mathrm{Ai}', \mathrm{Bi}, \mathrm{Bi}')$, all four, with the exponential factored out on the positive axis when SCALED (SciPy airy / airye). Read more
Source§

fn beta(self, y: Self) -> Self

Computes the Beta function $\mathrm{B}(x, y)$
Source§

fn lbeta(self, y: Self) -> Self

Computes $\ln\left|\mathrm{B}(x, y)\right|$, the log of the absolute Beta function. Read more
Source§

fn jacobi(self, alpha: Self, beta: Self, n: u32, m: u32) -> Self

Computes the m-th derivative of the n-th degree Jacobi polynomial Read more
Source§

fn hermite_n<const N: usize>(self) -> Self

Computes the N-th degree physicists’ Hermite polynomial $H_N(x)$ where x is self and N is the polynomial degree. Read more
Source§

fn hermitev(self, n: Self::Unsigned) -> Self

Computes the n-th degree physicists’ Hermite polynomial H_n(x) where x is self and n is a vector of unsigned integers representing the polynomial degree. Read more
Source§

fn hermite(self, n: u32) -> Self

$H_n(x)$ for a degree known only at runtime: hermitev with the degree splatted, which is the cheapest correct spelling of a uniform degree. The runtime twin of hermite_n.
Source§

fn hermite_function_n<const N: usize>(self) -> Self

Computes the orthonormal Hermite function Read more
Source§

fn hermite_function(self, n: u32) -> Self

$\psi_n(x)$ for a degree known only at runtime. The runtime twin of hermite_function_n: the same seed and recurrence, with the per-step constants computed rather than folded.
Source§

fn hermite_function_series_n<const N: usize>( self, coeffs: &[Self::Element; N], ) -> Self

Evaluates a finite series of Hermite functions at x = self: Read more
Source§

fn hermite_function_series(self, coeffs: &[Self::Element]) -> Self

hermite_function_series_n over a runtime-length coefficient slice. Read more
Source§

fn laguerre_n<const N: usize>(self, alpha: Self) -> Self

Computes the generalized (associated) Laguerre polynomial $L_N^{(\alpha)}(x)$, where x is self and N is the polynomial degree. Read more
Source§

fn laguerrev(self, alpha: Self, n: Self::Unsigned) -> Self

Computes the generalized (associated) Laguerre polynomial $L_n^{(\alpha)}(x)$ where n is a vector of unsigned integers giving the degree per lane. Read more
Source§

fn laguerre(self, alpha: Self, n: u32) -> Self

$L_n^{(\alpha)}(x)$ for a degree known only at runtime: laguerrev with the degree splatted. The runtime twin of laguerre_n.
Source§

fn laguerre_function_n<const N: usize>(self, alpha: Self) -> Self

Computes the orthonormal generalized Laguerre function Read more
Source§

fn laguerre_function(self, alpha: Self, n: u32) -> Self

$\ell_n^{(\alpha)}(x)$ for a degree known only at runtime. The runtime twin of laguerre_function_n: the same seed and recurrence, with the per-step scales computed rather than folded.
Source§

fn laguerre_function_i_n<const N: usize>(self, alpha: i32) -> Self

laguerre_function at an integer weight, taken as a scalar i32 rather than a vector. Read more
Source§

fn laguerre_function_i(self, alpha: i32, n: u32) -> Self

laguerre_function_i_n for a degree known only at runtime.
Source§

fn laguerre_function_series_n<const N: usize>( self, alpha: Self, coeffs: &[Self::Element; N], ) -> Self

Evaluates a finite series of generalized Laguerre functions at x = self: Read more
Source§

fn laguerre_function_series(self, alpha: Self, coeffs: &[Self::Element]) -> Self

laguerre_function_series_n over a runtime-length coefficient slice. Read more
Source§

fn laguerre_function_series_i_n<const N: usize>( self, alpha: i32, coeffs: &[Self::Element; N], ) -> Self

laguerre_function_series at a scalar integer weight, in the same relation to it as laguerre_function_i is to laguerre_function. See there for what the integer form buys.
Source§

fn laguerre_function_series_i( self, alpha: i32, coeffs: &[Self::Element], ) -> Self

laguerre_function_series_i_n over a runtime-length coefficient slice. Read more
Source§

fn chebyshev_n<const K: usize, const N: usize>( self, coeffs: &[Self::Element; N], ) -> Self

Evaluates a finite series of Chebyshev polynomials of the K-th kind at x = self: Read more
Source§

fn chebyshev<const K: usize>(self, coeffs: &[Self::Element]) -> Self

chebyshev_n over a runtime-length coefficient slice. Read more
Source§

fn gaussian(self, a: Self, c: Self) -> Self

Computes the Gaussian function with amplitude a and standard deviation c, defined as $a\, e^{-\frac{1}{2}(x/c)^2}$. Read more
Source§

fn planck(self) -> Self

Computes the Planck shape factor $\frac{x^3}{e^x - 1}$, finite at x = 0 where it vanishes like $x^2$. Read more
Source§

fn legendre(self, n: u32, m: u32) -> Self

Computes the m-th associated n-th degree Legendre polynomial, where m=0 signifies the regular n-th degree Legendre polynomial. Read more
Source§

fn legendre_series_n<const N: usize>(self, coeffs: &[Self::Element; N]) -> Self

Evaluates a finite Legendre series at x = self: Read more
Source§

fn legendre_series(self, coeffs: &[Self::Element]) -> Self

legendre_series_n over a runtime-length coefficient slice. Read more
Source§

fn zernike_r(self, n: u32, m: u32) -> Self

Computes the Zernike radial polynomial $R_n^m(\rho)$, where rho is self. Read more
Source§

fn zernike<const NORM: u8>(self, theta: Self, n: u32, m: i32) -> Self

Computes the Zernike polynomial $Z_n^m(\rho, \theta)$ on the unit disc, with rho as self: Read more
Source§

fn zernike_basis<const L: usize, const NORM: u8, const N: usize>( x: Self, y: Self, out: &mut [Self; N], )

Evaluates all Zernike modes through degree L at the Cartesian pupil point (x, y), into out[j] for the ANSI Z80.28 / OSA index $j = (n(n+2) + m)/2$. Read more
Source§

fn lambert_w(self) -> (Self, Self)

Computes both branches of the Lambert W function simultaneously: ($W_0(x)$, $W_{-1}(x)$). Read more
Source§

fn expint_n<const N: usize>(self) -> Self

Computes the generalized exponential integral E_n(x) for integer order n.
Source§

fn expint(self, n: u32) -> Self

E_n(x) for an order known only at runtime. The runtime twin of expint_n: the same E_1 kernel, the same recurrence and the same continued-fraction handover, so the two agree to the bit.
Source§

fn phi_n<const N: usize>(self) -> Self

Returns $\varphi_N(x)$, the N-th phi-function of exponential integrators. Read more
Source§

fn phi(self, n: u32) -> Self

$\varphi_n(x)$ for an order known only at runtime. The runtime twin of phi_n: the same series and recurrence arms, with the series length worked out from n per call rather than at compile time.
Source§

fn carlson<K>(kind: K) -> Self
where K: CarlsonKind<Output = Self>,

Carlson symmetric elliptic integral, selected by a CarlsonKind request struct with named fields. The arity (and which argument is the parameter / repeated one) is fixed per kind, so the wrong shape is a compile error. Read more
Source§

fn ellint<K>(kind: K) -> Self
where K: EllipticKind<Output = Self>,

Legendre elliptic integral, selected by an EllipticKind request struct. Each form (EllintK/EllintF/EllintE/ EllintEInc/EllintD/EllintDInc/ EllintPi/EllintPiInc) carries exactly its own arguments, and completeness is encoded by whether the struct has a phi field. Read more
Source§

impl<E, V> SpecialMathWithPolicy for V

Source§

fn erf_p<P>(self) -> V
where P: Policy,

Computes the error function.

For f32 vectors, this is still decently accurate even with the Medium and Worst precision policies, thanks to good approximations that don’t rely on the precision of exp. Subsequently, performance of the lower precision policies is excellent. Furthermore, if using on a GPU with native exp support, all precision policies will have good performance and accuracy.

Below Best, the f64 kernel forms erf as $1 - m\,e^{-x^2}$, whose error is a fixed absolute ulp of 1: erf(0) comes out 2.2e-16 and erf(1e-8) is only 2e-8 relative. From Best up, |x| < 0.84375 takes a direct $x + x\,R(x^2)/S(x^2)$ arm that is exact at zero and relatively accurate down to the denormals. The f32 kernel carries that arm from Average.

Source§

fn erfc_p<P>(self) -> V
where P: Policy,

Computes the complementary error function.

The f64 kernel is one product of six rationals times $e^{-x^2}$ over the whole line, within about 3 ulp everywhere on hardware with a fused multiply-add: the one error that grows, the rounding of $x^2$ under the exponential amplified by $x^2$, is removed with the exact residual of the product at every tier. Without a native FMA that residual is unavailable, so Best removes the growth with a bit-split of x instead, and the lower tiers keep it (47 ulp at x = 14, 237 at x = 24).

Source§

fn erfcx_p<P>(self) -> V
where P: Policy,

Computes the scaled complementary error function, $\operatorname{erfcx}(x) = e^{x^2}\operatorname{erfc}(x)$.

erfc underflows to zero at x ~ 27 in f64 and x ~ 9 in f32, where the true value is $e^{-x^2}/(x\sqrt{\pi})$, nonzero and merely too small to represent. Anything reading a Gaussian tail past that point silently gets zero: importance weights, log-likelihoods, censored-data models, the Voigt profile. erfcx removes the exponential and decays only as $1/(x\sqrt{\pi})$, so it is representable for every finite argument and keeps full relative accuracy.

Computed on the real backends as the Faddeeva function restricted to the imaginary axis, $w(ix) = \operatorname{erfcx}(x)$, where Weideman’s rational approximation degenerates to real arithmetic: one reciprocal and one Horner, no transcendental at all for x >= 0. That makes it cheaper than the erfc it complements, and measures 1.22 ulp worst over $x \in [0, 10^{15}]$ at the Best tier and above.

Negative arguments use $\operatorname{erfcx}(-x) = 2e^{x^2} - \operatorname{erfcx}(x)$ and legitimately overflow below about -26.6 (f64), the function itself growing like $e^{x^2}$ in that direction.

The two are related by $\operatorname{erfc}(x) = e^{-x^2}\operatorname{erfcx}(x)$, which is the numerically sound way to recover a tail value that erfc alone cannot hold. Keep the $-x^2$ in the log domain rather than exponentiating it.

Source§

fn logistic_sigmoid_p<P>(self) -> V
where P: Policy,

Computes the Logistic sigmoid function, defined as $\sigma(x) = \frac{1}{1 + e^{-x}}$.

It’s worth mentioning that the derivative of the logistic sigmoid can be computed very cheaply from the output of the logistic sigmoid itself, in the form of:

let s = x.logistic_sigmoid();
let derivative = s * (1.0 - s); // or s.nmul_adde(s, s), which may be slightly faster

Notably, for f32 and f64 this implementation still has good precision for the Worst precision policy, and for the Best precision policies handles very large positive and negative inputs without overflow or underflow issues.

Source§

fn logit_p<P>(self) -> V
where P: Policy,

Computes the logit $\ln\!\frac{p}{1-p}$, the inverse of logistic_sigmoid.

Evaluated as $\ln(p) - \ln_{1p}(-p)$, which is accurate for small p where the direct quotient is not. For p approaching 1 no evaluation order helps. $1 - p$ has already lost its low digits inside the input itself, and the information is not recoverable from p. A caller who knows $q = 1 - p$ should pass it to logit_1m instead, which is exact at the far end of the range.

p = 0 gives -∞, p = 1 gives +∞, and p outside [0, 1] is out of domain.

Source§

fn logit_1m_p<P>(self) -> V
where P: Policy,

Computes $\mathrm{logit}(1 - q) = \ln\!\frac{1-q}{q}$ from the complement q directly.

The companion entry point to logit, in the same relationship as langevin_1m has to langevin. The logit diverges as its argument approaches 1, and near that end $1 - p$ cannot be formed from p without losing every digit that matters. Working in q throughout sidesteps that: evaluated as $\ln_{1p}(-q) - \ln(q)$, accurate to a few ulp however small q is.

Note the sign convention follows the substitution, so logit_1m(q) == -logit(q) as functions of the same number. The two differ in which probability the argument names.

Source§

fn softplus_p<P>(self, k: V, rcp_k: V) -> V
where P: Policy,

Computes the softplus function, defined as $\frac{1}{k}\ln(1 + e^{kx})$.

This is a smooth approximation to the ReLU function that is more numerically stable for large inputs.

The parameter k controls the steepness of the curve, with larger values approaching ReLU more closely. Pass k = 1 and rcp_k = 1 for the standard softplus with no steepness scaling.

rcp_k must equal 1/k. It is passed explicitly so callers that invoke softplus repeatedly with the same k can pre-compute the reciprocal once rather than recomputing it per call.

To also obtain the derivative with respect to x, use softplus_d.

Source§

fn tgamma_p<P>(self) -> V
where P: Policy,

Computes the Gamma function ($\Gamma(z)$) for any real input, for each value in a vector.

This implementation uses a few different behaviors to ensure the greatest precision where possible.

  • For non-integer positive inputs, it uses the Lanczos approximation.
  • For small non-integer negative inputs, it uses the recursive identity $\Gamma(z) = \Gamma(z+1)/z$ until z is positive.
  • For large non-integer negative inputs, it uses the reflection formula $-\pi / (\Gamma(z)\sin(\pi z)\,z)$.
  • For positive integers, it simply computes the factorial in a tight loop to ensure precision. Lookup tables could not be used with SIMD.
  • At zero, the result will be positive or negative infinity based on the input sign (signed zero is a thing).

NOTE: The Gamma function is not defined for negative integers.

Source§

fn lgamma_p<P>(self) -> V
where P: Policy,

Computes the natural log of the Gamma function ($\ln|\Gamma(x)|$) for any real input, for each value in a vector.

Source§

fn poisson_pmf_p<P>(self, lambda: V) -> V
where P: Policy,

The Poisson probability mass $P(k; \lambda) = e^{-\lambda}\lambda^k / k!$ at k = self, for real $k \ge 0$ and mean $\lambda \ge 0$.

Not exp(k ln lambda - lambda - lgamma(k+1)): that forms an $O(1)$ answer as the exponential of a difference of large numbers, and half an ulp of $\ln\Gamma(k+1) = O(k \ln k)$ becomes that many ulp of the mass. For $k \ge 9$ this uses Loader’s saddle-point form (the one R’s dpois uses),

P(k; \lambda) = \frac{e^{-\mathrm{stirlerr}(k) - \mathrm{bd0}(k, \lambda)}}{\sqrt{2\pi k}}

with stirlerr the Stirling remainder (a short $1/k^2$ series) and bd0 the deviance $k \ln(k/\lambda) + \lambda - k$ (a series in $(k-\lambda)/(k+\lambda)$ near the peak, where the direct form cancels): both are small where the mass is not negligible, so the exponential amplifies nothing, and there is no lgamma and no ln at all near the peak. Below $k = 9$ the same machinery is used after shifting k up by an integer, with the exact product $(k+1)\cdots(k+m)$ taken back out, so there is no lgamma anywhere, and mixed vectors share one ln, one stirlerr and one exp. Real k is allowed because the Gamma density is the same function: $f(x; a) = P(a-1; x)$ for shape $a \ge 1$ (unit scale).

Edges: $\lambda = 0$ gives 1 at $k = 0$ and 0 above; $k = 0$ is $e^{-\lambda}$.

Source§

fn poisson_log_pmf_p<P>(self, lambda: V) -> V
where P: Policy,

$\ln P(k; \lambda)$, the log of poisson_pmf, formed directly (no exp then ln) so it stays finite far in the tails where the mass itself underflows.

Source§

fn digamma_p<P>(self) -> V
where P: Policy,

Computes the digamma function $\psi(x) = \frac{\mathrm{d}}{\mathrm{d}x}\ln\Gamma(x) = \frac{\Gamma'(x)}{\Gamma(x)}$ for any real input, for each value in a vector.

The argument is handled in three regimes:

  • For x >= 10, an asymptotic expansion in $1/x^2$ is used.
  • For smaller x, the recurrence $\psi(x) = \psi(x+1) - 1/x$ shifts the argument into [1, 2], where a rational minimax approximation $\psi(x) = (x - x_0)(Y + R(x-1))$ is used ($x_0$ is the positive root of $\psi$).
  • For x <= -1, the reflection formula $\psi(1-x) = \psi(x) + \pi\cot(\pi x)$ is applied.

NOTE: The digamma function is not defined at zero or the negative integers. Those inputs yield NaN when overflow checking is enabled.

Source§

fn trigamma_p<P>(self) -> V
where P: Policy,

Computes the trigamma function $\psi_1(x) = \frac{\mathrm{d}}{\mathrm{d}x}\psi(x)$, the second derivative of $\ln\Gamma$.

Real vectors run a dedicated kernel (three minimax rational regions with a single recurrence step and the $\pi^2/\sin^2(\pi x)$ reflection) that is a little tighter than the general polygamma machinery at order 1. polygamma(1) routes here, so the two spellings agree exactly. Complex vectors have their own implementation, which is the reason this lives on SpecialMath while polygamma is real-only.

The poles at zero and the negative integers evaluate to +inf: $\psi_1$ has double poles, so unlike digamma the two one-sided limits agree.

Source§

fn polygamma_p<P>(self, n: u32) -> V
where P: Policy,

Computes the polygamma function $\psi_n(x) = \frac{\mathrm{d}^n}{\mathrm{d}x^n}\psi(x)$, the n-th derivative of digamma (n = 0 is digamma, n = 1 is trigamma).

The order n is a runtime scalar shared by every lane. That is a deliberate design choice: it closes the Gamma family under differentiation, since $\psi_n'(x) = \psi_{n+1}(x)$ is reachable by passing n + 1, which is what lets forward-mode AD (Dual) differentiate through any member of the family to any depth. All order-dependent coefficients are scalar work splatted once, so uniform n costs a vector nothing.

For n >= 2, real vectors run a masked recurrence up to the transition point $N = 0.4\,d_{10} + 4n$ and then the Bernoulli asymptotic series on the positive axis. Negative arguments reflect through the n-th derivative of $\cot(\pi x)$ (tabulated to n = 20, above which negative arguments return NaN). At zero and the negative integers, odd n returns +inf (the correct two-sided limit) and even n has one-sided limits of opposite sign, so it returns NaN when overflow checking is enabled.

Complex vectors run the same recurrence-plus-series in complex arithmetic, gated on $\operatorname{Re} z$, reflecting the half-plane $\operatorname{Re} z < 1/2$ through the same tabulated $\cot$ derivative (so the n <= 20 reflection reach applies there too). Only psi_n of a real variable is real, so this is the family member that makes polygamma complex-capable at all orders.

Orders where $n!$ overflows the element type (n >= 171 for f64, n >= 35 for f32) return the signed infinity carried by the leading term on the real positive axis, and NaN over C.

Source§

fn zeta_p<P>(self) -> V
where P: Policy,

Computes the Riemann zeta function $\zeta(s) = \sum_{n\ge1} n^{-s}$.

Evaluated as 1 + zetac, which is where the accuracy argument lives (see there). Worst relative error measured against mpmath at 40 digits: 4.4e-16 for s in [1.5, 5], 4.3e-16 for [5, 40], 2.3e-15 through the critical strip [0.1, 0.9], and 4.6e-16 approaching the pole at s = 1, which returns infinity.

Negative s goes through the functional equation $\zeta(s) = 2^s\pi^{s-1}\sin(\pi s/2)\,\Gamma(1-s)\,\zeta(1-s)$, landing back at $1-s > 1$ where the series is at its most accurate. That arm costs a tgamma and a sin_pi beyond the main path, so it is gated on a lane needing it.

This is the Riemann zeta of one real argument. The two-argument Hurwitz form $\zeta(s, q)$ is not provided: it generalizes the same expansion but loses the prime factorization that makes this one cheap, so it is a separate and materially more expensive function rather than a special case of this one.

Source§

fn zetac_p<P>(self) -> V
where P: Policy,

Computes $\zeta(s) - 1$, accurately where $\zeta(s)$ is within rounding of 1.

$\zeta$ approaches 1 quickly: $\zeta(40) - 1$ is about 9.1e-13, already below the mantissa of $\zeta$ itself, and $\zeta(80) - 1$ is 8.3e-25. Forming zeta and subtracting 1 therefore destroys the answer: at s = 40 it is off by 9e-8 relative, at s = 80 by 100%, and past s = 200 it returns a flat zero.

This is not a wrapper around that subtraction. The Euler-Maclaurin sum underneath opens with the $n = 1$ term, which is the 1, so the complement is obtained by omitting it, with no cancellation anywhere and still full relative accuracy at s = 700, where the value is around 1e-211. $\zeta$ is the derived form here, the same way exp relates to exp_m1.

Same accuracy and the same negative-s handling as zeta.

Source§

fn polylog_p<P>( self, order: PolylogOrder<<V as GenericVector>::Element, <<V as GenericVector>::Signed as GenericVector>::Element>, ) -> V
where P: Policy,

Computes the polylogarithm $\mathrm{Li}_s(z) = \sum_{k \ge 1} z^k / k^s$, continued to the whole plane, at a scalar real order given as a PolylogOrder.

The order is uniform across the packet and tagged by class, because whole-number order is a different, far cheaper algorithm than arbitrary real order and every order-dependent coefficient is a per-call scalar precompute. See the order module for why it is not a vector. Integer covers both signs: $n \le 0$ is the closed rational form (a polynomial in $z/(1-z)$), $n = 1$ is $-\ln(1-z)$, and $n \ge 2$ runs entirely on tabulated $\zeta$ values. Real is the general algorithm (Wood 1992, Roughan 2026): the defining series, the unity series about $z = 1$ with its two cancelling poles fused algebraically so orders arbitrarily close to an integer cost nothing extra, and Wood’s m-th-root identity in the far field.

On a real vector the argument is real and the result is the real part of the principal value, which for $z > 1$ (the cut) is the same from either side. Complex vectors return the full value. On the cut it follows the sign of $\mathrm{Im}\,z$’s zero, C99 style, with -0 giving mpmath’s and Wood’s convention for a bare real.

let li2 = z.polylog(PolylogOrder::Integer(2));   // the dilogarithm
let fd  = (-x.exp()).polylog(PolylogOrder::Real(1.5)); // -F_{1/2}(x)/Gamma(3/2)

The order is spelled in the vector’s own element types: Real carries Self::Element (a complex element on a complex vector, of which only a real value is implemented and anything else answers NaN, or a dual element on a dual vector, whose derivative part must be zero) and Integer carries the signed lane element (i64 on an f64 vector, i32 on an f32 one). Every order-dependent coefficient is computed once per call in that element type through the scalar math surface.

Special values: $\mathrm{Li}_s(1) = \zeta(s)$ for $s > 1$ and $+\infty$ below, $\mathrm{Li}_s(-1) = -\eta(s)$, $\mathrm{Li}_s(0) = 0$. Every arm is a fixed-length series whose length follows the policy’s precision tier. Whole-number orders past $n = 79$ (binary64) or $n = 34$ (binary32, where $n!$ overflows) return NaN in the far field ($|\ln z| > 3.2$). The series and unity arms have no such limit. Cost grows with $\ln|z|$ in the far field at real order (one unity series per root, $m \approx \ln|z| / 2.08$ roots).

Measured against mpmath on 4952 points (real and complex $z$, orders from -6 to 30 and a dozen real ones including $2 + 10^{-9}$), binary64 at Precision: whole-number orders $n \ge 0$ within 1.3e-14 relative on the real line. Negative whole orders within 1.5e-13 (the alternating defining series on the negative axis peaks at ~2500x its sum). Real orders within 3.1e-13, with the far field’s m-th-root sum cancelling by $m^{s-1}$, which is what makes binary32 real order 1.1e-4 there and 2e-5 elsewhere. On the cut the real part is accurate normwise (the imaginary part can be a millionth of it near $z = 1$ at $s = 1 + 10^{-6}$).

Autodiff closes by $\mathrm{Li}_s'(z) = \mathrm{Li}_{s-1}(z)/z$ with the order lowered by one, which is why the runtime order is what the trait carries.

Source§

fn bessel_n_p<P, F, const N: i32>(self) -> V
where P: Policy, F: BesselFamily,

A cylindrical Bessel function at compile-time order, selected by family marker: J, Y, I, K, or any of them under Scaled. N is signed and the families reflect at negative order ($J_{-n} = (-1)^n J_n$, $I_{-n} = I_n$).

let j2 = x.bessel_n::<J, 2>();                 // J_2(x)
let ke = x.bessel_n::<Scaled<K>, 0>();         // e^x K_0(x)

The marker only selects: each spelling is a one-line route into the kernel for that family, scaling and order form, with nothing evaluated that was not asked for. Scaled<J> and Scaled<Y> are the SciPy jve/yve scalings by $e^{-|\mathrm{Im}\,z|}$, which is 1 on the real axis, so on a real vector they are J and Y unchanged. On a complex vector they are the scaled values.

Source§

fn bessel_p<P, F>( self, order: BesselOrder<V, <V as GenericVector>::Signed>, ) -> V
where P: Policy, F: BesselFamily,

bessel_n with the order taken per lane, at runtime, as a BesselOrder of any class.

let iv = x.bessel::<Scaled<I>>(BesselOrder::Real(nu));   // e^{-|x|} I_nu(x)
let jh = x.bessel::<J>(BesselOrder::HalfInteger(k));     // J_{k/2}(x), elementary
Source§

fn sph_bessel_n_p<P, F, const N: usize>(self) -> V
where P: Policy, F: BesselFamily,

A spherical Bessel function at compile-time order, the twin of bessel_n for $j_n$, $y_n$, $i_n$, $k_n$.

let j3 = x.sph_bessel_n::<J, 3>();             // j_3(x)
let ke = x.sph_bessel_n::<Scaled<K>, 1>();     // e^x k_1(x)
Source§

fn sph_bessel_p<P, F>(self, n: u32) -> V
where P: Policy, F: BesselFamily,

sph_bessel_n for an order known only at runtime.

Source§

fn airy_p<P, W>(self) -> V
where P: Policy, W: AiryFn,

One Airy function selected by marker: Ai, AiPrime, Bi, BiPrime, or any of them under Scaled.

Not a slice of airy_all: the four outputs come from two Bessel passes (order 1/3 for the values, 2/3 for the derivatives), and asking for one runs one pass (Ai skips the I half of it too, so it is roughly a quarter of the tuple). Take the tuple when you want more than one of them.

let ai = x.airy::<Ai>();
let bp = x.airy::<Scaled<BiPrime>>();      // e^{-zeta} Bi'(x) on the positive axis
Source§

fn airy_all_p<P, const SCALED: bool>(self) -> (V, V, V, V)
where P: Policy,

$(\mathrm{Ai}, \mathrm{Ai}', \mathrm{Bi}, \mathrm{Bi}')$, all four, with the exponential factored out on the positive axis when SCALED (SciPy airy / airye).

Prefer the scaled form on accuracy grounds, not only range: on the positive axis the kernel produces $e^{\zeta}K$ natively, so it evaluates no exponential anywhere and holds 1-3 eps where the unscaled one reaches 684 at x = 100 ($\zeta = \tfrac{2}{3}x^{3/2}$). Unscaled, Ai underflows past x ~ 104 and Bi overflows past x ~ 104.5. For x < 0 the functions oscillate, nothing is factored out, and the phase error grows like $|x|^{3/2}$ in every library.

Source§

fn beta_p<P>(self, y: V) -> V
where P: Policy,

Computes the Beta function $\mathrm{B}(x, y)$

Source§

fn lbeta_p<P>(self, y: V) -> V
where P: Policy,

Computes $\ln\left|\mathrm{B}(x, y)\right|$, the log of the absolute Beta function.

beta itself underflows to zero for quite ordinary arguments ($\mathrm{B}(200, 200)$ is about 1e-121, already gone in f32) and overflows for arguments straddling the poles. The log form has range to spare in both directions and is what the surrounding computation usually wants anyway, since Beta almost always appears inside a product of Gammas that is about to be logged.

Evaluated as $\ln\Gamma(x) + \ln\Gamma(y) - \ln\Gamma(x+y)$. The absolute value follows lgamma, so recover the sign from lgamma_r if the arguments can be negative.

This buys range at some cost in relative accuracy. The three lgamma terms cancel against each other, shedding roughly $\log_{10}\frac{\ln\Gamma(x+y)}{|\ln \mathrm{B}|}$ digits. That is under one digit at $x = y = 200$, and a little over two at $x = 200,\ y = 1$ where the terms are near 860 and the answer is near -5.3. It remains far better conditioned than beta, which simply has no value to return across most of that domain.

Source§

fn jacobi_p<P>(self, alpha: V, beta: V, n: u32, m: u32) -> V
where P: Policy,

Computes the m-th derivative of the n-th degree Jacobi polynomial

A the special case where α and β are both zero, the Jacobi polynomial reduces to a Legendre polynomial.

NOTE: Given constant α, β or n, LLVM will happily optimize those away and unroll loops.

Source§

fn hermite_n_p<P, const N: usize>(self) -> V
where P: Policy,

Computes the N-th degree physicists’ Hermite polynomial $H_N(x)$ where x is self and N is the polynomial degree.

Evaluated by the three-term recurrence

H_{n+1}(x) = 2x\,H_n(x) - 2n\,H_{n-1}(x)

seeded with $H_0 = 1$ and $H_1(x) = 2x$. The trip count is N, with no data dependence, so LLVM unrolls the whole thing into straight-line FMA.

The derivative is another member of the same family, $H_n'(x) = 2n\,H_{n-1}(x)$, so a value-and-slope pair costs one extra call rather than a separate kernel. The probabilists’ polynomials are a rescaling, $He_n(x) = 2^{-n/2} H_n(x/\sqrt{2})$.

NOTE: this is the raw polynomial, which grows fast: $H_n(0) = (-2)^{n/2} (n-1)!!$ for even n, and $H_n(x) \sim (2x)^n$ in the tails. It leaves binary32 range at the origin around degree 48 and binary64 around 300, and much earlier for |x| of a few units. If what you actually want is the normalized Hermite function (the quantum harmonic oscillator eigenstate, a Hermite-Gauss beam mode, or the basis of a Hermite spectral method), use hermite_function, which folds the Gaussian weight and the normalization into the recurrence and stays $O(1)$ at every degree. The raw polynomial is the right primitive for Gauss-Hermite quadrature node-finding at modest n and for anything that genuinely wants $H_n$ itself.

Source§

fn hermitev_p<P>(self, n: <V as GenericVector>::Unsigned) -> V
where P: Policy,

Computes the n-th degree physicists’ Hermite polynomial H_n(x) where x is self and n is a vector of unsigned integers representing the polynomial degree.

The polynomial is calculated independently per-lane with the given degree in n.

This uses the recurrence relation to compute the polynomial iteratively.

Source§

fn hermite_p<P>(self, n: u32) -> V
where P: Policy,

$H_n(x)$ for a degree known only at runtime: hermitev with the degree splatted, which is the cheapest correct spelling of a uniform degree. The runtime twin of hermite_n.

Source§

fn hermite_function_n_p<P, const N: usize>(self) -> V
where P: Policy,

Computes the orthonormal Hermite function

\psi_N(x) = \frac{1}{\sqrt{2^N N! \sqrt{\pi}}}\, e^{-x^2/2}\, H_N(x)

where x is self. These are the eigenfunctions of the quantum harmonic oscillator and of the Fourier transform, the Hermite-Gauss modes of a paraxial beam, and the basis of Hermite spectral methods. They are orthonormal on the whole line, $\int \psi_m \psi_n\, dx = \delta_{mn}$.

Evaluated by the recurrence on the functions themselves,

\psi_{n+1}(x) = \sqrt{\tfrac{2}{n+1}}\, x\, \psi_n(x) - \sqrt{\tfrac{n}{n+1}}\, \psi_{n-1}(x)

which keeps every intermediate $O(1)$ (the polynomial’s growth and the Gaussian’s decay cancel inside each step), so unlike hermite it does not overflow at high degree. Both square roots are literals under the unrolled loop. The per-step cost is one FMA on the critical path.

§Range

The only quantity that can leave the exponent range is the Gaussian seed, which is carried as $e^{-x^2/4}$ in two halves to double the reach. Full accuracy at every degree holds for $|x|$ under about 18.7 (binary32) or 53 (binary64), which covers every degree up to about 175 / 1400 everywhere on the line, since past the turning point $\sqrt{2n+1}$ the true value decays faster than the seed. Beyond that the result is still correct wherever $e^{-x^2/4}$ is representable, and zero past it.

Under a Best-or-better precision policy on true-FMA hardware, the rounding of $x^2$ (which is the entire error budget of a Gaussian at large x) is recovered exactly and corrected to first order.

Source§

fn hermite_function_p<P>(self, n: u32) -> V
where P: Policy,

$\psi_n(x)$ for a degree known only at runtime. The runtime twin of hermite_function_n: the same seed and recurrence, with the per-step constants computed rather than folded.

Source§

fn hermite_function_series_n_p<P, const N: usize>( self, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Evaluates a finite series of Hermite functions at x = self:

\sum_{k=0}^{N-1} \mathrm{coeffs}[k] \cdot \psi_k(x)

with $\psi_k$ as in hermite_function. Evaluated by Clenshaw’s backward recurrence, which is more stable than summing the functions one at a time and never forms them individually. N is the length of the coefficient array, so the highest function is $\psi_{N-1}$; N = 0 is rejected.

Same range as hermite_function: the coefficients are pre-scaled by half of the Gaussian and the outer factor carries the other half, so the running Clenshaw values grow no faster than $e^{x^2/4}$.

Source§

fn hermite_function_series_p<P>( self, coeffs: &[<V as GenericVector>::Element], ) -> V
where P: Policy,

hermite_function_series_n over a runtime-length coefficient slice.

Same recurrence, same pre-scaling, same range. The length is the only difference, and it costs real work rather than only unrolling: the recurrence coefficients $\sqrt{2/(k+1)}$ and $\sqrt{k/(k+1)}$ fold to literals when N is a constant and become per-step square roots when it is not. Prefer the const form when the degree is known.

An empty coefficient slice is 0, where the const form rejects N = 0 at compile time.

Source§

fn laguerre_n_p<P, const N: usize>(self, alpha: V) -> V
where P: Policy,

Computes the generalized (associated) Laguerre polynomial $L_N^{(\alpha)}(x)$, where x is self and N is the polynomial degree.

Passing alpha = Self::ZERO gives the ordinary Laguerre polynomial $L_N(x)$; because alpha is an ordinary argument rather than a const generic, that case folds away completely when the zero is visible at the call site.

Evaluated by the three-term recurrence

(n+1)\,L_{n+1}^{(\alpha)}(x) = (2n + \alpha + 1 - x)\,L_n^{(\alpha)}(x) - (n + \alpha)\,L_{n-1}^{(\alpha)}(x)

seeded with $L_0^{(\alpha)} = 1$ and $L_1^{(\alpha)}(x) = 1 + \alpha - x$. The trip count is N, with no data dependence, so LLVM unrolls the whole thing into straight-line FMA.

The derivative is another member of the same family, $\frac{\mathrm{d}}{\mathrm{d}x} L_n^{(\alpha)}(x) = -L_{n-1}^{(\alpha+1)}(x)$, so a value-and-slope pair costs one extra call rather than a separate kernel.

NOTE: the forward recurrence is the standard evaluation route (Boost and GSL both use it) and is well behaved across the oscillatory region $0 \le x \lesssim 4n$. Past that $L_n^{(\alpha)}$ itself grows like $(-x)^n/n!$ and will overflow for large N and x on its own account.

Laguerre-Gaussian beam modes, the radial part of the hydrogen wavefunction, the quantum harmonic oscillator and coherent-state expansions, and Gauss-Laguerre quadrature.

Source§

fn laguerrev_p<P>(self, alpha: V, n: <V as GenericVector>::Unsigned) -> V
where P: Policy,

Computes the generalized (associated) Laguerre polynomial $L_n^{(\alpha)}(x)$ where n is a vector of unsigned integers giving the degree per lane.

The per-lane counterpart of laguerre, in the same relation to it as hermitev is to hermite. The recurrence runs to the largest n in the vector and lanes freeze at their own degree, so the cost is set by max(n) rather than by any one lane.

Source§

fn laguerre_p<P>(self, alpha: V, n: u32) -> V
where P: Policy,

$L_n^{(\alpha)}(x)$ for a degree known only at runtime: laguerrev with the degree splatted. The runtime twin of laguerre_n.

Source§

fn laguerre_function_n_p<P, const N: usize>(self, alpha: V) -> V
where P: Policy,

Computes the orthonormal generalized Laguerre function

l_N^{(\alpha)}(x) = \sqrt{\frac{N!}{\Gamma(N+\alpha+1)}}\; x^{\alpha/2} e^{-x/2}\, L_N^{(\alpha)}(x)

where x is self. Orthonormal on the half-line, $\int_0^\infty l_m l_n\, dx = \delta_{mn}$. This is the radial factor of Laguerre-Gauss beam modes and (up to a power of x from the spherical measure) of the hydrogen wavefunctions. Defined for $x \ge 0$ and $\alpha > -1$, and nothing is checked outside that.

Evaluated by the recurrence on the functions themselves, with $s_k = \sqrt{(k+1)(k+\alpha+1)}$:

l_{k+1} = \frac{(2k + \alpha + 1 - x)\, l_k - s_{k-1}\, l_{k-1}}{s_k}

which keeps every intermediate $O(1)$, so unlike laguerre it does not overflow at high degree or large x. alpha is a runtime vector, so each step also carries a sqrt and a reciprocal, beside the recurrence rather than on its critical path, and folded to literals when alpha is a visible constant. The seed is skipped outright by a uniform branch when every lane has alpha = 0, which is the ordinary Laguerre function and by far the common case.

§Range

The Gaussian-like seed $x^{\alpha/2} e^{-x/2}$ is carried as $e^{-x/4}$ in two halves, as in hermite_function. Full accuracy at every degree for x under about 350 (binary32) or 2800 (binary64), covering every degree up to roughly 87 / 700 everywhere on the half-line (the turning point of $l_n^{(\alpha)}$ is near 4n).

alpha is unrestricted over the same x range. The seed’s whole parameter dependence, $x^{\alpha/2}/\sqrt{\Gamma(\alpha+1)}$, is the square root of the Poisson mass $P(\alpha; x)$ and is evaluated as poisson_pmf is (Loader’s saddle-point form, one exponential of a small exponent), so neither factor materializes (separately $x^{\alpha/2}$ overflows binary64 near $\alpha = 250$ and $1/\sqrt{\Gamma(\alpha+1)}$ underflows near $\alpha = 320$, and their overlap would be inf * 0) and nothing large is exponentiated: 0-3 ulp at the peak x ~ alpha out to $\alpha = 1400$, against a 50-digit oracle.

Source§

fn laguerre_function_p<P>(self, alpha: V, n: u32) -> V
where P: Policy,

$\ell_n^{(\alpha)}(x)$ for a degree known only at runtime. The runtime twin of laguerre_function_n: the same seed and recurrence, with the per-step scales computed rather than folded.

Source§

fn laguerre_function_i_n_p<P, const N: usize>(self, alpha: i32) -> V
where P: Policy,

laguerre_function at an integer weight, taken as a scalar i32 rather than a vector.

Same function and same range. What changes is what the compiler can see. Every quantity the recurrence derives from the weight (the $s_k = \sqrt{(k+1)(k+\alpha+1)}$ and their reciprocals, and the $2k+\alpha+1$ offsets) becomes a scalar constant instead of a vector sqrt and reciprocal per step, and folds to a literal outright when alpha is compile-time known.

The seed changes too. Up to $\alpha = 170$ (binary64) / 29 (binary32) the normalization $x^{\alpha/2}/\sqrt{\alpha!}$ is a scalar factorial, a powi and at most one sqrt, with no ln, lgamma or second exp at all, and a few ulp more accurate than the log form, whose lgamma error is amplified by the exponential. $\alpha = 0$ is a scalar test that skips even that. Beyond the cap it takes the vector form’s saddle-point seed. Measured on AVX2 f64x4 at degree 4: about 5x faster than the vector form at a literal small weight, 2x at a runtime one.

Prefer this whenever the weight is a non-negative integer, which every classical application has: the hydrogen radial functions use $\alpha = 2\ell+1$ and the Laguerre-Gauss beam modes use $\alpha = |\ell|$. Negative values are out of domain, as $\alpha \le -1$ is for the general form.

Like the series forms this is inlined into the caller rather than given its own dispatch trampoline: the weight is a plain i32 argument, and a shared out-of-line copy would take it at runtime, which both defeats the folding above and (measured) stops LLVM overlapping consecutive evaluations, at 7x the cost. Call it from inside a #[thermite::dispatch] body.

Source§

fn laguerre_function_i_p<P>(self, alpha: i32, n: u32) -> V
where P: Policy,

laguerre_function_i_n for a degree known only at runtime.

Source§

fn laguerre_function_series_n_p<P, const N: usize>( self, alpha: V, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Evaluates a finite series of generalized Laguerre functions at x = self:

\sum_{k=0}^{N-1} \mathrm{coeffs}[k] \cdot l_k^{(\alpha)}(x)

with $l_k^{(\alpha)}$ as in laguerre_function. Clenshaw’s backward recurrence, same range as the single function; N is the coefficient count and N = 0 is rejected.

Source§

fn laguerre_function_series_p<P>( self, alpha: V, coeffs: &[<V as GenericVector>::Element], ) -> V
where P: Policy,

laguerre_function_series_n over a runtime-length coefficient slice.

Same recurrence, same pre-scaling, same range. The per-step weights are computed rather than folded, as in hermite_function_series. An empty coefficient slice is 0.

Source§

fn laguerre_function_series_i_n_p<P, const N: usize>( self, alpha: i32, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

laguerre_function_series at a scalar integer weight, in the same relation to it as laguerre_function_i is to laguerre_function. See there for what the integer form buys.

Source§

fn laguerre_function_series_i_p<P>( self, alpha: i32, coeffs: &[<V as GenericVector>::Element], ) -> V
where P: Policy,

laguerre_function_series_i_n over a runtime-length coefficient slice.

The _n is the coefficient count and the _i is the integer weight, in that order because the length is the newer axis, and both mean what they do everywhere else. An empty coefficient slice is 0.

Source§

fn chebyshev_n_p<P, const K: usize, const N: usize>( self, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Evaluates a finite series of Chebyshev polynomials of the K-th kind at x = self:

\sum_{k=0}^{N-1} \mathrm{coeffs}[k] \cdot P_k(x)

where P_k is T_k, U_k, V_k, or W_k depending on K. All four kinds share the recurrence $P_{k+1}(x) = 2x \cdot P_k(x) - P_{k-1}(x)$ with P_0(x) = 1, and differ only in P_1(x):

KKindP_1(x)Notes
1First (T_k)xMost common, the minimax/approximation basis on [-1, 1].
2Second (U_k)2xRelated to $\sin((k+1)\theta)/\sin(\theta)$ under $x = \cos\theta$.
3Third (V_k)2x - 1“Airfoil” polynomials; $\cos((k+\tfrac12)\theta)/\cos(\theta/2)$.
4Fourth (W_k)2x + 1$\sin((k+\tfrac12)\theta)/\sin(\theta/2)$.

Any other value of K is a compile-time error.

There is deliberately no single-polynomial T_n(x) entry point beside this, unlike legendre or hermite. Chebyshev polynomials are used almost exclusively as an approximation basis, i.e. as a series; their quadrature nodes and weights are closed-form, so nothing needs to iterate on a lone $T_n$; and the one genuine single-$T_n$ application (Chebyshev filter response, Dolph-Chebyshev windows) needs $|x| > 1$, where the right evaluation is $\cosh(n \cosh^{-1} x)$ and not this recurrence at all. A unit coefficient array recovers $T_n$ if it is ever wanted.

Evaluation is done via Clenshaw’s backward recurrence with FMA, which is more numerically stable than a forward sum when the partial sums of $\sum c_k P_k$ are much smaller than $\max_k |c_k P_k|$ (e.g. fitted minimax series with alternating-sign coefficients). N is the length of the coefficient slice, so the highest polynomial term is P_{N-1}; N = 0 is rejected, N = 1 evaluates to coeffs[0].

coeffs[0] multiplies P_0 = 1, coeffs[1] multiplies P_1(x) (which depends on K), and so on. Because LLVM sees both K and N as constants, the recurrence loop and the P_1 selection are fully unrolled and specialized at monomorphization time.

§Accuracy near $x = \pm 1$

The plain recurrence forms $2x b_{k+1} - b_{k+2}$ with consecutive $b_k$ of nearly equal magnitude as x approaches either endpoint, and cancels. This is a property of the recurrence, not of the series: measured against a 60-digit oracle at N = 24, it costs up to 37 ulp on sums whose own condition number is about 1, and up to 230 ulp on unstructured coefficients.

Under a Best-or-better precision policy, real vectors instead take Reinsch’s modification, which recurs on the differences (near +1) or sums (near -1) so the small quantity is never formed by subtraction. On the same grid that bounds the error envelope 2.5x to 17x tighter across all four kinds. It is an envelope improvement rather than a pointwise one (individual arguments can land worse), and costs roughly 2x on the recurrence’s dependency chain, which is why it is gated.

binary32 gains the same way, 2.6x to 13.5x on its own grid. Measuring it needs an f32-native one: 1 - 2^-j rounds to exactly 1.0 for every j >= 24, so an f64 grid piles two thirds of its points onto the endpoint itself, where the endpoint form degenerates into a plain running sum and the two policies agree, and never samples the f32 neighbourhood where the cancellation actually bites.

Coefficients from a minimax or least-squares fit decay geometrically and barely notice either way (about 3 ulp to 1). The gap opens on slowly-decaying or non-decaying spectra: truncated expansions, near-singular functions, or coefficients that came from somewhere other than a fit.

Complex and the composite arithmetics keep the plain recurrence at every policy, since Reinsch needs a real copysign and a meaningful nearest endpoint.

Source§

fn chebyshev_p<P, const K: usize>( self, coeffs: &[<V as GenericVector>::Element], ) -> V
where P: Policy,

chebyshev_n over a runtime-length coefficient slice.

K stays a const generic, since it selects which Chebyshev kind, not how many coefficients, and there are exactly four. Only the length becomes dynamic.

Same recurrence and the same Best-precision Reinsch form near $x = \pm 1$; what the runtime length costs is the unrolling and the folded coeffs indices. An empty coefficient slice is 0.

Source§

fn gaussian_p<P>(self, a: V, c: V) -> V
where P: Policy,

Computes the Gaussian function with amplitude a and standard deviation c, defined as $a\, e^{-\frac{1}{2}(x/c)^2}$.

The position b is assumed to be zero. For a non-zero position, use self - b as the input.

Source§

fn planck_p<P>(self) -> V
where P: Policy,

Computes the Planck shape factor $\frac{x^3}{e^x - 1}$, finite at x = 0 where it vanishes like $x^2$.

The dimensionless kernel of Planck’s law: substituting $x = h\nu/kT$ recovers the spectral radiance up to a scale factor, so this is the part worth computing carefully and the constants are left to the caller. Radiative transfer, climate radiation budgets, and stellar atmospheres.

The denominator cancels for small x and the quotient is $0/0$ at the origin. Evaluated here as $x^2/\varphi_1(x)$ using phi_n::<1>, which is finite and equal to 1 there, so the singularity never forms rather than being patched after the fact.

Source§

fn legendre_p<P>(self, n: u32, m: u32) -> V
where P: Policy,

Computes the m-th associated n-th degree Legendre polynomial, where m=0 signifies the regular n-th degree Legendre polynomial.

If m is odd, the input is only valid between -1 and 1

NOTE: Given constant n and/or m, LLVM will happily unroll and optimize inner loops.

Internally, this is computed with jacobi when m > 0.

Source§

fn legendre_series_n_p<P, const N: usize>( self, coeffs: &[<V as GenericVector>::Element; N], ) -> V
where P: Policy,

Evaluates a finite Legendre series at x = self:

\sum_{k=0}^{N-1} \mathrm{coeffs}[k] \cdot P_k(x)

The form a Legendre-moment expansion takes: Mie and Henyey-Greenstein scattering phase functions tabulated by their moments, multipole expansions in $\cos\theta$, and the polar factor of a spherical-harmonic expansion at fixed order.

Evaluated by Clenshaw’s backward recurrence on the Legendre three-term relation, which is more stable than building each $P_k$ with legendre and summing, and does $O(N)$ work rather than $O(N^2)$. The recurrence ratios $(2k+1)/(k+1)$ and $k/(k+1)$ are literals under the unrolled loop, so the per-step cost matches chebyshev: one FMA on the critical path. N is the coefficient count; N = 0 is rejected, N = 1 evaluates to coeffs[0].

Plain Clenshaw at every policy: the endpoint cancellation that chebyshev treats under Best precision exists here too ($P_n(1) = 1$ for every n), but its Reinsch-style rewrite for the Legendre ratios has not been derived or measured.

Source§

fn legendre_series_p<P>(self, coeffs: &[<V as GenericVector>::Element]) -> V
where P: Policy,

legendre_series_n over a runtime-length coefficient slice.

Plain Clenshaw here too. The recurrence ratios $(2k+1)/(k+1)$ and $k/(k+1)$ are literals only when N is a constant, so this pays a division per step where the const form pays none, the widest const-versus-slice gap of the series family. An empty coefficient slice is 0.

Source§

fn zernike_r_p<P>(self, n: u32, m: u32) -> V
where P: Policy,

Computes the Zernike radial polynomial $R_n^m(\rho)$, where rho is self.

Returns zero unless $m \le n$ with $n - m$ even, the condition for the mode to exist. m is the absolute azimuthal frequency here. The sign only affects the angular factor, which lives in zernike.

Evaluated through the shifted Jacobi identity

R_n^m(\rho) = \rho^m\, P_{(n-m)/2}^{(0,\,m)}\!\left(2\rho^2 - 1\right)

rather than the textbook sum $\sum_k (-1)^k \frac{(n-k)!}{k!\,((n+m)/2 - k)!\,((n-m)/2 - k)!} \rho^{n-2k}$, which alternates factorials of size $(n-k)!$ against an answer bounded by 1 and loses all precision somewhere around n = 10-15. That is well inside the range adaptive optics, ophthalmology and surface metrology actually use.

The $(-1)^{(n-m)/2}$ prefactor usually seen with this identity is absent because the argument is written $2\rho^2 - 1$ rather than $1 - 2\rho^2$: reflecting a Jacobi polynomial swaps its two parameters and absorbs exactly that sign.

The polynomial is only orthogonal on $\rho \in [0, 1]$ and grows quickly outside it. Nothing clamps the argument, so an unnormalized pupil coordinate stays the caller’s problem.

Source§

fn zernike_p<P, const NORM: u8>(self, theta: V, n: u32, m: i32) -> V
where P: Policy,

Computes the Zernike polynomial $Z_n^m(\rho, \theta)$ on the unit disc, with rho as self:

Z_n^m(\rho, \theta) = N_n^m\, R_n^{|m|}(\rho) \times
  \begin{cases} \cos(m\theta) & m \ge 0 \\ \sin(|m|\theta) & m < 0 \end{cases}

Returns zero unless $|m| \le n$ with $n - |m|$ even.

NORM selects the normalization $N_n^m$ and must be either ZERNIKE_UNIT_PEAK ($N = 1$, so $R_n^m(1) = 1$ and coefficients read as peak amplitude) or ZERNIKE_ORTHONORMAL ($N_n^m = \sqrt{2(n+1)/(1 + \delta_{m,0})}$, the ANSI Z80.28 and Noll convention, under which coefficients read as RMS contributions). Any other value is a compile-time error. There is deliberately no default: the two differ by a factor of up to $\sqrt{2(n+1)}$ per mode, and picking one silently is how coefficient sets get misinterpreted.

(n, m) is a runtime pair rather than a const generic on purpose. The workload is a basis, not a function. A wavefront fit evaluates tens to hundreds of modes over thousands of pupil samples, with the mode list coming from a config or a sensor geometry, so the degree is loop-invariant across the vector axis and const-generic specialization would buy a jump table rather than an unrolled loop.

The single-index conventions (ANSI Z80.28 / OSA, Noll, Fringe) and the conversions between them are in crate::zernike. They disagree from the second term onward, so convert at the boundary rather than assuming.

Source§

fn zernike_basis_p<P, const L: usize, const NORM: u8, const N: usize>( x: V, y: V, out: &mut [V; N], )
where P: Policy,

Evaluates all Zernike modes through degree L at the Cartesian pupil point (x, y), into out[j] for the ANSI Z80.28 / OSA index $j = (n(n+2) + m)/2$.

N must equal (L+1)(L+2)/2 (compile-time checked), and NORM is ZERNIKE_UNIT_PEAK or ZERNIKE_ORTHONORMAL as on zernike.

This is the entry point a wavefront fit or reconstruction wants. It is not merely a loop over zernike. Substituting $s = x^2+y^2$ splits every mode into a polynomial in s times $\operatorname{Re}$ or $\operatorname{Im}$ of $(x+iy)^{|m|}$, which is where the $\rho^{|m|}$ and the $\cos m\theta$ both come from at once. Evaluation is then pure polynomial arithmetic: no atan2, no sqrt, no trigonometry, no division, $O(L^2)$ FMAs for the entire basis, and no singularity at the pupil centre. Calling the single-mode form per mode instead costs a sin_cos and a powi each and restarts the radial recurrence every time, for $O(L^3)$ work.

Cartesian input is part of that, not a convenience: pupil samples arrive as (x, y), and a polar entry point would charge an atan2 per sample for an angle this kernel immediately dissolves.

Fully unrolled at compile time for each L up to MAX_ZERNIKE_DEGREE; above that it takes a rolled path that is correct at any degree and substantially slower.

Nothing normalizes (x, y) onto the unit disc. Outside it the polynomials still evaluate correctly and simply are not orthogonal.

The layout is ANSI because it is the scheme whose index has a closed form and whose degree truncation is contiguous. Noll and Fringe callers gather through noll_to_ansi / fringe_to_ansi.

use thermite::prelude::*;
use thermite_special::{SpecialMath, ZERNIKE_ORTHONORMAL};
use thermite_special::zernike::noll_to_ansi;

type V = Vector<f64>;
const L: usize = 4;
const N: usize = 15; // (L+1)(L+2)/2

let mut basis = [V::ZERO; N];
V::zernike_basis::<L, ZERNIKE_ORTHONORMAL, N>(V::splat(0.3), V::splat(0.4), &mut basis);

// Noll 4 is defocus, Z_2^0 = sqrt(3) (2 rho^2 - 1) orthonormal.
let defocus = basis[noll_to_ansi(4) as usize].extract::<0>();
assert!((defocus - 3f64.sqrt() * (2.0 * 0.25 - 1.0)).abs() < 1e-14);
Source§

fn lambert_w_p<P>(self) -> (V, V)
where P: Policy,

Computes both branches of the Lambert W function simultaneously: ($W_0(x)$, $W_{-1}(x)$).

The $W_0$ result is valid for x >= -1/e; the $W_{-1}$ result is valid for -1/e <= x < 0. Outside these domains, the respective result is NaN (when overflow checking is enabled).

Source§

fn expint_n_p<P, const N: usize>(self) -> V
where P: Policy,

Computes the generalized exponential integral E_n(x) for integer order n.

Source§

fn expint_p<P>(self, n: u32) -> V
where P: Policy,

E_n(x) for an order known only at runtime. The runtime twin of expint_n: the same E_1 kernel, the same recurrence and the same continued-fraction handover, so the two agree to the bit.

Source§

fn phi_n_p<P, const N: usize>(self) -> V
where P: Policy,

Returns $\varphi_N(x)$, the N-th phi-function of exponential integrators.

\varphi_0(x) = e^x, \qquad
\varphi_{k+1}(x) = \frac{\varphi_k(x) - 1/k!}{x}, \qquad
\varphi_k(x) = \sum_{n \ge 0} \frac{x^n}{(n + k)!}, \qquad
\varphi_k(0) = \frac{1}{k!}

phi_n::<0> is exp. phi_n::<1> is $(e^x - 1)/x$, which written out directly is $0/0$ at the origin and loses most of the mantissa near it, so it is evaluated as $\mathrm{expm1}(x)/x$ with the removable singularity filled in (the value is 1), which is accurate across the whole line. Outside the exponential-integrator literature phi_n::<1> goes by exprel, which is the name SciPy, Boost and the statistics literature use for it. There is no separate exprel here because this is it. Beyond that the recurrence is the wrong way to compute them: each step subtracts 1/k! from a value that is barely larger while |x| is small, so $\varphi_2 = (\mathrm{expm1}(x) - x)/x^2$ loses twice the bits phi_n::<1> would have, and gets worse with N. Below |x| = N this sums the series instead (its terms are monotone there, so nothing cancels), and above it runs the recurrence upward from expm1, where the amplification per step is bounded. Measured against mpmath, both arms sit within a few ulp for N <= 8.

The series arm’s length is bounded by the policy’s max_iterations. The primitive float types know their precision statically and use a fixed count instead. Nothing caps N, though nothing needs it large: ETDRK4 wants phi_1..phi_3, and exponential Rosenbrock methods rarely go past phi_4.

phi_n::<1> alone is the coefficient that keeps appearing wherever an exponential is integrated over a finite step:

  • The in-scattering integral through a homogeneous medium, $\int_0^t e^{-\sigma s}\,ds = t\,\varphi_1(-\sigma t)$. The singular case is the empty medium, which is not an edge case in practice.
  • Exact stepping of an Ornstein-Uhlenbeck process, and the Langevin thermostat’s mean-reversion factor.
  • Frame-rate-independent exponential smoothing, usually written 1 - exp(-k * dt) and then divided by k.

The higher orders are the coefficients of exponential time differencing: integrating y' = Ly + N(y) exactly over a step gives $y(h) = e^{hL} y_0 + h\,\varphi_1(hL)\,N$, and expanding N in time along the step brings in $\varphi_2, \varphi_3, \ldots$ as the weights of the higher-order terms.

Source§

fn phi_p<P>(self, n: u32) -> V
where P: Policy,

$\varphi_n(x)$ for an order known only at runtime. The runtime twin of phi_n: the same series and recurrence arms, with the series length worked out from n per call rather than at compile time.

Source§

fn carlson_p<P, K>(kind: K) -> V
where P: Policy, K: CarlsonKind<Output = V>,

Carlson symmetric elliptic integral, selected by a CarlsonKind request struct with named fields. The arity (and which argument is the parameter / repeated one) is fixed per kind, so the wrong shape is a compile error.

let rf = V::carlson(CarlsonRf { x, y, z });
let rj = V::carlson_p::<Precision, _>(CarlsonRj { x, y, z, p });
Source§

fn ellint_p<P, K>(kind: K) -> V
where P: Policy, K: EllipticKind<Output = V>,

Legendre elliptic integral, selected by an EllipticKind request struct. Each form (EllintK/EllintF/EllintE/ EllintEInc/EllintD/EllintDInc/ EllintPi/EllintPiInc) carries exactly its own arguments, and completeness is encoded by whether the struct has a phi field.

Two family members that are not Legendre integrals dispatch through here as well, because they are built from the same Carlson forms and belong beside their siblings: JacobiZeta, the oscillating part of $E(\varphi, k)$, and HeumanLambda, its complementary-modulus companion.

let k_int = V::ellint(EllintK { k });                       // K(k)
let e_inc = V::ellint_p::<Precision, _>(EllintEInc { phi, k }); // E(phi, k)
let z     = V::ellint(JacobiZeta { phi, k });               // Z(phi, k)
Source§

impl<V> Swizzle3 for V
where V: SwizzleVector<Lanes = UInt<UInt<UTerm, B1>, B1>>,

Source§

fn xyz(self) -> V

Source§

fn xxx(self) -> V

Source§

fn xxy(self) -> V

Source§

fn xxz(self) -> V

Source§

fn xyx(self) -> V

Source§

fn xyy(self) -> V

Source§

fn xzx(self) -> V

Source§

fn xzy(self) -> V

Source§

fn xzz(self) -> V

Source§

fn yxx(self) -> V

Source§

fn yxy(self) -> V

Source§

fn yxz(self) -> V

Source§

fn yyx(self) -> V

Source§

fn yyy(self) -> V

Source§

fn yyz(self) -> V

Source§

fn yzx(self) -> V

Source§

fn yzy(self) -> V

Source§

fn yzz(self) -> V

Source§

fn zxx(self) -> V

Source§

fn zxy(self) -> V

Source§

fn zxz(self) -> V

Source§

fn zyx(self) -> V

Source§

fn zyy(self) -> V

Source§

fn zyz(self) -> V

Source§

fn zzx(self) -> V

Source§

fn zzy(self) -> V

Source§

fn zzz(self) -> V

Source§

impl<V> Swizzle4 for V
where V: SwizzleVector<Lanes = UInt<UInt<UInt<UTerm, B1>, B0>, B0>>,

Source§

fn xyzw(self) -> V

Source§

fn xxxx(self) -> V

Source§

fn xxxy(self) -> V

Source§

fn xxxz(self) -> V

Source§

fn xxxw(self) -> V

Source§

fn xxyx(self) -> V

Source§

fn xxyy(self) -> V

Source§

fn xxyz(self) -> V

Source§

fn xxyw(self) -> V

Source§

fn xxzx(self) -> V

Source§

fn xxzy(self) -> V

Source§

fn xxzz(self) -> V

Source§

fn xxzw(self) -> V

Source§

fn xxwx(self) -> V

Source§

fn xxwy(self) -> V

Source§

fn xxwz(self) -> V

Source§

fn xxww(self) -> V

Source§

fn xyxx(self) -> V

Source§

fn xyxy(self) -> V

Source§

fn xyxz(self) -> V

Source§

fn xyxw(self) -> V

Source§

fn xyyx(self) -> V

Source§

fn xyyy(self) -> V

Source§

fn xyyz(self) -> V

Source§

fn xyyw(self) -> V

Source§

fn xyzx(self) -> V

Source§

fn xyzy(self) -> V

Source§

fn xyzz(self) -> V

Source§

fn xywx(self) -> V

Source§

fn xywy(self) -> V

Source§

fn xywz(self) -> V

Source§

fn xyww(self) -> V

Source§

fn xzxx(self) -> V

Source§

fn xzxy(self) -> V

Source§

fn xzxz(self) -> V

Source§

fn xzxw(self) -> V

Source§

fn xzyx(self) -> V

Source§

fn xzyy(self) -> V

Source§

fn xzyz(self) -> V

Source§

fn xzyw(self) -> V

Source§

fn xzzx(self) -> V

Source§

fn xzzy(self) -> V

Source§

fn xzzz(self) -> V

Source§

fn xzzw(self) -> V

Source§

fn xzwx(self) -> V

Source§

fn xzwy(self) -> V

Source§

fn xzwz(self) -> V

Source§

fn xzww(self) -> V

Source§

fn xwxx(self) -> V

Source§

fn xwxy(self) -> V

Source§

fn xwxz(self) -> V

Source§

fn xwxw(self) -> V

Source§

fn xwyx(self) -> V

Source§

fn xwyy(self) -> V

Source§

fn xwyz(self) -> V

Source§

fn xwyw(self) -> V

Source§

fn xwzx(self) -> V

Source§

fn xwzy(self) -> V

Source§

fn xwzz(self) -> V

Source§

fn xwzw(self) -> V

Source§

fn xwwx(self) -> V

Source§

fn xwwy(self) -> V

Source§

fn xwwz(self) -> V

Source§

fn xwww(self) -> V

Source§

fn yxxx(self) -> V

Source§

fn yxxy(self) -> V

Source§

fn yxxz(self) -> V

Source§

fn yxxw(self) -> V

Source§

fn yxyx(self) -> V

Source§

fn yxyy(self) -> V

Source§

fn yxyz(self) -> V

Source§

fn yxyw(self) -> V

Source§

fn yxzx(self) -> V

Source§

fn yxzy(self) -> V

Source§

fn yxzz(self) -> V

Source§

fn yxzw(self) -> V

Source§

fn yxwx(self) -> V

Source§

fn yxwy(self) -> V

Source§

fn yxwz(self) -> V

Source§

fn yxww(self) -> V

Source§

fn yyxx(self) -> V

Source§

fn yyxy(self) -> V

Source§

fn yyxz(self) -> V

Source§

fn yyxw(self) -> V

Source§

fn yyyx(self) -> V

Source§

fn yyyy(self) -> V

Source§

fn yyyz(self) -> V

Source§

fn yyyw(self) -> V

Source§

fn yyzx(self) -> V

Source§

fn yyzy(self) -> V

Source§

fn yyzz(self) -> V

Source§

fn yyzw(self) -> V

Source§

fn yywx(self) -> V

Source§

fn yywy(self) -> V

Source§

fn yywz(self) -> V

Source§

fn yyww(self) -> V

Source§

fn yzxx(self) -> V

Source§

fn yzxy(self) -> V

Source§

fn yzxz(self) -> V

Source§

fn yzxw(self) -> V

Source§

fn yzyx(self) -> V

Source§

fn yzyy(self) -> V

Source§

fn yzyz(self) -> V

Source§

fn yzyw(self) -> V

Source§

fn yzzx(self) -> V

Source§

fn yzzy(self) -> V

Source§

fn yzzz(self) -> V

Source§

fn yzzw(self) -> V

Source§

fn yzwx(self) -> V

Source§

fn yzwy(self) -> V

Source§

fn yzwz(self) -> V

Source§

fn yzww(self) -> V

Source§

fn ywxx(self) -> V

Source§

fn ywxy(self) -> V

Source§

fn ywxz(self) -> V

Source§

fn ywxw(self) -> V

Source§

fn ywyx(self) -> V

Source§

fn ywyy(self) -> V

Source§

fn ywyz(self) -> V

Source§

fn ywyw(self) -> V

Source§

fn ywzx(self) -> V

Source§

fn ywzy(self) -> V

Source§

fn ywzz(self) -> V

Source§

fn ywzw(self) -> V

Source§

fn ywwx(self) -> V

Source§

fn ywwy(self) -> V

Source§

fn ywwz(self) -> V

Source§

fn ywww(self) -> V

Source§

fn zxxx(self) -> V

Source§

fn zxxy(self) -> V

Source§

fn zxxz(self) -> V

Source§

fn zxxw(self) -> V

Source§

fn zxyx(self) -> V

Source§

fn zxyy(self) -> V

Source§

fn zxyz(self) -> V

Source§

fn zxyw(self) -> V

Source§

fn zxzx(self) -> V

Source§

fn zxzy(self) -> V

Source§

fn zxzz(self) -> V

Source§

fn zxzw(self) -> V

Source§

fn zxwx(self) -> V

Source§

fn zxwy(self) -> V

Source§

fn zxwz(self) -> V

Source§

fn zxww(self) -> V

Source§

fn zyxx(self) -> V

Source§

fn zyxy(self) -> V

Source§

fn zyxz(self) -> V

Source§

fn zyxw(self) -> V

Source§

fn zyyx(self) -> V

Source§

fn zyyy(self) -> V

Source§

fn zyyz(self) -> V

Source§

fn zyyw(self) -> V

Source§

fn zyzx(self) -> V

Source§

fn zyzy(self) -> V

Source§

fn zyzz(self) -> V

Source§

fn zyzw(self) -> V

Source§

fn zywx(self) -> V

Source§

fn zywy(self) -> V

Source§

fn zywz(self) -> V

Source§

fn zyww(self) -> V

Source§

fn zzxx(self) -> V

Source§

fn zzxy(self) -> V

Source§

fn zzxz(self) -> V

Source§

fn zzxw(self) -> V

Source§

fn zzyx(self) -> V

Source§

fn zzyy(self) -> V

Source§

fn zzyz(self) -> V

Source§

fn zzyw(self) -> V

Source§

fn zzzx(self) -> V

Source§

fn zzzy(self) -> V

Source§

fn zzzz(self) -> V

Source§

fn zzzw(self) -> V

Source§

fn zzwx(self) -> V

Source§

fn zzwy(self) -> V

Source§

fn zzwz(self) -> V

Source§

fn zzww(self) -> V

Source§

fn zwxx(self) -> V

Source§

fn zwxy(self) -> V

Source§

fn zwxz(self) -> V

Source§

fn zwxw(self) -> V

Source§

fn zwyx(self) -> V

Source§

fn zwyy(self) -> V

Source§

fn zwyz(self) -> V

Source§

fn zwyw(self) -> V

Source§

fn zwzx(self) -> V

Source§

fn zwzy(self) -> V

Source§

fn zwzz(self) -> V

Source§

fn zwzw(self) -> V

Source§

fn zwwx(self) -> V

Source§

fn zwwy(self) -> V

Source§

fn zwwz(self) -> V

Source§

fn zwww(self) -> V

Source§

fn wxxx(self) -> V

Source§

fn wxxy(self) -> V

Source§

fn wxxz(self) -> V

Source§

fn wxxw(self) -> V

Source§

fn wxyx(self) -> V

Source§

fn wxyy(self) -> V

Source§

fn wxyz(self) -> V

Source§

fn wxyw(self) -> V

Source§

fn wxzx(self) -> V

Source§

fn wxzy(self) -> V

Source§

fn wxzz(self) -> V

Source§

fn wxzw(self) -> V

Source§

fn wxwx(self) -> V

Source§

fn wxwy(self) -> V

Source§

fn wxwz(self) -> V

Source§

fn wxww(self) -> V

Source§

fn wyxx(self) -> V

Source§

fn wyxy(self) -> V

Source§

fn wyxz(self) -> V

Source§

fn wyxw(self) -> V

Source§

fn wyyx(self) -> V

Source§

fn wyyy(self) -> V

Source§

fn wyyz(self) -> V

Source§

fn wyyw(self) -> V

Source§

fn wyzx(self) -> V

Source§

fn wyzy(self) -> V

Source§

fn wyzz(self) -> V

Source§

fn wyzw(self) -> V

Source§

fn wywx(self) -> V

Source§

fn wywy(self) -> V

Source§

fn wywz(self) -> V

Source§

fn wyww(self) -> V

Source§

fn wzxx(self) -> V

Source§

fn wzxy(self) -> V

Source§

fn wzxz(self) -> V

Source§

fn wzxw(self) -> V

Source§

fn wzyx(self) -> V

Source§

fn wzyy(self) -> V

Source§

fn wzyz(self) -> V

Source§

fn wzyw(self) -> V

Source§

fn wzzx(self) -> V

Source§

fn wzzy(self) -> V

Source§

fn wzzz(self) -> V

Source§

fn wzzw(self) -> V

Source§

fn wzwx(self) -> V

Source§

fn wzwy(self) -> V

Source§

fn wzwz(self) -> V

Source§

fn wzww(self) -> V

Source§

fn wwxx(self) -> V

Source§

fn wwxy(self) -> V

Source§

fn wwxz(self) -> V

Source§

fn wwxw(self) -> V

Source§

fn wwyx(self) -> V

Source§

fn wwyy(self) -> V

Source§

fn wwyz(self) -> V

Source§

fn wwyw(self) -> V

Source§

fn wwzx(self) -> V

Source§

fn wwzy(self) -> V

Source§

fn wwzz(self) -> V

Source§

fn wwzw(self) -> V

Source§

fn wwwx(self) -> V

Source§

fn wwwy(self) -> V

Source§

fn wwwz(self) -> V

Source§

fn wwww(self) -> V

Source§

impl<V> SwizzleVector for V

§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<M> TranscendentalMath for M

Source§

fn sin_cos(self) -> (Self, Self)

Trigonometric sine and cosine, together. This will be more efficient than calling sin and cos separately.
Source§

fn sin(self) -> Self

Trigonometric sine
Source§

fn cos(self) -> Self

Trigonometric cosine
Source§

fn tan(self) -> Self

Trigonometric tangent
Source§

fn cos_m1(self) -> Self

Returns cos(x) - 1 of self, which is more precise than cos(x) - 1 directly near zero. Read more
Source§

fn versin(self) -> Self

Returns the versine $1 - \cos(x)$ of self, evaluated as $2\sin^2(x/2)$ (accurate near zero).
Source§

fn haversin(self) -> Self

Returns the haversine $\tfrac{1 - \cos(x)}{2}$ of self, evaluated as $\sin^2(x/2)$ (accurate near zero). Read more
Source§

fn sincos_pi(self) -> (Self, Self)

Sine and cosine of pi * x, together. This will be more efficient than calling sin_pi and cos_pi separately, and more precise than computing them manually with sin(pi * x) and cos(pi * x).
Source§

fn sin_pi(self) -> Self

Trigonometric sine of pi * x, with improved precision when the policy allows.
Source§

fn cos_pi(self) -> Self

Trigonometric cosine of pi * x, with improved precision when the policy allows.
Source§

fn tan_pi(self) -> Self

Trigonometric tangent of pi * x, with improved precision when the policy allows.
Source§

fn sinc(self) -> Self

Computes sin(x) / x with improved precision when the policy allows.
Source§

fn versinc(self) -> Self

Returns $\frac{1 - \cos(x)}{x^2}$, finite at x = 0 where it takes the value 1/2. Read more
Source§

fn sinc_pi(self) -> Self

Computes $\frac{\sin(\pi x)}{\pi x}$ with improved precision when the policy allows.
Source§

fn sinh_cosh(self) -> (Self, Self)

Hyperbolic sine and cosine, together. This will be more efficient than calling sinh and cosh separately.
Source§

fn sinh(self) -> Self

Hyperbolic sine
Source§

fn cosh(self) -> Self

Hyperbolic cosine
Source§

fn tanh(self) -> Self

Hyperbolic tangent
Source§

fn asin(self) -> Self

Returns the arcsine of self.
Source§

fn acos(self) -> Self

Returns the arccosine of self.
Source§

fn atan(self) -> Self

Returns the arctangent of self.
Source§

fn asinh(self) -> Self

Inverse hyperbolic sine
Source§

fn acosh(self) -> Self

Inverse hyperbolic cosine
Source§

fn atanh(self) -> Self

Inverse hyperbolic tangent
Source§

fn exp(self) -> Self

The exponential function, returns e^(self).
Source§

fn exph(self) -> Self

The Half exponential function, returns 0.5 * e^(self).
Source§

fn exp2(self) -> Self

The base-2 exponential function, returns 2^(self).
Source§

fn exp10(self) -> Self

The base-10 exponential function, returns 10^(self).
Source§

fn exp_m1(self) -> Self

Returns exp(self) - 1 of self, which is more precise than calculating exp(self) - 1 directly.
Source§

fn exp2_m1(self) -> Self

Returns 2^(self) - 1, which is more precise than calculating exp2(self) - 1 directly.
Source§

fn exp10_m1(self) -> Self

Returns 10^(self) - 1, which is more precise than calculating exp10(self) - 1 directly.
Source§

fn sqrt1pm1(self) -> Self

Returns $\sqrt{1 + x} - 1$ of self, which is more precise than sqrt(1 + x) - 1 directly near zero. Read more
Source§

fn sqrt1mexp(self) -> Self

Returns $\sqrt{1 - e^{-x}}$ for x >= 0, without the cancellation of the direct form. Read more
Source§

fn powf(self, e: Self) -> Self

Returns self raised to the power of e.
Source§

fn powf_m1(self, e: Self) -> Self

Returns $x^e - 1$ where x = self, computed accurately as $e^{e \ln(x)}$-style expm1. Read more
Source§

fn compound(self, n: Self) -> Self

Returns $(1 + x)^n$ where x = self, computed accurately near x = 0 as $e^{n \ln(1 + x)}$. Read more
Source§

fn compound_m1(self, n: Self) -> Self

Returns $(1 + x)^n - 1$ where x = self, the $-1$ sibling of compound. Read more
Source§

fn cbrt(self) -> Self

Returns the cube root of self.
Source§

fn nth_root_n<const N: usize>(self) -> Self

Returns the Nth root of self. Read more
Source§

fn nth_root(self, n: u32) -> Self

Returns the n-th root of self for a degree known only at runtime. Read more
Source§

fn ln(self) -> Self

Returns the natural logarithm of self. Read more
Source§

fn xlogy(self, y: Self) -> Self

Returns $x \ln y$ with x = self, defined as 0 wherever x is zero. Read more
Source§

fn xlog1py(self, y: Self) -> Self

Returns $x \ln(1 + y)$ with x = self, defined as 0 wherever x is zero. Read more
Source§

fn sinhc(self) -> Self

Returns $\sinh(x)/x$ of self, the hyperbolic counterpart of sinc, with its removable singularity $\mathrm{sinhc}(0) = 1$ filled in. Read more
Source§

fn atanhc(self) -> Self

Returns $\operatorname{atanh}(x)/x$ of self, with its removable singularity $\mathrm{atanhc}(0) = 1$ filled in. Read more
Source§

fn cosh_m1(self) -> Self

Returns $\cosh(x) - 1$ of self, the hyperbolic counterpart of cos_m1. Read more
Source§

fn ln_1p(self) -> Self

Returns $\ln(1 + x)$ of self.
Source§

fn log2(self) -> Self

Returns the base-2 logarithm of self.
Source§

fn log10(self) -> Self

Returns the base-10 logarithm of self.
Source§

fn log2_p1(self) -> Self

Returns $\log_2(1 + x)$ of self, which is more precise than log2(1 + x) directly near zero.
Source§

fn log10_p1(self) -> Self

Returns $\log_{10}(1 + x)$ of self, which is more precise than log10(1 + x) directly near zero.
Source§

fn log1pmx(self) -> Self

Returns $\ln(1 + x) - x$ of self, which is accurate near zero where the subtraction otherwise cancels away every significant digit. Read more
Source§

fn log(self, base: Self) -> Self

Returns the logarithm of self with respect to the given base. Read more
Source§

fn log_n_n<const N: usize>(self) -> Self

Returns the logarithm of self with respect to the given integer base N. Read more
Source§

fn log_n(self, n: u32) -> Self

Returns the logarithm of self with respect to an integer base known only at runtime. Read more
Source§

fn ln1m_expnx(self) -> Self

Returns $\ln(1 - e^{-x})$, which depending on the policy may be an approximation more performant than the exact calculation. If you’re using a policy with below average precision, and happen to have ln(x) available, you can use ln1m_expnx_ext instead to provide that.
Source§

fn ln1m_expnx_ext(self, lnx: Self) -> Self

Returns ln(1 - exp(lnx)), which depending on the policy may be an approximation more performant than the exact calculation. If you’re using a policy with below average precision, it’s recommended to use this function instead of ln1m_expnx to provide ln(x) directly. Read more
Source§

impl<E, V> TranscendentalMathWithPolicy for V

Source§

fn sin_cos_p<P>(self) -> (V, V)
where P: Policy,

Trigonometric sine and cosine, together. This will be more efficient than calling sin and cos separately.

Source§

fn sin_p<P>(self) -> V
where P: Policy,

Trigonometric sine

Source§

fn cos_p<P>(self) -> V
where P: Policy,

Trigonometric cosine

Source§

fn tan_p<P>(self) -> V
where P: Policy,

Trigonometric tangent

Source§

fn cos_m1_p<P>(self) -> V
where P: Policy,

Returns cos(x) - 1 of self, which is more precise than cos(x) - 1 directly near zero.

Evaluated as $-2\sin^2(x/2)$, which has no cancellation near x = 0.

Source§

fn versin_p<P>(self) -> V
where P: Policy,

Returns the versine $1 - \cos(x)$ of self, evaluated as $2\sin^2(x/2)$ (accurate near zero).

Source§

fn haversin_p<P>(self) -> V
where P: Policy,

Returns the haversine $\tfrac{1 - \cos(x)}{2}$ of self, evaluated as $\sin^2(x/2)$ (accurate near zero).

This is the kernel of the haversine great-circle-distance formula.

Source§

fn sincos_pi_p<P>(self) -> (V, V)
where P: Policy,

Sine and cosine of pi * x, together. This will be more efficient than calling sin_pi and cos_pi separately, and more precise than computing them manually with sin(pi * x) and cos(pi * x).

Source§

fn sin_pi_p<P>(self) -> V
where P: Policy,

Trigonometric sine of pi * x, with improved precision when the policy allows.

Source§

fn cos_pi_p<P>(self) -> V
where P: Policy,

Trigonometric cosine of pi * x, with improved precision when the policy allows.

Source§

fn tan_pi_p<P>(self) -> V
where P: Policy,

Trigonometric tangent of pi * x, with improved precision when the policy allows.

Source§

fn sinc_p<P>(self) -> V
where P: Policy,

Computes sin(x) / x with improved precision when the policy allows.

Source§

fn versinc_p<P>(self) -> V
where P: Policy,

Returns $\frac{1 - \cos(x)}{x^2}$, finite at x = 0 where it takes the value 1/2.

The $x^2$ denominator is the one worth naming: $\frac{1-\cos x}{x}$ is simply zero at the origin and carries no removable singularity, while this ratio tends to 1/2 and is what actually appears in practice.

Written directly, $1 - \cos x$ has already lost half the mantissa by x of order 1e-4. Evaluated here as $\tfrac{1}{2}\,\mathrm{sinc}^2(x/2)$, an exact identity that needs no series and no cutoff, and inherits sinc’s behaviour at the origin.

This is the second Rodrigues coefficient of the SO(3) exponential map, alongside sinc as the first. Rigid-body and Lie-group integrators, IMU preintegration, and skinning all evaluate it once per timestep. The prevailing practice is a hand-rolled Taylor cutoff with an arbitrary epsilon.

Source§

fn sinc_pi_p<P>(self) -> V
where P: Policy,

Computes $\frac{\sin(\pi x)}{\pi x}$ with improved precision when the policy allows.

Source§

fn sinh_cosh_p<P>(self) -> (V, V)
where P: Policy,

Hyperbolic sine and cosine, together. This will be more efficient than calling sinh and cosh separately.

Source§

fn sinh_p<P>(self) -> V
where P: Policy,

Hyperbolic sine

Source§

fn cosh_p<P>(self) -> V
where P: Policy,

Hyperbolic cosine

Source§

fn tanh_p<P>(self) -> V
where P: Policy,

Hyperbolic tangent

Source§

fn asin_p<P>(self) -> V
where P: Policy,

Returns the arcsine of self.

Source§

fn acos_p<P>(self) -> V
where P: Policy,

Returns the arccosine of self.

Source§

fn atan_p<P>(self) -> V
where P: Policy,

Returns the arctangent of self.

Source§

fn asinh_p<P>(self) -> V
where P: Policy,

Inverse hyperbolic sine

Source§

fn acosh_p<P>(self) -> V
where P: Policy,

Inverse hyperbolic cosine

Source§

fn atanh_p<P>(self) -> V
where P: Policy,

Inverse hyperbolic tangent

Source§

fn exp_p<P>(self) -> V
where P: Policy,

The exponential function, returns e^(self).

Source§

fn exph_p<P>(self) -> V
where P: Policy,

The Half exponential function, returns 0.5 * e^(self).

Source§

fn exp2_p<P>(self) -> V
where P: Policy,

The base-2 exponential function, returns 2^(self).

Source§

fn exp10_p<P>(self) -> V
where P: Policy,

The base-10 exponential function, returns 10^(self).

Source§

fn exp_m1_p<P>(self) -> V
where P: Policy,

Returns exp(self) - 1 of self, which is more precise than calculating exp(self) - 1 directly.

Source§

fn exp2_m1_p<P>(self) -> V
where P: Policy,

Returns 2^(self) - 1, which is more precise than calculating exp2(self) - 1 directly.

Source§

fn exp10_m1_p<P>(self) -> V
where P: Policy,

Returns 10^(self) - 1, which is more precise than calculating exp10(self) - 1 directly.

Source§

fn sqrt1pm1_p<P>(self) -> V
where P: Policy,

Returns $\sqrt{1 + x} - 1$ of self, which is more precise than sqrt(1 + x) - 1 directly near zero.

Evaluated as $\frac{x}{\sqrt{1 + x} + 1}$, which has no cancellation near x = 0.

Source§

fn sqrt1mexp_p<P>(self) -> V
where P: Policy,

Returns $\sqrt{1 - e^{-x}}$ for x >= 0, without the cancellation of the direct form.

$1 - e^{-x}$ annihilates for small x, so this is evaluated as $\sqrt{-\mathrm{expm1}(-x)}$, which is accurate all the way down. Negative x is outside the domain and gives NaN.

This is the noise scaling of an exactly-integrated Ornstein-Uhlenbeck step: Langevin and Bussi-Parrinello thermostats, and the variance-preserving schedules used by diffusion models.

Source§

fn powf_p<P>(self, e: V) -> V
where P: Policy,

Returns self raised to the power of e.

Source§

fn powf_m1_p<P>(self, e: V) -> V
where P: Policy,

Returns $x^e - 1$ where x = self, computed accurately as $e^{e \ln(x)}$-style expm1.

More precise than powf(x, e) - 1 when the result is near zero (i.e. x near 1 or e near 0), e.g. compound returns/growth rates.

Source§

fn compound_p<P>(self, n: V) -> V
where P: Policy,

Returns $(1 + x)^n$ where x = self, computed accurately near x = 0 as $e^{n \ln(1 + x)}$.

This is the IEEE 754 compound operation, and is more precise than powf(1 + x, n) for small x (e.g. compound-growth/interest over n periods at rate x).

Source§

fn compound_m1_p<P>(self, n: V) -> V
where P: Policy,

Returns $(1 + x)^n - 1$ where x = self, the $-1$ sibling of compound.

Accurate at both ends where the two obvious spellings are not: compound(x, n) - 1 cancels when the result is near zero (small x or small n), and powf_m1(1 + x, n) has already lost x entirely by $|x| < \varepsilon$ because forming $1 + x$ rounds it away. Evaluated as $\mathrm{expm1}(n \ln(1 + x))$, which does neither.

This is the numerator of the shifted Box-Cox transform, and the kernel underneath thermite-special’s boxcox_1p and Yeo-Johnson transform, whose whole reason for existing is data that straddles zero.

Source§

fn cbrt_p<P>(self) -> V
where P: Policy,

Returns the cube root of self.

Source§

fn nth_root_n_p<P, const N: usize>(self) -> V
where P: Policy,

Returns the Nth root of self.

This is often faster and more accurate than using powf(1.0 / N as float). Supports negative numbers for odd N.

Source§

fn nth_root_p<P>(self, n: u32) -> V
where P: Policy,

Returns the n-th root of self for a degree known only at runtime.

The same arithmetic as nth_root_n, so the two agree to the bit at every n. The difference is that the special cases (n of 1 to 4) are one uniform branch on the value rather than a compile-time fold. Prefer the const form when the degree is a literal.

Source§

fn ln_p<P>(self) -> V
where P: Policy,

Returns the natural logarithm of self.

§Examples

Every math function takes a precision policy via its _p variant. A quick sweep against a scalar reference is the cheapest way to validate that a policy choice is accurate enough for your domain:

use thermite::prelude::*;
use thermite::math::policy::policies::Precision;

type V = Vector<f64>;

let mut max_err = 0.0f64;
for i in 1..=1000 {
    let x = i as f64 * 0.05;
    let y = V::splat(x).ln_p::<Precision>().extract::<0>();
    max_err = max_err.max((y - x.ln()).abs() / x.ln().abs().max(1.0));
}
assert!(max_err < 1e-14, "max relative error {max_err}");
Source§

fn xlogy_p<P>(self, y: V) -> V
where P: Policy,

Returns $x \ln y$ with x = self, defined as 0 wherever x is zero.

$0 \cdot \ln 0$ is $0 \cdot -\infty =$ NaN written directly, and one NaN poisons every reduction downstream of it: a cross-entropy over a batch with a single zero-probability term returns NaN for the whole batch. The convention $x = 0 \Rightarrow 0$ is the limit $\lim_{x \to 0^+} x \ln y$ and is what information theory assumes everywhere.

A NaN y still propagates, taking priority over the zero guard, matching SciPy and PyTorch. A negative y does not: it is not NaN, so x = 0 gives 0 there and only a non-zero x yields NaN from the log.

This is the case where a vector implementation is strictly ahead of a scalar one: the guard is a masked select costing one instruction, where scalar code needs a branch per element.

Source§

fn xlog1py_p<P>(self, y: V) -> V
where P: Policy,

Returns $x \ln(1 + y)$ with x = self, defined as 0 wherever x is zero.

xlogy’s companion for the case where y is a small perturbation, keeping ln_1p’s accuracy near zero rather than losing it to $1 + y$ first. Same zero and NaN conventions.

Source§

fn sinhc_p<P>(self) -> V
where P: Policy,

Returns $\sinh(x)/x$ of self, the hyperbolic counterpart of sinc, with its removable singularity $\mathrm{sinhc}(0) = 1$ filled in.

Written directly, $\sinh(x)/x$ is $0/0$ at the origin. Small arguments take the even series $1 + x^2/6 + x^4/120$ instead, which also skips the sinh.

Unlike sinc, this one grows: $\mathrm{sinhc}(\pm\infty) = +\infty$, and the naive spelling gets $\infty/\infty = $ NaN there rather than the limit.

Turns up in the hyperbolic exponential map, catenary curves, beam and rod stiffness matrices in FEM, exact solutions of linear ODE blocks, and the Einstein heat-capacity function $x^2 e^x/(e^x-1)^2$, which is exactly $1/\mathrm{sinhc}(x/2)^2$.

Source§

fn atanhc_p<P>(self) -> V
where P: Policy,

Returns $\operatorname{atanh}(x)/x$ of self, with its removable singularity $\mathrm{atanhc}(0) = 1$ filled in.

The cardinal form of atanh, in the same relation to it as sinc is to sin. Small arguments take the even series $1 + x^2/3 + x^4/5$, which also skips the atanh.

Defined on $[-1, 1]$, even, with $\mathrm{atanhc}(\pm 1) = +\infty$ and NaN outside.

This is the shape the logarithmic mean actually reduces to, and logmean is written on it: with $f = \frac{a-b}{a+b}$,

\mathrm{logmean}(a, b) = \frac{a+b}{2\,\mathrm{atanhc}(f)}

so the $a \to b$ limit is carried by this function rather than special-cased there. It is also the inner object of the Ismail-Roe entropy-stable flux, where production codes write it as an if on $f^2 < 10^{-4}$ that mispredicts across shocks. It also turns up in relativistic velocity addition, optical-depth ratios in radiative transfer, and the Legendre function of the second kind $Q_0$.

Source§

fn cosh_m1_p<P>(self) -> V
where P: Policy,

Returns $\cosh(x) - 1$ of self, the hyperbolic counterpart of cos_m1.

Evaluated as $2\sinh^2(x/2)$, an exact identity rather than an approximation, so there is no series and no cutoff, the same treatment shipped versin gets from $1 - \cos x = 2\sin^2(x/2)$. The direct spelling instead cancels: $\cosh x - 1$ is $O(x^2)$ against a $\cosh$ of $1$, so it has lost half the mantissa by $x \approx 10^{-8}$ and all of it by $x \approx 10^{-16}$.

Source§

fn ln_1p_p<P>(self) -> V
where P: Policy,

Returns $\ln(1 + x)$ of self.

Source§

fn log2_p<P>(self) -> V
where P: Policy,

Returns the base-2 logarithm of self.

Source§

fn log10_p<P>(self) -> V
where P: Policy,

Returns the base-10 logarithm of self.

Source§

fn log2_p1_p<P>(self) -> V
where P: Policy,

Returns $\log_2(1 + x)$ of self, which is more precise than log2(1 + x) directly near zero.

Source§

fn log10_p1_p<P>(self) -> V
where P: Policy,

Returns $\log_{10}(1 + x)$ of self, which is more precise than log10(1 + x) directly near zero.

Source§

fn log1pmx_p<P>(self) -> V
where P: Policy,

Returns $\ln(1 + x) - x$ of self, which is accurate near zero where the subtraction otherwise cancels away every significant digit.

$\ln(1+x) \approx x - x^2/2$ for small x, so the difference is $O(x^2)$ while both terms are $O(x)$: computing it as written costs about $2\varepsilon/|x|$ of relative error, which is total loss by $|x| \approx \varepsilon$. On $-1/2 \le x \le 1$ this instead sums the odd series in $r = x/(2+x)$,

\ln(1+x) - x = r\left(2r^2 \sum_{k \ge 0} \frac{r^{2k}}{2k+3} - x\right)

which has no cancellation and is exact at $x = 0$. Outside that window the direct form is already accurate to a few ulp and is what runs.

The Medium and Worst policies return the direct form everywhere, dropping the series and its window test. That is a change of behavior near zero, not a few ulp: once $1 + x$ rounds to 1 the direct form yields $-x$, which differs from $-x^2/2$ by every digit and by an unbounded factor. Those tiers are the right choice for arguments that stay clear of zero (where the direct form is a few ulp anyway, so the series is pure cost) and the wrong one for the near-zero case this function exists to serve. Ask for Average or better there.

The natural home of $\ln(1+x)-x$ is a density or deviance: the Poisson/binomial deviance is $-k \cdot \mathrm{log1pmx}((\lambda-k)/k)$, and the same shape turns up in entropies, Kullback-Leibler divergences and saddle-point approximations.

Source§

fn log_p<P>(self, base: V) -> V
where P: Policy,

Returns the logarithm of self with respect to the given base.

This is simply a convenience method for self.log2() / base.log2().

Source§

fn log_n_n_p<P, const N: usize>(self) -> V
where P: Policy,

Returns the logarithm of self with respect to the given integer base N.

This is efficient for bases <=32 using a lookup table, and falls back to the general log(x)/libm::log(N) implementation for larger bases.

For bases 0 and 1, the result is 0 and Infinity respectively.

Source§

fn log_n_p<P>(self, n: u32) -> V
where P: Policy,

Returns the logarithm of self with respect to an integer base known only at runtime.

The runtime twin of log_n_n: the same table lookup for bases up to 32 and the same fallback above, so the two agree to the bit. Bases 0 and 1 give 0 and infinity as there.

Source§

fn ln1m_expnx_p<P>(self) -> V
where P: Policy,

Returns $\ln(1 - e^{-x})$, which depending on the policy may be an approximation more performant than the exact calculation. If you’re using a policy with below average precision, and happen to have ln(x) available, you can use ln1m_expnx_ext instead to provide that.

Source§

fn ln1m_expnx_ext_p<P>(self, lnx: V) -> V
where P: Policy,

Returns ln(1 - exp(lnx)), which depending on the policy may be an approximation more performant than the exact calculation. If you’re using a policy with below average precision, it’s recommended to use this function instead of ln1m_expnx to provide ln(x) directly.

Although not obvious, ln(x) is used internally for the approximation, and if it’s already available, you may as well use this function to avoid recomputing it.

§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UpperBounded for T
where T: Bounded,

Source§

fn max_value() -> T

Returns the largest finite number this type can represent
Last built: 2026-09-08 21:35:55 UTC