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> { pub(crate) fn round(num: Number, arena: &mut Arena) -> Result<Number, MachineStubGen> {
let stub_gen = || { let res = match num {
let is_atom = atom!("is"); Number::Fixnum(_) | Number::Integer(_) => num,
functor_stub(is_atom, 2) 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); // FIXME: make round/1 return EvalError
let result = try_numeric_result!(result, stub_gen)?; 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> { pub(crate) fn bitwise_complement(n1: Number, arena: &mut Arena) -> Result<Number, MachineStubGen> {