NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.94k stars 1.53k forks source link

Improve representation for "floats" and fix repro bugs #8274

Open roberth opened 1 year ago

roberth commented 1 year ago

Describe the bug

Native floating point

Native CPU floating point operations are not suitable for a portable deterministic language because they can produce slightly different results on different platforms or with different compiler settings due to variations in the precision and range of the floating point numbers used, as well as rounding errors. Portable deterministic languages aim to produce identical results on different platforms and with different compiler settings, so they typically use fixed-point or arbitrary-precision arithmetic libraries instead.

C++ footgun

Furthermore their printing has accidentally changed recently. Floats are too easy to use in ways that are not portable and deterministic.

Steps To Reproduce

Expected behavior

Some ideas.

Arbitrary precision library

The rational numbers support all the operations we already support in the language:

I suspect that we can use a fairly small library for our purposes.

We already have OpenSSL bignum at our disposal for no extra dependency cost, but that's only an integer library. Boost and GNU libgmp provide rational number support but should be evaluated for our specific toString needs.

newtype

Use a C++ type that doesn't expose non-deterministic behavior, like NixFloat = double does.

This is also useful for limiting the boost overhead to a single file if needed.

nix-env --version output

Additional context

Priorities

Add :+1: to issues you find important.

yorickvP commented 1 year ago

All of nix's floating point operations are already defined precisely (they are ieee754 float64's), except for printing.

My idea was to fully add (a variant of) ryu to print nicely while preserving precision.

We are working on a versioning RFC to make these backwards-incompatible changes possible in the future (cc @fricklerhandwerk).

vcunat commented 1 year ago

I heard that some embedded platforms don't implement floats precisely according to ieee754, but I don't expect we need to be bothered by that, with Nix evals being quite expensive in practice.

Side note: I think there's generally too much FUD around floats. All operations doable on 32-bit integers are done without any loss of precision on 64-bit floats (with quite a few bits to spare). Yes, even the textbook counter-examples with floating-point control variable in a for loop...

flokli commented 1 year ago

Linking https://github.com/NixOS/nix/issues/5733#issuecomment-1529002378 as it's relevant.