From 3e331d4cf0b05f1983e760e397a400456ead9e4b Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 22 Jan 2026 21:52:06 +0200 Subject: [PATCH] math: rewrite hypot(), update tests (#26418) --- vlib/math/hypot.v | 34 ++++++++++++++++++---------------- vlib/math/math_test.v | 5 +++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/vlib/math/hypot.v b/vlib/math/hypot.v index f4200bdde..3fecd9816 100644 --- a/vlib/math/hypot.v +++ b/vlib/math/hypot.v @@ -1,25 +1,27 @@ module math -// hypot returns the hypotenuse of the triangle give two sides +// hypot returns the hypotenuse of the triangle give two sides. +// +// special cases are: +// hypot(±inf, y) = +inf +// hypot(x, ±inf) = +inf +// hypot(nan, y) = nan +// hypot(x, nan) = nan pub fn hypot(x f64, y f64) f64 { - if is_inf(x, 0) || is_inf(y, 0) { + mut p := abs(x) + mut q := abs(y) + if is_inf(p, 1) || is_inf(q, 1) { return inf(1) } - if is_nan(x) || is_nan(y) { + if is_nan(p) || is_nan(q) { return nan() } - mut result := 0.0 - if x != 0.0 || y != 0.0 { - abs_x := abs(x) - abs_y := abs(y) - cmin, cmax := minmax(abs_x, abs_y) - rat := cmin / cmax - root_term := sqrt(1.0 + rat * rat) - if cmax < max_f64 / root_term { - result = cmax * root_term - } else { - panic('overflow in hypot_e function') - } + if p < q { + p, q = q, p } - return result + if p == 0.0 { + return 0.0 + } + q = q / p + return p * sqrt(1 + q * q) } diff --git a/vlib/math/math_test.v b/vlib/math/math_test.v index ea7d9671f..88245d814 100644 --- a/vlib/math/math_test.v +++ b/vlib/math/math_test.v @@ -658,10 +658,11 @@ fn test_hypot() { [inf(1), inf(-1)], [inf(1), 0], [inf(1), inf(1)], [inf(1), nan()], [nan(), inf(-1)], [nan(), 0], [nan(), inf(1)], [nan(), - nan()]] + nan()], + [-0.0, max_f64]] hypot_sc_ := [inf(1), inf(1), inf(1), inf(1), 0, 0, 0, 0, inf(1), inf(1), nan(), inf(1), inf(1), inf(1), inf(1), inf(1), - nan(), inf(1), nan()] + nan(), inf(1), nan(), max_f64] for i := 0; i < vfhypot_sc_.len; i++ { f := hypot(vfhypot_sc_[i][0], vfhypot_sc_[i][1]) assert alike(hypot_sc_[i], f) -- 2.39.5