Skip to content

feat: Add an overflow-safe Euclidean norm for fixed vectors #217

Description

@acgetchell

Summary

Add an overflow- and underflow-safe Euclidean norm to Vector<const D: usize>.
The existing norm2_sq() deliberately computes the squared norm in f64 and
returns a typed error when that square is not representable. Callers that need
the norm itself should not have to reimplement scaled hypot accumulation to
avoid an unnecessary intermediate overflow or underflow.

This is additive stable-Rust work and is independent of the
generic_const_exprs redesign in #123.

Downstream motivation: delaunay

delaunay currently carries a public geometry::util::norms::hypot helper and
uses it throughout distance, circumsphere, quality, measure, point-generation,
and topology-repair paths. The implementation is generic fixed-dimension linear
algebra rather than Delaunay-specific geometry. Moving it here would give the
algorithm one numerical owner and let Delaunay retire most or all of its local
norm module.

The distinction from norm2_sq() matters for finite inputs such as
[1.0e200, 1.0e200]: the Euclidean norm is finite even though the squared norm
is not representable as f64.

Requested contract

One possible surface is:

impl<const D: usize> Vector<D> {
    pub fn norm2(&self) -> Result<f64, LaError>;
}

The operation should:

  • return the Euclidean/L2 norm of the finite stored vector;
  • avoid avoidable overflow and underflow through scaling or an equivalently
    justified algorithm;
  • return 0.0 for the zero-dimensional and all-zero vectors;
  • preserve a typed LaError when the mathematical result cannot be represented
    as a finite f64;
  • retain deterministic operation ordering and document its rounding behavior;
  • avoid allocation and remain available without the exact feature;
  • leave norm2_sq() unchanged for callers that genuinely need a squared norm.

Acceptance criteria

  • Known-answer and property tests cover dimensions used downstream, including
    D=0 through D=8.
  • Tests cover zero, signed zero, mixed magnitudes, subnormal inputs, near-
    overflow values, and finite inputs whose norm is or is not representable.
  • Results are checked against an independent high-precision oracle where a
    simple known answer is insufficient.
  • Focused benchmarks compare the implementation with iterative f64::hypot,
    the prior Delaunay scaled implementation, and appropriate peer-crate norms.
  • Public documentation distinguishes norm2() from norm2_sq() and states the
    numerical contract precisely.

Downstream cleanup enabled

After release, Delaunay can adopt Vector::norm2() and the existing
Vector::norm2_sq(), remove its hand-written generalized hypot and
squared_norm implementations where their semantics match, and keep only
geometry-level error mapping where needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apienhancementNew feature or requestperformancePerformance related issuesrustPull requests that update rust codevalidation

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions