Fix round() losing precision on bigints

The original issue can be reproduced with `X is round(2 ^ 54 + 1) - 2 ^ 54, X = 1.`
This commit is contained in:
Emilie Burgun
2025-01-17 23:33:09 +01:00
parent 9420c7e41e
commit d3361c16d8

View File

@@ -1072,16 +1072,22 @@ pub(crate) fn truncate(n: Number, arena: &mut Arena) -> Number {
}
}
pub(crate) fn round(n: Number, arena: &mut Arena) -> Result<Number, MachineStubGen> {
let stub_gen = || {
let is_atom = atom!("is");
functor_stub(is_atom, 2)
pub(crate) fn round(num: Number, arena: &mut Arena) -> Result<Number, MachineStubGen> {
let res = match num {
Number::Fixnum(_) | Number::Integer(_) => num,
Number::Rational(rat) => Number::arena_from(rat.round(), arena),
Number::Float(f) => Number::Float(OrderedFloat((*f).round())),
};
let result = add(n, Number::Float(OrderedFloat(0.5f64)), arena);
let result = try_numeric_result!(result, stub_gen)?;
// FIXME: make round/1 return EvalError
rnd_i(&res, arena).map_err(|err| -> MachineStubGen {
Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(err);
let stub = functor_stub(atom!("round"), 1);
Ok(floor(result, arena))
machine_st.error_form(eval_error, stub)
})
})
}
pub(crate) fn bitwise_complement(n1: Number, arena: &mut Arena) -> Result<Number, MachineStubGen> {