As a part of particle system simulating gravitation and collisions between many objects I came across a strange bug.
This is a school project aimed at optimization through vectorization (OpenMP SIMD) and as a part of the optimizations I wanted to get rid of following expression:
if (r > COLLISION_DISTANCE) {
resultVelX += gravityVelX;
// ... same for remaining dimensions
}
if (r > 0.f && r < COLLISION_DISTANCE) {
resultVelX += collisionVelX;
// ... same for remaining dimensions
}
My idea was to capture both conditions in variables and then add values to result without ifs, using simple arithmetics:
const int condGrav = (r > COLLISION_DISTANCE);
const int condCol = (r > 0.f && r < COLLISION_DISTANCE);
resultVelX += condGrav * gravityVelX + condCol * collisionVelX;
// ... same for remaining dimensions
We have been given a set of tests for this project and to my surprise, while simple tests passed in both versions of code, in the most complex cases, it failed for the second version, reporting infinite precision error (e+616 as I found out from the most informative logs).
All computations are done on floats. Compilation is done with intel 2016a compiler icpc.
Question: What is wrong with the second piece of code? Is it just wrong or there is something to floats themselves I am missing?