Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix invalid casts in is/2 #2777

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

adri326
Copy link
Contributor

@adri326 adri326 commented Jan 17, 2025

This fixes #2772 and a few of other issues I found:

  • rnd_i would first convert big floats into an i64, before converting them into an IBig
  • round/1 would add 0.5 to big integers, losing precision beyond ±2 ^ 53
  • gcd/2 would attempt to cast its second argument to an isize before computing the gcd using IBig::gcd, triggering a panic!()
  • min/2 and max/2 would return the float version of their arguments if their types didn't match

This PR is accompanied by a test suite (that @UWN might be interested in) for the behavior of is/2, both after being compiled and being metacalled. Implementation-specific behavior (like bitshifting negative numbers) is excluded from this test suite.

I ran the integration tests with cargo-tarpaulin to get a report and help me find uncovered edge cases. I chose not to test special cases like pow(integer, integer), since it's unclear to me whether or not small Number::Integer should be returned from computations (like X is 2 ^ 64 - 2 ^ 64).

Each of these changes (including the addition of the new test suite) were placed in their own commits.

Fixes mthom#2772.

The current implementation of `rnd_i` incorrectly casts `f` (an `f64`)
into an `i64`, before casting it into an `Integer`.

This fixes that issue by using `Integer::try_from(f)` instead.
@adri326
Copy link
Contributor Author

adri326 commented Jan 17, 2025

(might as well fix round/1 while I'm at it)

The original issue can be reproduced with `X is round(2 ^ 54 + 1) - 2 ^ 54, X = 1.`
@adri326 adri326 force-pushed the fix-2772-rnd_i-clipping branch from 508e901 to a739390 Compare January 17, 2025 22:44
@triska
Copy link
Contributor

triska commented Jan 18, 2025

Thank you a lot, this is ideal: With this I can address #2771 entirely in Prolog, based on solid underlying functionality in the core!

The implementation for gcd/2 would cast the second argument to an isize.
@adri326 adri326 changed the title Fix rnd_i clipping floats that don't fit in Fixnum Fix invalid casts in is/2 Jan 20, 2025
It now behaves the same way as SWI-Prolog.
This extensively tests the behavior of is/2, both when compiled and in metacalls.
@adri326 adri326 force-pushed the fix-2772-rnd_i-clipping branch from 1afa051 to 3b6c209 Compare January 20, 2025 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

truncate/1 incorrect
2 participants