summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThomas Hartmann <Thomas.Hartmann@nokia.com>2011-11-10 11:16:56 +0100
committerQt by Nokia <qt-info@nokia.com>2011-11-11 09:16:21 +0100
commite82b120410820e978b87b0a0f3b99718f3671fb1 (patch)
tree535869d543ded89ac08c653305f6bb3ffb717eb3 /src
parent64c8691548d357d34521ec698050cf4d442eee3d (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.cpp39
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)