From f91f464ec8ad499678a253c03397180c033f1b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Apr 2013 18:36:53 +0200 Subject: [PATCH] GCC 4.4 compatibility: better solution for explicit conversion of Unit. Having implicit conversion on Unit class causes much more harm than doing the conversion some other way -- mainly for multiplication and division, which is done with builtin operators and thus the result is unitless. Also it is possible to do wrong "retyping" between degrees and radians: Rad a = Constants::pi(); Deg b(a*2); On GCC >4.5 b is `180`, but on GCC 4.4 it is `2pi`, which is obviously wrong and not wanted. The conversion is done using Unit::toUnderlyingType() which is now used everywhere instead of conversion operator. The conversion operator is made available only for GCC 4.5, where it can be marked as explicit. This might cause incompatibilites with `master` branch, where no Unit::toUnderlyingType() exists, but users should have no need to convert it to underlying type anyway as all required functions are available through the library. This reverts commit 36ac4de5c4ae2af654c3490f5b25c20e086258b7 and partially also 0db3a183ae12e1287dda3da203b9d092bab6c1b3 (UnitTest.cpp). --- src/Color.h | 6 +++--- src/Math/Angle.h | 8 ++++---- src/Math/Complex.h | 2 +- src/Math/Functions.h | 6 +++--- src/Math/Matrix3.h | 4 ++-- src/Math/Matrix4.h | 18 +++++++++--------- src/Math/Quaternion.h | 2 +- src/Math/Test/AngleTest.cpp | 22 +++++++++++----------- src/Math/Test/FunctionsTest.cpp | 16 ++++++++-------- src/Math/Test/UnitTest.cpp | 19 +++---------------- src/Math/Unit.h | 12 +++--------- src/Primitives/Capsule.cpp | 8 ++++---- src/Primitives/Cylinder.cpp | 2 +- src/Primitives/UVSphere.cpp | 2 +- 14 files changed, 54 insertions(+), 73 deletions(-) diff --git a/src/Color.h b/src/Color.h index 5900c8b04..fadae7dd0 100644 --- a/src/Color.h +++ b/src/Color.h @@ -46,11 +46,11 @@ template inline typename std::enable_if::valu std::tie(hue, saturation, value) = hsv; /* Remove repeats */ - hue -= Math::Deg(int(T(hue)/T(360))*T(360)); + hue -= int(hue.toUnderlyingType()/T(360))*Math::Deg(360); if(hue < Math::Deg(0)) hue += Math::Deg(360); - int h = int(T(hue)/T(60)) % 6; - T f = T(hue)/T(60) - h; + int h = int(hue.toUnderlyingType()/T(60)) % 6; + T f = hue.toUnderlyingType()/T(60) - h; T p = value * (T(1) - saturation); T q = value * (T(1) - f*saturation); diff --git a/src/Math/Angle.h b/src/Math/Angle.h index 9b7b66000..fa68945f6 100644 --- a/src/Math/Angle.h +++ b/src/Math/Angle.h @@ -231,14 +231,14 @@ See operator""_degf() for more information. inline constexpr Rad operator "" _radf(long double value) { return Rad(value); } #endif -template inline constexpr Deg::Deg(Unit value): Unit(T(180)*T(value)/Math::Constants::pi()) {} -template inline constexpr Rad::Rad(Unit value): Unit(T(value)*Math::Constants::pi()/T(180)) {} +template inline constexpr Deg::Deg(Unit value): Unit(T(180)*value.toUnderlyingType()/Math::Constants::pi()) {} +template inline constexpr Rad::Rad(Unit value): Unit(value.toUnderlyingType()*Math::Constants::pi()/T(180)) {} /** @debugoperator{Magnum::Math::Rad} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Unit& value) { debug << "Rad("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); - debug << T(value) << ")"; + debug << value.toUnderlyingType() << ")"; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true); return debug; } @@ -247,7 +247,7 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Unit& value) { debug << "Deg("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); - debug << T(value) << ")"; + debug << value.toUnderlyingType() << ")"; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true); return debug; } diff --git a/src/Math/Complex.h b/src/Math/Complex.h index 01027e4c9..c423fc3fa 100644 --- a/src/Math/Complex.h +++ b/src/Math/Complex.h @@ -93,7 +93,7 @@ template class Complex { * @see angle(), Matrix3::rotation(), Quaternion::rotation() */ inline static Complex rotation(Rad angle) { - return {std::cos(T(angle)), std::sin(T(angle))}; + return {std::cos(angle.toUnderlyingType()), std::sin(angle.toUnderlyingType())}; } /** diff --git a/src/Math/Functions.h b/src/Math/Functions.h index cec7db9e5..132a0f2e0 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -86,7 +86,7 @@ UnsignedInt MAGNUM_EXPORT log(UnsignedInt base, UnsignedInt number); #ifdef DOXYGEN_GENERATING_OUTPUT template inline T sin(Rad angle) { return std::sin(T(angle)); } #else -template inline T sin(Unit angle) { return std::sin(T(angle)); } +template inline T sin(Unit angle) { return std::sin(angle.toUnderlyingType()); } template inline T sin(Unit angle) { return sin(Rad(angle)); } #endif @@ -94,7 +94,7 @@ template inline T sin(Unit angle) { return sin(Rad(angle)); #ifdef DOXYGEN_GENERATING_OUTPUT template inline T cos(Rad angle) { return std::cos(T(angle)); } #else -template inline T cos(Unit angle) { return std::cos(T(angle)); } +template inline T cos(Unit angle) { return std::cos(angle.toUnderlyingType()); } template inline T cos(Unit angle) { return cos(Rad(angle)); } #endif @@ -102,7 +102,7 @@ template inline T cos(Unit angle) { return cos(Rad(angle)); #ifdef DOXYGEN_GENERATING_OUTPUT template inline T tan(Rad angle) { return std::tan(T(angle)); } #else -template inline T tan(Unit angle) { return std::tan(T(angle)); } +template inline T tan(Unit angle) { return std::tan(angle.toUnderlyingType()); } template inline T tan(Unit angle) { return tan(Rad(angle)); } #endif diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 579610d70..2b43e83b0 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -80,8 +80,8 @@ template class Matrix3: public Matrix<3, T> { * Matrix4::rotation(Rad, const Vector3&) */ static Matrix3 rotation(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); + T sine = std::sin(angle.toUnderlyingType()); + T cosine = std::cos(angle.toUnderlyingType()); return {{ cosine, sine, T(0)}, { -sine, cosine, T(0)}, diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index 0ebebff4b..8fb0484ce 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -94,8 +94,8 @@ template class Matrix4: public Matrix<4, T> { CORRADE_ASSERT(normalizedAxis.isNormalized(), "Math::Matrix4::rotation(): axis must be normalized", {}); - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); + T sine = std::sin(angle.toUnderlyingType()); + T cosine = std::cos(angle.toUnderlyingType()); T oneMinusCosine = T(1) - cosine; T xx = normalizedAxis.x()*normalizedAxis.x(); @@ -131,8 +131,8 @@ template class Matrix4: public Matrix<4, T> { * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ static Matrix4 rotationX(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); + T sine = std::sin(angle.toUnderlyingType()); + T cosine = std::cos(angle.toUnderlyingType()); return {{T(1), T(0), T(0), T(0)}, {T(0), cosine, sine, T(0)}, @@ -149,8 +149,8 @@ template class Matrix4: public Matrix<4, T> { * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ static Matrix4 rotationY(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); + T sine = std::sin(angle.toUnderlyingType()); + T cosine = std::cos(angle.toUnderlyingType()); return {{cosine, T(0), -sine, T(0)}, { T(0), T(1), T(0), T(0)}, @@ -167,8 +167,8 @@ template class Matrix4: public Matrix<4, T> { * rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) */ static Matrix4 rotationZ(Rad angle) { - T sine = std::sin(T(angle)); - T cosine = std::cos(T(angle)); + T sine = std::sin(angle.toUnderlyingType()); + T cosine = std::cos(angle.toUnderlyingType()); return {{cosine, sine, T(0), T(0)}, { -sine, cosine, T(0), T(0)}, @@ -235,7 +235,7 @@ template class Matrix4: public Matrix<4, T> { * @see orthographicProjection(), Matrix3::projection() */ static Matrix4 perspectiveProjection(Rad fov, T aspectRatio, T near, T far) { - T xyScale = 2*std::tan(T(fov)/2)*near; + T xyScale = 2*std::tan(fov.toUnderlyingType()/2)*near; return perspectiveProjection(Vector2(xyScale, xyScale/aspectRatio), near, far); } diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index 0cc1ac8ad..644f81029 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -170,7 +170,7 @@ template class Quaternion { CORRADE_ASSERT(normalizedAxis.isNormalized(), "Math::Quaternion::rotation(): axis must be normalized", {}); - return {normalizedAxis*std::sin(T(angle)/2), std::cos(T(angle)/2)}; + return {normalizedAxis*std::sin(angle.toUnderlyingType()/2), std::cos(angle.toUnderlyingType()/2)}; } /** diff --git a/src/Math/Test/AngleTest.cpp b/src/Math/Test/AngleTest.cpp index cdc3b3eba..bb64a9803 100644 --- a/src/Math/Test/AngleTest.cpp +++ b/src/Math/Test/AngleTest.cpp @@ -60,24 +60,24 @@ AngleTest::AngleTest() { void AngleTest::construct() { /* Default constructor */ constexpr Deg m; - CORRADE_COMPARE(Float(m), 0.0f); + CORRADE_COMPARE(m.toUnderlyingType(), 0.0f); #ifndef MAGNUM_TARGET_GLES constexpr Degd a; - CORRADE_COMPARE(Double(a), 0.0); + CORRADE_COMPARE(a.toUnderlyingType(), 0.0); #else constexpr Deg a; - CORRADE_COMPARE(Float(a), 0.0f); + CORRADE_COMPARE(a.toUnderlyingType(), 0.0f); #endif /* Value constructor */ constexpr Deg b(25.0); - CORRADE_COMPARE(Float(b), 25.0f); + CORRADE_COMPARE(b.toUnderlyingType(), 25.0f); #ifndef MAGNUM_TARGET_GLES constexpr Radd n(3.14); - CORRADE_COMPARE(Double(n), 3.14); + CORRADE_COMPARE(n.toUnderlyingType(), 3.14); #else constexpr Rad n(3.14); - CORRADE_COMPARE(Float(n), 3.14f); + CORRADE_COMPARE(n.toUnderlyingType(), 3.14f); #endif /* Copy constructor */ @@ -93,13 +93,13 @@ void AngleTest::construct() { /* Conversion operator */ constexpr Rad p(n); - CORRADE_COMPARE(Float(p), 3.14f); + CORRADE_COMPARE(p.toUnderlyingType(), 3.14f); #ifndef MAGNUM_TARGET_GLES constexpr Degd d(b); - CORRADE_COMPARE(Double(d), 25.0); + CORRADE_COMPARE(d.toUnderlyingType(), 25.0); #else constexpr Deg d(b); - CORRADE_COMPARE(Float(d), 25.0f); + CORRADE_COMPARE(d.toUnderlyingType(), 25.0f); #endif } @@ -130,10 +130,10 @@ void AngleTest::literals() { void AngleTest::conversion() { /* Implicit conversion should be allowed */ constexpr Deg a = Rad(1.57079633f); - CORRADE_COMPARE(Float(a), 90.0f); + CORRADE_COMPARE(a.toUnderlyingType(), 90.0f); constexpr Rad b = Deg(90.0f); - CORRADE_COMPARE(Float(b), 1.57079633f); + CORRADE_COMPARE(b.toUnderlyingType(), 1.57079633f); } void AngleTest::debugDeg() { diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index e7d2770d5..898df5ef8 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -300,17 +300,17 @@ void FunctionsTest::trigonometric() { void FunctionsTest::trigonometricWithBase() { /* Verify that the functions can be called with Unit and Unit */ - CORRADE_VERIFY((std::is_same>::value)); - CORRADE_VERIFY((std::is_same>::value)); + CORRADE_VERIFY((std::is_same>::value)); + CORRADE_VERIFY((std::is_same>::value)); - CORRADE_COMPARE(Math::sin(Deg(15.0f)+Deg(15.0f)), 0.5f); - CORRADE_COMPARE(Math::sin(Rad(Constants::pi()/12)+Rad(Constants::pi()/12)), 0.5f); + CORRADE_COMPARE(Math::sin(2*Deg(15.0f)), 0.5f); + CORRADE_COMPARE(Math::sin(2*Rad(Constants::pi()/12)), 0.5f); - CORRADE_COMPARE(Math::cos(Deg(30.0f)+Deg(30.0f)), 0.5f); - CORRADE_COMPARE(Math::cos(Rad(Constants::pi()/6)+Rad(Constants::pi()/6)), 0.5f); + CORRADE_COMPARE(Math::cos(2*Deg(30.0f)), 0.5f); + CORRADE_COMPARE(Math::cos(2*Rad(Constants::pi()/6)), 0.5f); - CORRADE_COMPARE(Math::tan(Deg(22.5f)+Deg(22.5f)), 1.0f); - CORRADE_COMPARE(Math::tan(Rad(Constants::pi()/8)+Rad(Constants::pi()/8)), 1.0f); + CORRADE_COMPARE(Math::tan(2*Deg(22.5f)), 1.0f); + CORRADE_COMPARE(Math::tan(2*Rad(Constants::pi()/8)), 1.0f); } }}} diff --git a/src/Math/Test/UnitTest.cpp b/src/Math/Test/UnitTest.cpp index 9adf26e1f..aa437e7a8 100644 --- a/src/Math/Test/UnitTest.cpp +++ b/src/Math/Test/UnitTest.cpp @@ -58,21 +58,16 @@ typedef Unit Sec; typedef Unit Seci; inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, Sec value) { - return debug << Float(value); + return debug << value.toUnderlyingType(); } void UnitTest::construct() { constexpr Sec a(25.0f); - CORRADE_COMPARE(Float(a), 25.0f); + CORRADE_COMPARE(a.toUnderlyingType(), 25.0f); /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible::value)); - { - #ifdef CORRADE_GCC44_COMPATIBILITY - CORRADE_EXPECT_FAIL("GCC 4.4 doesn't have explicit conversion operators"); - #endif - CORRADE_VERIFY(!(std::is_convertible::value)); - } + CORRADE_VERIFY(!(std::is_convertible::value)); } void UnitTest::constructDefault() { @@ -143,17 +138,9 @@ void UnitTest::multiplyDivide() { constexpr Sec b(-4.5f); constexpr Sec c(5.0f); - /* The operation returns underlying type on GCC 4.4 because of non-explicit - conversion operators and conflicts with builtin operators */ - #ifndef CORRADE_GCC44_COMPATIBILITY constexpr Sec d = a*-1.5f; constexpr Sec e = -1.5f*a; constexpr Sec f = b/-1.5f; - #else - constexpr Sec d(a*-1.5f); - constexpr Sec e(-1.5f*a); - constexpr Sec f(b/-1.5f); - #endif CORRADE_COMPARE(d, b); CORRADE_COMPARE(e, b); CORRADE_COMPARE(f, a); diff --git a/src/Math/Unit.h b/src/Math/Unit.h index 0be16e18e..9e6a8746b 100644 --- a/src/Math/Unit.h +++ b/src/Math/Unit.h @@ -53,11 +53,12 @@ template class Derived, class T> class Unit { /** @brief Construct from another underlying type */ template inline constexpr explicit Unit(Unit value): value(value.value) {} + /** @brief Explicit conversion to underlying type */ + inline constexpr T toUnderlyingType() const { return value; } + /** @brief Explicit conversion to underlying type */ #ifndef CORRADE_GCC44_COMPATIBILITY inline constexpr explicit operator T() const { return value; } - #else - inline constexpr operator T() const { return value; } #endif /** @brief Equality comparison */ @@ -117,9 +118,6 @@ template class Derived, class T> class Unit { return Unit(value - other.value); } - /* These are conflicting with builtin operators because of non-explicit - conversion to T */ - #ifndef CORRADE_GCC44_COMPATIBILITY /** @brief Multiply with number and assign */ inline Unit& operator*=(T number) { value *= number; @@ -146,21 +144,17 @@ template class Derived, class T> class Unit { inline constexpr T operator/(Unit other) const { return value/other.value; } - #endif private: T value; }; -/* This is conflicting with builtin operator because of non-explicit conversion to T */ -#ifndef CORRADE_GCC44_COMPATIBILITY /** @relates Unit @brief Multiply number with value */ template class Derived, class T> inline constexpr Unit operator*(typename std::common_type::type number, const Unit& value) { return value*number; } -#endif }} diff --git a/src/Primitives/Capsule.cpp b/src/Primitives/Capsule.cpp index 51eed80ea..e35ecb34f 100644 --- a/src/Primitives/Capsule.cpp +++ b/src/Primitives/Capsule.cpp @@ -40,7 +40,7 @@ Capsule::Capsule(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, Unsigne capVertex(-height/2, -1.0f, 0.0f); /* Rings of bottom hemisphere */ - hemisphereVertexRings(hemisphereRings-1, -length/2, -Rad(Constants::pi()/2)+hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement); + hemisphereVertexRings(hemisphereRings-1, -length/2, -Rad(Constants::pi())/2+hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement); /* Rings of cylinder */ cylinderVertexRings(cylinderRings+1, -length/2, length/cylinderRings, 1.0f/height, length/(cylinderRings*height)); @@ -71,12 +71,12 @@ void Capsule::hemisphereVertexRings(UnsignedInt count, Float centerY, Rad startR Rad segmentAngleIncrement(2*Constants::pi()/segments); Float x, y, z; for(UnsignedInt i = 0; i != count; ++i) { - Rad ringAngle = startRingAngle + Rad(i*ringAngleIncrement); + Rad ringAngle = startRingAngle + i*ringAngleIncrement; x = z = Math::cos(ringAngle); y = Math::sin(ringAngle); for(UnsignedInt j = 0; j != segments; ++j) { - Rad segmentAngle(j*segmentAngleIncrement); + Rad segmentAngle = j*segmentAngleIncrement; positions(0)->push_back({x*Math::sin(segmentAngle), centerY+y, z*Math::cos(segmentAngle)}); normals(0)->push_back({x*Math::sin(segmentAngle), y, z*Math::cos(segmentAngle)}); @@ -97,7 +97,7 @@ void Capsule::cylinderVertexRings(UnsignedInt count, Float startY, Float yIncrem Rad segmentAngleIncrement(2*Constants::pi()/segments); for(UnsignedInt i = 0; i != count; ++i) { for(UnsignedInt j = 0; j != segments; ++j) { - Rad segmentAngle(j*segmentAngleIncrement); + Rad segmentAngle = j*segmentAngleIncrement; positions(0)->push_back({Math::sin(segmentAngle), startY, Math::cos(segmentAngle)}); normals(0)->push_back({Math::sin(segmentAngle), 0.0f, Math::cos(segmentAngle)}); diff --git a/src/Primitives/Cylinder.cpp b/src/Primitives/Cylinder.cpp index 3d6ff6e58..691e5402b 100644 --- a/src/Primitives/Cylinder.cpp +++ b/src/Primitives/Cylinder.cpp @@ -60,7 +60,7 @@ void Cylinder::capVertexRing(Float y, Float textureCoordsV, const Vector3& norma Rad segmentAngleIncrement(2*Constants::pi()/segments); for(UnsignedInt i = 0; i != segments; ++i) { - Rad segmentAngle(i*segmentAngleIncrement); + Rad segmentAngle = i*segmentAngleIncrement; positions(0)->push_back({Math::sin(segmentAngle), y, Math::cos(segmentAngle)}); normals(0)->push_back(normal); diff --git a/src/Primitives/UVSphere.cpp b/src/Primitives/UVSphere.cpp index f2591633c..b6cde4ca3 100644 --- a/src/Primitives/UVSphere.cpp +++ b/src/Primitives/UVSphere.cpp @@ -38,7 +38,7 @@ UVSphere::UVSphere(UnsignedInt rings, UnsignedInt segments, TextureCoords textur capVertex(-1.0f, -1.0f, 0.0f); /* Vertex rings */ - hemisphereVertexRings(rings-1, 0.0f, -Rad(Constants::pi()/2)+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement); + hemisphereVertexRings(rings-1, 0.0f, -Rad(Constants::pi())/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement); /* Top cap vertex */ capVertex(1.0f, 1.0f, 1.0f);