-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Nix language: inconsistent handling of numbers #12899
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
Comments
That may be possible.
I have no idea which behavior is preferable.
Fixing this is technically a breaking change, but if you write
Don't know what to think of this.
Better to throw an error than be sneaky.
This is already a problem for numbers within the 64-bit range if you make the additional assumption that the bounds are reasonable.
|
This is another problem... The right behavior would be to pass through all Nix integers, if the functions shall return a Nix integer. Another problem when rounding is the rounding mode. Here, we can just hope that it is "round to nearest even" on all architectures and that no library or other part of the Nix binary changes it because it is global state. |
I don't think that this is a breaking change because |
We kind of have to assume that ends up in a derivation though. We've made that mistake, and I would not like to repeat it. |
On a related note: You cannot represent int64 min in nix as a literal. My guess is that the parser only parses the positive part and then negates the result by applying an operation instead of parsing the number directly:
|
Uh oh!
There was an error while loading. Please reload this page.
Describe the bug
After noticing #12848 I started to investigate other strange corner cases of the Nix language related to numbers. This issue lists several corner cases, which should be either documented or fixed.
Handling of
0.0
1.
1.
is parsed as1.0
(here, I'm adding the point to indicate a Nix float), while0.
isn't parsed, i.e.Expected behavior:
0.
should be parsed as0.0
2.
1 / 0.0
throws an error instead of returninginf
:Computing
1. / (1. / x)
throws an error, ifx = inf
orx = -inf
.inf
can be generated easily:3.
-0.0
is parsed as0.0
. This is not nice because-0.0
can be generated easily, i.e.Probably this cannot cause unexpected behavior at the moment because division by
0.0
throws an error.Nevertheless I think that it makes sense to have consistent
IEEE754
doubles.Handling of subnormal numbers
Parsing subnormal numbers throws an error, e.g.
but they can be generated easily, e.g.
The question is: Which behavior is appropriate?
builtins.ceil
andbuiltins.floor
are brokenWhen applying these functions to a Nix float, which is outside of the range of the Nix integer type, then
-9223372036854775808 = INT64_MIN = -2^63
is returned, e.g.This makes no sense because the next smaller integer would be
INT64_MAX = 2^63 - 1 = 9223372036854775807
forbuiltins.floor
. Probablybuiltins.ceil
should throw an error instead because there is no integer greater or equal to1e200
, if the return type shall be an integer.Applying these functions to
inf
,-inf
orNaN
returns BS, too:This should throw an error instead.See below.The next question is why these functions don't return a Nix float.
ceil
andfloor
in other languages don't return an integer type.EDIT: After analyzing the source code, these cases are UB because a
double
is casted toint64
and the observed behavior is probably specific tox86-64
. This shall be fixed.Throwing an error when the argument is outside of the range of integers or
NaN
is one solution. Then| floor(x) - x | < 1
would hold for every Nix floatx
(ceil
is analogous).Or the behavior can be saturating, i.e.
floor(x) = 2^63-1
for all Nix floatsx >= 2^63
. The drawback is that| floor(x) - x |
wouldn't be bounded anymore.Metadata
nix (Nix) 2.26.2
Additional context
Checklist
Add 👍 to issues you find important.
The text was updated successfully, but these errors were encountered: