diff options
author | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2011-11-10 11:16:56 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-11-11 09:16:21 +0100 |
commit | e82b120410820e978b87b0a0f3b99718f3671fb1 (patch) | |
tree | 535869d543ded89ac08c653305f6bb3ffb717eb3 /src | |
parent | 64c8691548d357d34521ec698050cf4d442eee3d (diff) |
avoid type aliasing
For -O2 gcc activates -fstrict-aliasing. As a result the compiler is
allowed to assume that pt[1]=px[1]/3+B1 does not affect t.
Therefore the result of _fast_cbrt() was always 0.
Using a union for casting avoids this issue.
For more details see:
http://labs.qt.nokia.com/2011/06/10/type-punning-and-strict-aliasing
Also the updated code respect endianness.
Change-Id: Id4bed16efac52e494e7357dc2f23f94e8c525df1
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/tools/qeasingcurve.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 231c2655d4..a1b51e6f9a 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -628,19 +628,40 @@ struct BezierEase : public QEasingCurveFunction float static inline _fast_cbrt(float x) { - int& i = (int&) x; - i = (i - (127<<23)) / 3 + (127<<23); - return x; + union { + float f; + quint32 i; + } ux; + + const unsigned int B1 = 709921077; + + ux.f = x; + ux.i = (ux.i / 3 + B1); + + return ux.f; } double static inline _fast_cbrt(double d) { - const unsigned int B1 = 715094163; - double t = 0.0; - unsigned int* pt = (unsigned int*) &t; - unsigned int* px = (unsigned int*) &d; - pt[1]=px[1]/3+B1; - return t; + union { + double d; + quint32 pt[2]; + } ut, ux; + + const unsigned int B1 = 715094163; + +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + const int h0 = 1; +#else + const int h0 = 0; +#endif + ut.d = 0.0; + ux.d = d; + + quint32 hx = ux.pt[h0]; //high word of d + ut.pt[h0] = hx / 3 + B1; + + return ut.d; } qreal static inline _acos(qreal x) |