Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for a constexpr ceil function

Since std:ceil is non-constexpr neither in Visual Studio 2015, I'm looking for a constexpr implementation of it which I can use compile-time - with little success.

Any help is appreciated.

like image 705
plasmacel Avatar asked Aug 11 '15 21:08

plasmacel


3 Answers

Here's a version building on Jarod42's excellent answer by eliminating one of the two branches. This'll work on C++14 or C++17—if you inline the integer cast, you can make it support C++11 as well.

constexpr int int_ceil(float f)
{
    const int i = static_cast<int>(f);
    return f > i ? i + 1 : i;
}

Here's a small suite to verify the correct behavior. (Just a series of C++17 static_assert()s, since the function is constexpr—if it compiles, you know the tests passed!)

static_assert(int_ceil(0.0) == 0);
static_assert(int_ceil(0.5) == 1);
static_assert(int_ceil(0.999999) == 1);
static_assert(int_ceil(1.0) == 1);
static_assert(int_ceil(123.0) == 123);
static_assert(int_ceil(123.4) == 124);

static_assert(int_ceil(-0.5) == 0);
static_assert(int_ceil(-0.999999) == 0);
static_assert(int_ceil(-1.0) == -1);
static_assert(int_ceil(-123.0) == -123);
static_assert(int_ceil(-123.4) == -123);

Here's a Compiler Explorer sample to play with (as a bonus, it includes a constexpr implementation of floor() as well).

like image 188
s3cur3 Avatar answered Nov 03 '22 08:11

s3cur3


Since the compiler of Visual Studio 2015 still doesn't allow for a constexpr function to have if conditionals and variables, I rewrote Jarod42's solution and eliminated them:

constexpr int32_t ceil(float num)
{
    return (static_cast<float>(static_cast<int32_t>(num)) == num)
        ? static_cast<int32_t>(num)
        : static_cast<int32_t>(num) + ((num > 0) ? 1 : 0);
}
like image 25
plasmacel Avatar answered Nov 03 '22 07:11

plasmacel


You may use

constexpr std::int32_t ceil(float num) {
    std::int32_t inum = static_cast<std::int32_t>(num);
    if (num == static_cast<float>(inum)) {
        return inum;
    }
    return inum + (num > 0 ? 1 : 0);
}

Live demo

Note: Doesn't work once an integer cannot represent float value.

like image 7
Jarod42 Avatar answered Nov 03 '22 07:11

Jarod42