lhahne
lhahne

Reputation: 6029

Compile-time trigonometry in C

I currently have code that looks like

while (very_long_loop) {
    ...
    y1 = getSomeValue();
    ...
    x1 = y1*cos(PI/2);
    x2 = y2*cos(SOME_CONSTANT);
    ...
    outputValues(x1, x2, ...);
}

the obvious optimization would be to compute the cosines ahead-of-time. I could do this by filling an array with the values but I was wondering would it be possible to make the compiler compute these at compile-time?

Edit: I know that C doesn't have compile-time evaluation but I was hoping there would had been some weird and ugly way to do this with macros.

Upvotes: 6

Views: 2111

Answers (8)

Christoph
Christoph

Reputation: 169563

If you're lucky, you won't have to do anything: Modern compilers do constant propagation for functions in the same translation unit and intrinsic functions (which most likely will include the math functions).

Look at the assembly to check if that's the case for your compiler and increase the optimization levels if necessary.

Upvotes: 7

maxschlepzig
maxschlepzig

Reputation: 39045

You assume that computing cos is more expensive than an access. Perhaps this is not true on your architecture. Thus you should do some testing (profiling) - as always with optimization ideas.

Upvotes: 1

FooF
FooF

Reputation: 4462

I am struck with awe by Christoph's answer above.

So nothing needs to be done in this case, where gcc has some knowledge about the math functions. But if you have a function (maybe implemented by you) which cannot be calculated by your C compiler or if your C compiler is not so clever (or you need to fill complicated data structures or some other reason) you can use some higher level language to act as macroprocessor. In the past, I have used eRuby for this purpose, but (ePerl should work very well too and is another obvious readily available and more or less comfortable choice.

You can specify make rules for transforming files with extension .eruby (or .eperl or whatever) to files with that extension stripped out so that, for example, if you write files module.c.eruby or module.h.eruby then make automatically knows how to generate module.c or module.h, respectively, and keeps them up-to-date. In your make rule you can easily add generation of comment that warns editing the file directly.

If you are using Windows or something similar, then I am out of my depths in explaining how to add support for running this transformation automatically for you by your favorite IDE. But I believe it should be possible, or you could just run make outside of your IDE whenever you need to change those .eruby (or whatever) files.

By the way, I have seen that with incredibly small lines of code I have seen eLua implemented to use Lua as a macro language. Of course any other scripting language with support for regular expressions and flexible layout rules should work as well (but Python is malsuited for this purpose due to strict white space rules).

Upvotes: 0

Pete Kirkham
Pete Kirkham

Reputation: 49311

If you check the code and the compiler is not hoisting the constant values out of the loop, then do so yourself.

If the arguments to the trig functions are constant as in your sample code, then either pre-compute them yourself, or make them static variables so they are only computed once. If they vary between calls, but are constant within the loop then move them to outside the loop. If they vary between iterations of the loop, then a look-up table may be faster, but if that is acceptable accuracy then implementing your own trig functions which halt the calculation at a lower accuracy is also an option.

Upvotes: 0

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272487

No, unfortunately.

I would recommend writing a little program (or script) that generates a list of these values (which you can then #include into the correct place), that is run as part of your build process.

By the way: cos(pi/2) = 0!

Upvotes: 1

Jens Gustedt
Jens Gustedt

Reputation: 78903

No, C doesn't have the concept of compile time evaluation of functions and not even of symbolic constants if they are of type double. The only way to have them as immediate operand would be to precompute them and then to define them in macros. This is the way the C library does it for pi for example.

Upvotes: 0

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798606

Instead of precomputing these values, it is possible to use global variables to hold the values, which would be computed once on program startup.

Upvotes: 0

Mitch Wheat
Mitch Wheat

Reputation: 300539

Nope. A pre-computed lookup table would be the only way. In fact, Cosine (and Sine) might even be implemented that way in your libraries.

Profile first, Optimise Later.

Upvotes: 1

Related Questions