cmpute/dashu

round mode HalfUp

Closed this issue · 3 comments

I'm trying to implement this behavior with Dashu:

https://www.w3.org/TR/xpath-functions-31/#func-round

If two such values are equally near (for example, if the fractional
part in $arg is exactly .5), the function returns the one that is
closest to positive infinity."

While dashu implements a rounding mode HalfAway, I think this requires HalfUp. Alternatively I take the absolute value, use HalfAway, and then reapply the sign, but that seems cumbersome.

cmpute commented

I don't plan to add that rounding mode to Dashu now, because this rounding mode is rather rarely used. You can implement the rounding mode in your application, because the requirement for the rounding mode is just to implement the Round trait.

Please refer to

dashu/float/src/round.rs

Lines 288 to 321 in 4329c5c

impl Round for mode::HalfAway {
type Reverse = Self;
#[inline]
fn round_low_part<F: FnOnce() -> Ordering>(
integer: &IBig,
low_sign: Sign,
low_half_test: F,
) -> Rounding {
match low_half_test() {
// |rem| < 1/2
Ordering::Less => Rounding::NoOp,
// |rem| = 1/2
Ordering::Equal => {
// +1 if integer and rem >= 0, -1 if integer and rem <= 0
if integer >= &IBig::ZERO && low_sign == Sign::Positive {
Rounding::AddOne
} else if integer <= &IBig::ZERO && low_sign == Sign::Negative {
Rounding::SubOne
} else {
Rounding::NoOp
}
}
// |rem| > 1/2
Ordering::Greater => {
// +1 if rem > 0, -1 if rem < 0
match low_sign {
Sign::Positive => Rounding::AddOne,
Sign::Negative => Rounding::SubOne,
}
}
}
}
}
for an implementation example.

Thanks for the tip! Given that the rounding mode is rarely used, I now wonder how this spec ended up with it - seems a strange one to pick.

cmpute commented

I have the same question... It's so counter-intuitive