Less puzzled
Some weeks ago, I made a posting in which I presented some code and then considered how it might be optimized and asked for input from readers. I was confident that I would not have found every possibility. Indeed, there were some useful comments, which I really appreciated. [It is nice to know that there is someone out there!]
Apart from the comments, I had an email from Michael Luber in Germany, who looked at the problem in some detail. With his permission, I have reproduced his results here …
I also like puzzles very much and, therefore, I would like to comment on this post.
I played around a bit and also found that much of what I could think of would probably addressed by most compilers.
However, in the end, I came up with this:
/*******************************************************************/
#define ITERATIONS 50
int mandelbrot(float a)
{
int i;
float b = a;
for (i=0; i<ITERATIONS; i++)
{
if (*((unsigned int*) &b) & (unsigned int)0x40000000)
{
return i;
}
b = b * b + a;
}
return i;
}
/*******************************************************************/
Here is what I considered:
- Some compilers might initialize all uninitialized auto variables with zero, so I preferred to put a declaration of b with the assignment of a to it as a single statement. (As Peter already did).
- I would rather let the variable i run from zero to (ITERATIONS – 1). This may save initializing it (see above), and saves the subtraction of 1 in the return statement.
- This also allows i to be returned instead of ITERATIONS, if the for-loop runs to completion, which may save loading the constant ITERATIONS into a register (assuming i already is in a register).
- For checking if the absolute value of a float is greater than 2, I just check for the second bit is set, which should work considering how floats are represented in memory. Of course, this “hack” introduces a hardware dependency, which is generally not a good idea. However, if the requirement is for performance above all, I could consider that. On x86-gcc, this trick reduces the check to a total of four instructions, including those for loading the float from stack as well as the conditional jump:
mov -0x8(%ebp),%eax
and $0x40000000,%eax
test %eax,%eax
je 0x4010bd
Maybe I would put this in a macro and add some compile-time checks to be safe, in case the compiler changes, or I go to 64-bit or something like that.
I’m also aware that my code checks for >=2 instead of >2, but when it comes to comparison of floating point numbers, this seems acceptable.