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.
Summary
Add an overflow- and underflow-safe Euclidean norm to
Vector<const D: usize>.The existing
norm2_sq()deliberately computes the squared norm inf64andreturns a typed error when that square is not representable. Callers that need
the norm itself should not have to reimplement scaled
hypotaccumulation toavoid an unnecessary intermediate overflow or underflow.
This is additive stable-Rust work and is independent of the
generic_const_exprsredesign in #123.Downstream motivation:
delaunaydelaunaycurrently carries a publicgeometry::util::norms::hypothelper anduses 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 normis not representable as
f64.Requested contract
One possible surface is:
The operation should:
justified algorithm;
0.0for the zero-dimensional and all-zero vectors;LaErrorwhen the mathematical result cannot be representedas a finite
f64;exactfeature;norm2_sq()unchanged for callers that genuinely need a squared norm.Acceptance criteria
D=0 through D=8.
overflow values, and finite inputs whose norm is or is not representable.
simple known answer is insufficient.
f64::hypot,the prior Delaunay scaled implementation, and appropriate peer-crate norms.
norm2()fromnorm2_sq()and states thenumerical contract precisely.
Downstream cleanup enabled
After release, Delaunay can adopt
Vector::norm2()and the existingVector::norm2_sq(), remove its hand-written generalizedhypotandsquared_normimplementations where their semantics match, and keep onlygeometry-level error mapping where needed.