Skip to main content

Module norms

Module norms 

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