query
On this page

floor

lib.trivial.floor

Primop
Docs pulled from | This Revision | 3 days ago


Nix manual

Takes 1 arguments

number

Rounds and converts number to the next lower NixInt value if possible, i.e. floor *number* <= *number* and *number* - floor *number* < 1.

An evaluation error is thrown, if there exists no such NixInt value floor *number*. Due to bugs in previous Nix versions an evaluation error might be thrown, if the datatype of number is a NixInt and if *number* < -9007199254740992 or *number* > 9007199254740992.

If the datatype of number is neither a NixInt (signed 64-bit integer) nor a NixFloat (IEEE-754 double-precision floating-point number), an evaluation error will be thrown.

Noogle detected

Aliases

Detected Type
floor :: Float -> Int

Implementation

This function is implemented in c++ and is part of the native nix runtime.

src/libexpr/primops.cc:1111

static void prim_floor(EvalState & state, const PosIdx pos, Value ** args, Value & v)
{
    auto value = state.forceFloat(
        *args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.floor");
    auto floorValue = floor(value);
    bool isInt = args[0]->type() == nInt;
    constexpr NixFloat int_min = std::numeric_limits<NixInt::Inner>::min(); // power of 2, so that no rounding occurs
    if (floorValue >= int_min && floorValue < -int_min) {
        v.mkInt(floorValue);
    } else if (isInt) {
        // a NixInt, e.g. INT64_MAX, can be rounded to -int_min due to the cast to NixFloat
        state
            .error<EvalError>(
                "Due to a bug (see https://github.com/NixOS/nix/issues/12899) the NixInt argument %1% caused undefined behavior in previous Nix versions.\n\tFuture Nix versions might implement the correct behavior.",
                args[0]->integer().value)
            .atPos(pos)
            .debugThrow();
    } else {
        state.error<EvalError>("NixFloat argument %1% is not in the range of NixInt", args[0]->fpoint())
            .atPos(pos)
            .debugThrow();
    }
    // `forceFloat` casts NixInt to NixFloat, but instead NixInt args shall be returned unmodified
    if (isInt) {
        auto arg = args[0]->integer();
        auto res = v.integer();
        if (arg != res) {
            state
                .error<EvalError>(
                    "Due to a bug (see https://github.com/NixOS/nix/issues/12899) a loss of precision occurred in previous Nix versions because the NixInt argument %1% was rounded to %2%.\n\tFuture Nix versions might implement the correct behavior.",
                    arg,
                    res)
                .atPos(pos)
                .debugThrow();
        }
    }
}

Implementation

The following is the current implementation of this function.

floor