Built-in power function
Is your feature request related to a problem? Please describe.
Some rather simple and not so uncommon operations involve raising a number to a certain power. One example is for bitwise operations: bit shifting (multiplying or dividing by powers of 2), bit masking (which uses shifting) - useful e.g. when dealing with UTF-8 or other similar types of data; and so on - those would be use cases for int ^ int operations (using an informal ^ notation for power). But float ^ float operations are also useful at times, e.g. to calculate the square root of a number (x ^ 0.5), which can be used whenever you need to work with things like distances, or you need to "revert" some power operation (among other possibilities).
However, those operations are not currently available and require manual implementation, which is simple for int ^ int (albeit likely slower than a native solution when used repeatedly with slightly larger exponents), but not so simple for float ^ float.
Describe the solution you'd like
I think something like builtins.pow x y would be nice. When x and y are both ints with y >= 0, an int is returned. When y is negative or one of them is a float (or both are), a float is returned. (Or something similar to that.)
We'd also have to handle the x == y == 0 case somehow, as well as attempts to calculate roots of negative numbers. In principle, throwing an error is a possibility.
Describe alternatives you've considered
You can currently implement int ^ int in pure Nix with recursion or by multiplying an entire list where the base is repeated exponent times. However, that does feel like some unnecessary overhead for this operation, which is often repeated many times when it's needed. Additionally, float ^ float wouldn't be as simple to implement (requiring some extra math) and would likely have more overhead. It feels like adding a fast, native and globally available function for power wouldn't harm the language, and would be overall positive.
Additional context (none)
Priorities
Add :+1: to issues you find important.
I was just looking to be doing some more complicated color math in my NixOS configuration and am a little astonished that there isn't any floating point arithmetic available at all seemingly...
Without having looked at the actual source code for Nix at all, but seeing as it seems to be largely implemented in C++, wouldn't it be trivial to simply expose everything available in math.h through builtins.math. or something like that?
(Related #8298).
I'm using a library which adds types for ipv4/ipv6/mac addresses and it requires some heavy calculations internally to allow simple arithmetic on addresses. It has to ship its own pow function and just using a few of these calculations will immediately triple my system evaluation time to several minutes, all because of the pow function. I'll probably have to remove all of these wonderful functions because the increased evaluation time is becoming a show-stopper.
I'd be very happy if there is any way at all to get this into nix as a builtin.
It has to ship its own
powfunction and just using a few of these calculations will immediately triple my system evaluation time to several minutes, all because of the pow function.
For reference, I am using the following implementation:
/*
Raises the `base` to the power of `power`.
Considering the small input size and the lack of a built-in power function [2],
this naive power implementation should satisfy reasonable performance
requirements.
Due to the lack of a modulo and bitwise AND operator, it is questionable whether
the recursive exponentiation by squaring [1] implementation would even be
faster.
[1]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
[2]: https://github.com/NixOS/nix/issues/10387
# Type
pow :: Number -> Number -> Number
# Arguments
base
: The base number to be raised.
power
: The exponent to raise `base` to.
# Examples
pow 2 5
=> 32
*/
pow = lib.fix (
self: base: power:
if power != 0
then base * (self base (power - 1))
else 1
);
I assume inlining lib.fix would marginally improve performance by removing one additional function call.
Yes, please include some more basic arithmetic operations, and bit manipulation operations!