2

I have a C program which involves some floating-point literal that's defined by a macro. And - it just so happens that in a performance-critical part of the code, I need the ceiling of that floating-point number, as an integer (say, an int). Now, if it were an actual literal, then I would just manually take the ceiling and be done with it. But since it's a macro, I can't do that.

Naturally, ceilf(MY_DOUBLE_LITERAL) works, but - it's expensive. (int)(MY_DOUBLE_LITERAL) + 1 will also work... except if the literal is itself an integer, in which case it will be wrong.

So, is there some way - preprocessor macros are fine - to obtain the ceiling of MY_DOUBLE_LITERAL, or alternatively to determine whether it is an integer or not?

Notes:

  • I cannot perform the ceil() before the performance-critical part of the code, due to constraints I won't go into. Naturally if one can move computation outside of the performance-critical part or loop, that's always best, and thanks goes to @SpyrosK for mentioning that.
  • C99 preferred.
  • You may assume the literal is a double, i.e. a decimal number like 123.4 or an exponential-notation like 1.23e4.
7
  • C11 generics? Commented Feb 13, 2022 at 19:12
  • @pmg: 1. How would those help? 2. What do you think of my answer? Commented Feb 13, 2022 at 19:17
  • #define ceil_literal(X) _Generic((X), double: ceil, default: dummy_int)(X), but of course, not all C99 compilers support _Generic. Commented Feb 13, 2022 at 19:21
  • 2
    If it's floating-point literal, as you say, I'd think ceilf(MY_DOUBLE_LITERAL) would be optimized just as well. Commented Feb 13, 2022 at 19:30
  • @P.P: Make this an answer? Commented Feb 13, 2022 at 19:39

2 Answers 2

3

If your literal fits nicely within the int representation range, you will often be able to rely on compiler optimizations. clang and gcc, for example, will go as far as simply optimizing ceilf() away when it's provided a literal, so ceifl(MY_DOUBLE_LITERAL) will result in a literal being used and no time wasted at run-time.

If somehow that doesn't work with your compiler, you could use:

int poor_mans_ceil(double x)
{
    return (int) x + ( ((double)(int) x < x) ? 1 : 0);
}

which should be "easier" for a compiler to optimize. You can see this happening on GodBolt.


Having said that - Some compilers in more exotic setting might fail to optimize both ceil() and the function above. Example: NVIDIA's NVCC compiler for CUDA.

Sign up to request clarification or add additional context in comments.

1 Comment

To handle negative values as well, I suggest (int) x + ( ((double)(int) x < x) ? 1 : 0) -- or, as P.P suggested, just use ceil/ceilf which your compiler should be able to optimize away.
0

A solution could be to statically store the rounded float macro literal in a const variable outside the critical part of the code and use the precomputed int const value in the critical part. This will work as long as the float returned by the macro is always the same value.

1 Comment

Actually, in my case, this will not work, since all of the code I'm working on is the performance-critical part, for reasons I won't go into. I'll clarify this in the question and sorry for the bother.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.