diff options
author | sterni <sternenseemann@systemli.org> | 2023-08-05T14·07+0200 |
---|---|---|
committer | sterni <sternenseemann@systemli.org> | 2023-08-09T12·12+0000 |
commit | 55a3b3eb81a1c37b0c5345e68c03520c85564e3d (patch) | |
tree | fed17501809109ab90e8324732fdc68a32f1fee5 /users/sterni/nix | |
parent | 984ea69386a47e753c4129e2a6230aa60b4584cd (diff) |
feat(sterni/nix): add trivial float library r/6478
Only implements the different conversion types from and to ints for now. Unfortunately very reliant on builtins.{floor,ceil} which can't be implemented purely except very inefficiently (to my knowledge), so it only really works for C++ Nix >= 2.4. Tests are thus skipped for C++ Nix 2.3. Change-Id: Idcb1a11df11e214cdba3f2a0715472b370daa7dc Reviewed-on: https://cl.tvl.fyi/c/depot/+/9008 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'users/sterni/nix')
-rw-r--r-- | users/sterni/nix/float/default.nix | 23 | ||||
-rw-r--r-- | users/sterni/nix/float/tests/default.nix | 49 | ||||
-rw-r--r-- | users/sterni/nix/num/default.nix | 1 |
3 files changed, 73 insertions, 0 deletions
diff --git a/users/sterni/nix/float/default.nix b/users/sterni/nix/float/default.nix new file mode 100644 index 000000000000..ecb6465c8842 --- /dev/null +++ b/users/sterni/nix/float/default.nix @@ -0,0 +1,23 @@ +{ depot, ... }: + +let + inherit (depot.users.sterni.nix) + num + ; +in + +rec { + # In C++ Nix, the required builtins have been added in version 2.4 + ceil = builtins.ceil or (throw "Nix implementation is missing builtins.ceil"); + floor = builtins.floor or (throw "Nix implementation is missing builtins.floor"); + + truncate = f: if f >= 0 then floor f else ceil f; + round = f: + let + s = num.sign f; + a = s * f; + in + s * (if a >= floor a + 0.5 then ceil a else floor a); + + intToFloat = i: i * 1.0; +} diff --git a/users/sterni/nix/float/tests/default.nix b/users/sterni/nix/float/tests/default.nix new file mode 100644 index 000000000000..75e2a1bfa091 --- /dev/null +++ b/users/sterni/nix/float/tests/default.nix @@ -0,0 +1,49 @@ +{ depot, lib, ... }: + +let + + inherit (depot.nix.runTestsuite) + runTestsuite + it + assertEq + ; + + inherit (depot.users.sterni.nix) + float + ; + + testsBuiltins = it "tests builtin operations" [ + (assertEq "ceil pos" (float.ceil 1.5) 2) + (assertEq "ceil neg" (float.ceil (-1.5)) (-1)) + (assertEq "floor pos" (float.floor 1.5) 1) + (assertEq "floor neg" (float.floor (-1.5)) (-2)) + ]; + + testsConversionFrom = it "tests integer to float conversion" [ + (assertEq "float.intToFloat is identity for floats" (float.intToFloat 1.3) 1.3) + (assertEq "float.intToFloat converts ints" + (builtins.all + (val: builtins.isFloat val) + (builtins.map float.intToFloat (builtins.genList (i: i - 500) 1000))) + true) + ]; + + exampleFloats = [ 0.5 0.45 0.3 0.1 200 203.457847 204.65547 (-1.5) (-2) (-1.3) (-0.45) ]; + testsConversionTo = it "tests float to integer conversion" [ + (assertEq "round" + (builtins.map float.round exampleFloats) + [ 1 0 0 0 200 203 205 (-2) (-2) (-1) 0 ]) + (assertEq "truncate towards zero" + (builtins.map float.truncate exampleFloats) + [ 0 0 0 0 200 203 204 (-1) (-2) (-1) 0 ]) + ]; +in + +runTestsuite "nix.num" ([ + testsConversionFrom +] + # Skip for e.g. C++ Nix < 2.4 +++ lib.optionals (builtins ? ceil && builtins ? floor) [ + testsConversionTo + testsBuiltins +]) diff --git a/users/sterni/nix/num/default.nix b/users/sterni/nix/num/default.nix index 640493083722..81e2f8377f3b 100644 --- a/users/sterni/nix/num/default.nix +++ b/users/sterni/nix/num/default.nix @@ -8,6 +8,7 @@ rec { sub ; + sign = i: if i < 0 then -1 else 1; abs = i: if i < 0 then -i else i; inRange = a: b: x: x >= a && x <= b; |