When refracting a particular piece of C++ code that converted radians to degrees, it was suggested by a friend that I swap the order of the operations in the function as it would increase performance. I thought it would be interesting to actually see if this was the case, consider;

define PI 3.1415
double torad1(double n) {
return n * 180 / PI;
}

The assembler code produced by g++ 4.8 looks like this:

.LCPI0_0:
.quad 4640537203540230144 # double 180
.LCPI0_1:
.quad 4614256447914709615 # double 3.1415
torad1(double):
mulsd .LCPI0_0(%rip), %xmm0
divsd .LCPI0_1(%rip), %xmm0
ret

Notice the presence of a division operation. The compiler has conformed with what it has been taught, that floating point maths is not associative. The interesting part is that by swapping the order of the operations, the two constants can be folded;

define PI 3.1415
double torad2(double n) {
return 180 / PI * n;
}

Which produces assembler like this;

.LCPI1_0:
.quad 4633260719236591239 # double 57.29746936176985
torad2(double):
mulsd .LCPI1_0(%rip), %xmm0
ret

Notice how it has converted the division into a single multiplication of `n`

by `180 / PI`

? This is an interesting subtlety that I will be paying more attention to when I write code from now on.

If you’re using gcc/clang and would like to see how much faster your code would be if floating point operations were associative, but you’d rather not rewrite any code, you can compile using the `-ffast-math`

flag, which disables this behaviour. For full documentation on the flag, see here.

### Like this:

Like Loading...

Hai

I kind of expected that. The compiler pre-calculates operations with constants such as something that contains PI / 180. But it’s pretty interesting that the optimization only works with this operation order.

You could probably also write “n * (180 / PI)”.

Yes, that would work fine.