m5stack / M5StickC

M5StickC Arduino Library
MIT License
477 stars 222 forks source link

Fixed wrong result of invSqrt #41

Closed tanakamasayuki closed 5 years ago

tanakamasayuki commented 5 years ago

test code

#include <M5StickC.h>

float invSqrt(float x) {
  float halfx = 0.5f * x;
  float y = x;
  long i = *(long*)&y;
  i = 0x5f3759df - (i>>1);
  y = *(float*)&i;
  y = y * (1.5f - (halfx * y * y));
  return y;
}

float invSqrt2(float x) {
  return sqrt(x);
}

void setup(){
  M5.begin();

  for( float i = 0 ; i < 5 ; i+=0.5 ){
    Serial.printf( "i = %f, invSqrt() = %f, invSqrt2() = %f\n", i, invSqrt(i), invSqrt2(i) );
  }

}

void loop() {
}

output

M5StickC initializing...OK
i = 0.000000, ret = 19817753709685768192.000000, ret2 = 0.000000
i = 0.500000, ret = 1.413860, ret2 = 0.707107
i = 1.000000, ret = 0.998307, ret2 = 1.000000
i = 1.500000, ret = 0.815363, ret2 = 1.224745
i = 2.000000, ret = 0.706930, ret2 = 1.414214
i = 2.500000, ret = 0.631372, ret2 = 1.581139
i = 3.000000, ret = 0.576847, ret2 = 1.732051
i = 3.500000, ret = 0.534428, ret2 = 1.870829
i = 4.000000, ret = 0.499154, ret2 = 2.000000
i = 4.500000, ret = 0.471356, ret2 = 2.121320
EeeeBin commented 5 years ago

https://en.wikipedia.org/wiki/Fast_inverse_square_root, invSqrt is no problem

tanakamasayuki commented 5 years ago

Actual results are different.

\Arduino\libraries\M5StickC\src\utility\MahonyAHRS.cpp: In function 'float invSqrt(float)':
\Arduino\libraries\M5StickC\src\utility\MahonyAHRS.cpp:244:20: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  long i = *(long*)&y;
                    ^

\Arduino\libraries\M5StickC\src\utility\MahonyAHRS.cpp:246:16: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  y = *(float*)&i;
                ^

There is a compiler warning. Probably broken by optimization.

EeeeBin commented 5 years ago

invSqrt(float x) ~= 1 / sqrt(x)

tanakamasayuki commented 5 years ago

Sorry