Loading...
Pages: [1]   Go Down
Author Topic: bit manipulation on a float sign bit (optimize hack)  (Read 909 times)
0 Members and 1 Guest are viewing this topic.
Netherlands
Offline Offline
Tesla Member
***
Karma: 87
Posts: 9368
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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,
Code:
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 smiley-wink

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Netherlands
Offline Offline
Tesla Member
***
Karma: 87
Posts: 9368
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Same way you can test if float is negative:    if (zz<0)
Code:
 
zz = -100;
if (*(((byte*) &zz)+3) & 0x80) Serial.println("N");
else Serial.println("P");

Agree, not the most readable code smiley-wink

// not fully tested so all disclaimers apply
« Last Edit: August 20, 2011, 07:01:57 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Pages: [1]   Go Up
Print
 
Jump to: