bit manipulation on a float sign bit (optimize hack)

While tinkering on a faster sin(x) function - http://arduino.cc/forum/index.php/topic,69723.0.html - I noticed that negation of a float takes 1.5 micros, not very much but I use it twice in my code and 3 micros is 6.7% of my code. Then I wondered if I could just flip the sign bit with an x-or, and if so would it be faster?

So I made this sketch to test, // learned: The signbit of an arduino float is located in byte 4,

void setup()
{
  Serial.begin(115200);
  Serial.println("start");

  volatile float zz = 100;
  
  unsigned long before = micros();
  for (int i=0; i< 30000; i++)
  {
     *(((byte*) &zz)+3) |= 0x80;  // Force negative   zz = -fabs(zz); 
  }
  Serial.println((micros() - before)/30000.0);
  Serial.println(zz);
  
  before = micros();
  for (int i=0; i< 30000; i++)
  {
     *(((byte*) &zz)+3) &= 0x7F;  // force positive  zz = fabs(zz);
  }
  Serial.println((micros() - before)/30000.0);
  Serial.println(zz);
  
  before = micros();
  for (int i=0; i< 30001; i++)
  {
     *(((byte*) &zz)+3) ^= 0x80;  // equals  zz = -zz;
  }
  Serial.println((micros() - before)/30000.0);
  Serial.println(zz);
  
  before = micros();
  for (int i=0; i< 30000; i++)
  {
    zz = -zz;
  }
  Serial.println((micros() - before)/30000.0);
  Serial.println(zz);
}

void loop(){}

output, arduino 2009 (ide22, win7/64)

start
0.75
-100.00
0.75
100.00
0.75
-100.00
1.51
-100.00

==> Yes it works! twice as fast as the normal code,

Note: remember 0.75 microsec is just 12 instructions, so use this kind of optimization only if you are as desparate for cycles as me :wink:

Same way you can test if float is negative: if (zz<0)

zz = -100;
if (*(((byte*) &zz)+3) & 0x80) Serial.println("N");
else Serial.println("P");

Agree, not the most readable code :wink:

// not fully tested so all disclaimers apply