Expand description
Overflow-safe Euclidean norms and squared norms.
Vector::norm() computes the Euclidean norm with a deterministic scaled
sum-of-squares recurrence, so large or subnormal finite coordinates do not fail
merely because their raw squares overflow or underflow. It returns positive zero
for empty and all-zero vectors and reports LaError::NonFinite with
ArithmeticOperation::VectorNorm only when the exact norm rounds to infinity.
Near the upper range, a fixed-size stack accumulator sums squares exactly and
compares squared rounding midpoints to prevent false or hidden overflow. This
fallback needs no optional dependencies. The general binary64 result remains
approximate and has no certified error bound.
Vector::norm_squared() remains the direct left-to-right FMA sum of squares for
callers that need the squared norm. Its distinct contract deliberately reports
overflow when that square is not finite, even when norm() can return a finite
norm.
ยงLarge and subnormal coordinates
use core::assert_matches;
use la_stack::prelude::*;
let large = Vector::<5>::try_new([3e200, 4e200, 0.0, 0.0, 0.0])?;
assert!((large.norm()? / 1e200 - 5.0).abs() <= 1e-12);
assert_matches!(
large.norm_squared(),
Err(LaError::NonFinite {
origin: NonFiniteOrigin::Computation {
operation: ArithmeticOperation::VectorSquaredNorm, ..
},
location: NonFiniteLocation::Step { index: 0, .. },
..
})
);
let tiny = f64::from_bits(16);
let small = Vector::<5>::try_new([3.0 * tiny, 4.0 * tiny, 0.0, 0.0, 0.0])?;
assert_eq!(small.norm()?, 5.0 * tiny);
assert_eq!(small.norm_squared()?, 0.0); // The raw squares underflow.The large-vector assertion uses a tolerance for this fixture, not a certified
error bound. The small vector shows why taking the square root of
norm_squared() can lose a representable nonzero norm.