Home > Software engineering >  Compile-time ceiling function, for literals, in C?
Compile-time ceiling function, for literals, in C?

Time:02-14

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.

CodePudding user response:

If your literal fits nicely within the int representation range, you will often be able to rely on compiler optimizations. Use:

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

And it should be computed at compile-time with compiler optimizations enabled.

See some examples: GodBolt

Caveat If you're compiling in a more exotic setting, the compiler might fail you. For example, the above won't be optimized away with CUDA's NVCC.

CodePudding user response:

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.

  • Related