Skip to content

Commit 952ae4d

Browse files
authored
math: rewrite round() to match closely the Go version (and mpfr's one), update test (#26381)
1 parent 052d862 commit 952ae4d

File tree

2 files changed

+19
-18
lines changed

2 files changed

+19
-18
lines changed

vlib/math/floor.v

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,25 @@ pub fn trunc(x f64) f64 {
7777
// round(±inf) = ±inf
7878
// round(nan) = nan
7979
pub fn round(x f64) f64 {
80-
if x == 0 || is_nan(x) || is_inf(x, 0) {
81-
return x
82-
}
83-
// Largest integer <= x
84-
mut y := floor(x) // Fractional part
85-
mut r := x - y // Round up to nearest.
86-
if r > 0.5 {
87-
y += 1.0
88-
return y
89-
}
90-
// Round to even
91-
if r == 0.5 {
92-
r = y - 2.0 * floor(0.5 * y)
93-
if r == 1.0 {
94-
y += 1.0
80+
mut bits := f64_bits(x)
81+
mut e_ := (bits >> shift) & mask
82+
if e_ < bias {
83+
// Round abs(x) < 1 including denormals.
84+
bits &= sign_mask // +-0
85+
if e_ == bias - 1 {
86+
bits |= uvone // +-1
9587
}
88+
} else if e_ < bias + shift {
89+
// Round any abs(x) >= 1 containing a fractional component [0,1).
90+
//
91+
// Numbers with larger exponents are returned unchanged since they
92+
// must be either an integer, infinity, or NaN.
93+
half := u64(1) << (shift - 1)
94+
e_ -= bias
95+
bits += half >> e_
96+
bits &= ~(frac_mask >> e_)
9697
}
97-
// Else round down.
98-
return y
98+
return f64_from_bits(bits)
9999
}
100100

101101
// Returns the rounded float, with sig_digits of precision.

vlib/math/math_test.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,8 @@ fn test_round() {
847847
f := round(vf_[i])
848848
assert alike(round_[i], f)
849849
}
850-
vfround_sc_ := [[f64(0), 0], [nan(), nan()], [inf(1), inf(1)]]
850+
vfround_sc_ := [[f64(0), 0], [-0.5, -1.0], [nan(), nan()],
851+
[inf(1), inf(1)]]
851852
// vfround_even_sc_ := [[f64(0), 0], [f64(1.390671161567e-309), 0], // denormal
852853
// [f64(0.49999999999999994), 0], // 0.5-epsilon [f64(0.5), 0],
853854
// [f64(0.5000000000000001), 1], // 0.5+epsilon [f64(-1.5), -2],

0 commit comments

Comments
 (0)