From e82b120410820e978b87b0a0f3b99718f3671fb1 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 10 Nov 2011 11:16:56 +0100 Subject: 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 Reviewed-by: Thiago Macieira --- src/corelib/tools/qeasingcurve.cpp | 39 +++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src/corelib/tools/qeasingcurve.cpp') 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) -- cgit v1.2.3