Browse Source

Math: recognize Nanoseconds and Seconds in type traits.

Which in turn makes them usable with various math functions. Test
them all as well.
pull/638/head
Vladimír Vondruš 2 years ago
parent
commit
ec788f313c
  1. 30
      src/Magnum/Math/Test/FunctionsTest.cpp
  2. 12
      src/Magnum/Math/Test/TypeTraitsTest.cpp
  3. 27
      src/Magnum/Math/TypeTraits.h

30
src/Magnum/Math/Test/FunctionsTest.cpp

@ -29,6 +29,7 @@
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Math/Functions.h"
#include "Magnum/Math/Time.h"
#include "Magnum/Math/Vector4.h"
namespace Magnum { namespace Math { namespace Test { namespace {
@ -93,6 +94,7 @@ using namespace Literals;
using Magnum::Constants;
using Magnum::Deg;
using Magnum::Rad;
using Magnum::Seconds;
using Magnum::Vector2;
using Magnum::Vector3;
using Magnum::Vector4;
@ -196,6 +198,7 @@ void FunctionsTest::min() {
/* Wrapped types */
CORRADE_COMPARE(Math::min(5.0_degf, 9.0_degf), 5.0_degf);
CORRADE_COMPARE(Math::min(6.0_sec, 5500.0_msec), 5.5_sec);
}
void FunctionsTest::max() {
@ -205,6 +208,7 @@ void FunctionsTest::max() {
/* Wrapped types */
CORRADE_COMPARE(Math::max(5.0_degf, 9.0_degf), 9.0_degf);
CORRADE_COMPARE(Math::max(6.0_sec, 5500.0_msec), 6000.0_msec);
}
void FunctionsTest::minmax() {
@ -220,6 +224,7 @@ void FunctionsTest::minmax() {
/* Wrapped types */
CORRADE_COMPARE(Math::minmax(4.0_degf, 5.0_degf), Containers::pair(4.0_degf, 5.0_degf));
CORRADE_COMPARE(Math::minmax(6.0_sec, 5500.0_msec), Containers::pair(5.5_sec, 6.0_sec));
}
void FunctionsTest::clamp() {
@ -237,6 +242,7 @@ void FunctionsTest::clamp() {
/* Wrapped types */
CORRADE_COMPARE(Math::clamp(0.5_degf, 0.75_degf, 1.0_degf), 0.75_degf);
CORRADE_COMPARE(Math::clamp(0.5_sec, 0.75_sec, 799.9_msec), 0.75_sec);
}
void FunctionsTest::nanPropagation() {
@ -268,6 +274,7 @@ void FunctionsTest::sign() {
angle value back. With returning the type itself such operation wouldn't
have any definable unit. */
CORRADE_COMPARE(Math::sign(-3.7_degf), -1.0f);
CORRADE_COMPARE(Math::sign(-2.5_usec), -1.0f);
CORRADE_COMPARE(Math::sign(Math::Vector2<Deg>{3.5_degf, -1.9_degf}), (Vector2{1.0f, -1.0f}));
}
@ -278,6 +285,7 @@ void FunctionsTest::abs() {
/* Wrapped types */
CORRADE_COMPARE(Math::abs(-5.0_degf), 5.0_degf);
CORRADE_COMPARE(Math::abs(-5.0_msec), 5.0_msec);
}
void FunctionsTest::floor() {
@ -286,6 +294,8 @@ void FunctionsTest::floor() {
/* Wrapped types */
CORRADE_COMPARE(Math::floor(2.7_degf), 2.0_degf);
/* Nanoseconds are an integer type */
CORRADE_COMPARE(Math::floor(Seconds{2.7_sec}), Seconds{2.0_sec});
}
void FunctionsTest::round() {
@ -303,6 +313,8 @@ void FunctionsTest::round() {
/* Wrapped types */
CORRADE_COMPARE(Math::round(2.7_degf), 3.0_degf);
/* Nanoseconds are an integer type */
CORRADE_COMPARE(Math::round(Seconds{2.7_sec}), Seconds{3.0_sec});
}
void FunctionsTest::ceil() {
@ -311,6 +323,8 @@ void FunctionsTest::ceil() {
/* Wrapped types */
CORRADE_COMPARE(Math::ceil(2.7_degf), 3.0_degf);
/* Nanoseconds are an integer type */
CORRADE_COMPARE(Math::ceil(Seconds{2.7_sec}), Seconds{3.0_sec});
}
void FunctionsTest::binomialCoefficient() {
@ -347,6 +361,8 @@ void FunctionsTest::fmod() {
/* Wrapped types */
CORRADE_COMPARE(Math::fmod(2.7_degf, 1.3_degf), 0.1_degf);
/* Nanoseconds are an integer type */
CORRADE_COMPARE(Math::fmod(Seconds{2.7_sec}, Seconds{1.3_sec}), Seconds{0.1_sec});
}
void FunctionsTest::sqrt() {
@ -383,6 +399,7 @@ void FunctionsTest::lerp() {
/* Wrapped types */
CORRADE_COMPARE(Math::lerp(2.0_degf, 5.0_degf, 0.5f), 3.5_degf);
CORRADE_COMPARE(Math::lerp(2.0_usec, 5.0_usec, 0.5f), 3.5_usec);
}
void FunctionsTest::lerpBool() {
@ -396,6 +413,7 @@ void FunctionsTest::lerpBool() {
/* Wrapped types */
CORRADE_COMPARE(Math::lerp(2.0_degf, 5.0_degf, true), 5.0_degf);
CORRADE_COMPARE(Math::lerp(2.0_msec, 5.0_msec, true), 5.0_msec);
}
void FunctionsTest::lerpInverted() {
@ -409,6 +427,12 @@ void FunctionsTest::lerpInverted() {
/* Wrapped types */
CORRADE_COMPARE(Math::lerpInverted(2.0_degf, 5.0_degf, 3.5_degf), 0.5f);
/* Nanoseconds are an integer type */
CORRADE_COMPARE(Math::lerpInverted(Seconds{2.0_sec}, Seconds{5.0_sec}, Seconds{3.5_sec}), 0.5f);
{
CORRADE_EXPECT_FAIL("This doesn't work correctly with (integer) Nanoseconds.");
CORRADE_COMPARE(Math::lerpInverted(2.0_sec, 5.0_sec, 3.5_sec), 0.5f);
}
}
void FunctionsTest::select() {
@ -429,6 +453,7 @@ void FunctionsTest::select() {
/* Wrapped types */
CORRADE_COMPARE(Math::select(2.0_degf, 5.0_degf, 0.5f), 2.0_degf);
CORRADE_COMPARE(Math::select(2.0_msec, 5.0_msec, 0.5f), 2.0_msec);
}
void FunctionsTest::selectBool() {
@ -476,7 +501,10 @@ void FunctionsTest::isInf() {
/* Wrapped types */
CORRADE_VERIFY(Math::isInf(-Rad(Constants::inf())));
CORRADE_VERIFY(Math::isInf(Seconds{-Constants::inf()}));
CORRADE_VERIFY(!Math::isInf(5.3_degf));
/* Nanoseconds are an integer type */
CORRADE_VERIFY(!Math::isInf(Seconds{5.3_msec}));
}
void FunctionsTest::isInfVector() {
@ -492,7 +520,9 @@ void FunctionsTest::isNan() {
/* Wrapped types */
CORRADE_VERIFY(Math::isNan(-Rad(Constants::nan())));
CORRADE_VERIFY(Math::isNan(Seconds(Constants::nan())));
CORRADE_VERIFY(!Math::isNan(5.3_degf));
CORRADE_VERIFY(!Math::isNan(Seconds{5.3_usec}));
}
void FunctionsTest::isNanfVector() {

12
src/Magnum/Math/Test/TypeTraitsTest.cpp

@ -172,6 +172,8 @@ void TypeTraitsTest::isScalar() {
CORRADE_VERIFY(IsScalar<Deg<Float>>::value);
CORRADE_VERIFY(IsScalar<Half>::value);
CORRADE_VERIFY(IsScalar<Unit<Rad, Double>>::value);
CORRADE_VERIFY(IsScalar<Nanoseconds<Long>>::value);
CORRADE_VERIFY(IsScalar<Unit<Seconds, Float>>::value);
CORRADE_VERIFY(!IsScalar<Vector2<Float>>::value);
CORRADE_VERIFY(!IsVector<Matrix2x3<Float>>::value);
CORRADE_VERIFY(!IsScalar<Color3<Half>>::value);
@ -182,6 +184,7 @@ void TypeTraitsTest::isScalar() {
void TypeTraitsTest::isVector() {
CORRADE_VERIFY(!IsVector<UnsignedByte>::value);
CORRADE_VERIFY(!IsVector<Deg<UnsignedByte>>::value);
CORRADE_VERIFY(!IsVector<Seconds<Float>>::value);
CORRADE_VERIFY(IsVector<Vector<2, Deg<Float>>>::value);
CORRADE_VERIFY(IsVector<Color3<UnsignedByte>>::value);
CORRADE_VERIFY(IsVector<Color3<Half>>::value);
@ -198,8 +201,10 @@ void TypeTraitsTest::isIntegral() {
CORRADE_VERIFY(IsIntegral<Int>::value);
CORRADE_VERIFY(IsIntegral<Vector<7, UnsignedInt>>::value);
CORRADE_VERIFY(IsIntegral<Vector2<Long>>::value);
CORRADE_VERIFY(IsIntegral<Nanoseconds<Long>>::value);
CORRADE_VERIFY(!IsIntegral<Half>::value);
CORRADE_VERIFY(!IsIntegral<Deg<Float>>::value);
CORRADE_VERIFY(!IsIntegral<Seconds<Float>>::value);
CORRADE_VERIFY(!IsIntegral<char*>::value);
CORRADE_VERIFY(!IsIntegral<bool>::value);
}
@ -207,12 +212,15 @@ void TypeTraitsTest::isIntegral() {
void TypeTraitsTest::isFloatingPoint() {
CORRADE_VERIFY(!IsFloatingPoint<Int>::value);
CORRADE_VERIFY(!IsFloatingPoint<Vector<7, UnsignedInt>>::value);
CORRADE_VERIFY(!IsFloatingPoint<Nanoseconds<Long>>::value);
CORRADE_VERIFY(IsFloatingPoint<Double>::value);
CORRADE_VERIFY(IsFloatingPoint<Vector<2, Float>>::value);
CORRADE_VERIFY(IsFloatingPoint<Vector2<long double>>::value);
CORRADE_VERIFY(IsFloatingPoint<Deg<Float>>::value);
CORRADE_VERIFY(IsFloatingPoint<Seconds<Float>>::value);
CORRADE_VERIFY(IsFloatingPoint<Color4<Half>>::value);
CORRADE_VERIFY(IsFloatingPoint<Unit<Rad, Float>>::value);
CORRADE_VERIFY(IsFloatingPoint<Unit<Seconds, Float>>::value);
CORRADE_VERIFY(IsFloatingPoint<Deg<Half>>::value);
CORRADE_VERIFY(!IsFloatingPoint<char*>::value);
}
@ -223,6 +231,8 @@ void TypeTraitsTest::isUnitless() {
CORRADE_VERIFY(IsUnitless<Color4<Float>>::value);
CORRADE_VERIFY(!IsUnitless<Deg<Float>>::value);
CORRADE_VERIFY(!IsUnitless<Unit<Rad, Double>>::value);
CORRADE_VERIFY(!IsUnitless<Nanoseconds<Long>>::value);
CORRADE_VERIFY(!IsUnitless<Unit<Seconds, Float>>::value);
CORRADE_VERIFY(!IsUnitless<char*>::value);
}
@ -230,7 +240,9 @@ void TypeTraitsTest::underlyingTypeOf() {
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Int>, Int>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Deg<Float>>, Float>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Nanoseconds<Long>>, Long>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Unit<Rad, Double>>, Double>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Unit<Seconds, Float>>, Float>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Vector2<UnsignedByte>>, UnsignedByte>::value);
CORRADE_VERIFY(std::is_same<UnderlyingTypeOf<Color3<Float>>, Float>::value);

27
src/Magnum/Math/TypeTraits.h

@ -93,8 +93,9 @@ namespace Magnum { namespace Math {
@m_since{2019,10}
Equivalent to @ref std::true_type for all builtin scalar integer and
floating-point types and in addition also @ref Half, @ref Deg and @ref Rad;
equivalent to @ref std::false_type otherwise.
floating-point types and in addition also @ref Half, @ref Deg, @ref Rad,
@ref Nanoseconds and @ref Seconds; equivalent to @ref std::false_type
otherwise.
Note that this is *different* from @ref std::is_scalar, which is @cpp true @ce
also for enums or pointers --- it's rather closer to @ref std::is_arithmetic,
@ -130,6 +131,8 @@ template<> struct IsScalar<long double>: std::true_type {};
template<template<class> class Derived, class T> struct IsScalar<Unit<Derived, T>>: std::true_type {};
template<class T> struct IsScalar<Deg<T>>: std::true_type {};
template<class T> struct IsScalar<Rad<T>>: std::true_type {};
template<> struct IsScalar<Nanoseconds<Long>>: std::true_type {};
template<> struct IsScalar<Seconds<Float>>: std::true_type {};
#endif
/**
@ -162,7 +165,8 @@ template<class T> struct IsVector<Color4<T>>: std::true_type {};
@m_since{2019,10}
Equivalent to @ref std::true_type for all integral scalar and vector types
supported by Magnum math; equivalent to @ref std::false_type otherwise.
supported by Magnum math including @ref Magnum::Nanoseconds; equivalent to
@ref std::false_type otherwise.
Unlike @ref std::is_integral this is @ref std::false_type for @cpp bool @ce.
@see @ref IsFloatingPoint, @ref IsScalar, @ref IsVector
@ -189,6 +193,7 @@ template<> struct IsIntegral<unsigned long>: std::true_type {};
template<> struct IsIntegral<long long>: std::true_type {};
template<> struct IsIntegral<unsigned long long>: std::true_type {};
template<std::size_t size, class T> struct IsIntegral<Vector<size, T>>: IsIntegral<T> {};
template<> struct IsIntegral<Nanoseconds<Long>>: std::true_type {};
template<class T> struct IsIntegral<Vector2<T>>: IsIntegral<T> {};
template<class T> struct IsIntegral<Vector3<T>>: IsIntegral<T> {};
template<class T> struct IsIntegral<Vector4<T>>: IsIntegral<T> {};
@ -202,8 +207,8 @@ template<class T> struct IsIntegral<Color4<T>>: IsIntegral<T> {};
@m_since{2019,10}
Equivalent to @ref std::true_type for all floating-point scalar and vector
types supported by Magnum math including @ref Half, @ref Deg and @ref Rad;
equivalent to @ref std::false_type otherwise.
types supported by Magnum math including @ref Half, @ref Deg, @ref Rad and
@ref Seconds; equivalent to @ref std::false_type otherwise.
@see @ref IsIntegral, @ref IsScalar, @ref IsVector, @ref std::is_floating_point
*/
template<class T> struct IsFloatingPoint
@ -228,6 +233,7 @@ template<class T> struct IsFloatingPoint<Color4<T>>: IsFloatingPoint<T> {};
template<template<class> class Derived, class T> struct IsFloatingPoint<Unit<Derived, T>>: IsFloatingPoint<T> {};
template<class T> struct IsFloatingPoint<Deg<T>>: IsFloatingPoint<T> {};
template<class T> struct IsFloatingPoint<Rad<T>>: IsFloatingPoint<T> {};
template<> struct IsFloatingPoint<Seconds<Float>>: std::true_type {};
#endif
/**
@ -235,9 +241,10 @@ template<class T> struct IsFloatingPoint<Rad<T>>: IsFloatingPoint<T> {};
@m_since{2019,10}
Equivalent to @ref std::true_type for scalar or vector types that have an
unitless underlying type (i.e., not @ref Deg or @ref Rad); @ref std::false_type
otherwise. Some math functions such as @ref sqrt() or @ref log() work only with
unitless types because the resulting unit couldn't be expressed otherwise.
unitless underlying type (i.e., not @ref Deg, @ref Rad, @ref Nanoseconds or
@ref Seconds); @ref std::false_type otherwise. Some math functions such as
@ref sqrt() or @ref log() work only with unitless types because the resulting
unit couldn't be expressed otherwise.
@see @ref IsScalar, @ref IsVector
*/
template<class T> struct IsUnitless
@ -248,6 +255,8 @@ template<class T> struct IsUnitless
template<template<class> class Derived, class T> struct IsUnitless<Unit<Derived, T>>: std::false_type {};
template<class T> struct IsUnitless<Deg<T>>: std::false_type {};
template<class T> struct IsUnitless<Rad<T>>: std::false_type {};
template<class T> struct IsUnitless<Nanoseconds<T>>: std::false_type {};
template<class T> struct IsUnitless<Seconds<T>>: std::false_type {};
namespace Implementation {
template<class T> struct UnderlyingType {
@ -259,6 +268,8 @@ namespace Implementation {
};
template<class T> struct UnderlyingType<Deg<T>> { typedef T Type; };
template<class T> struct UnderlyingType<Rad<T>> { typedef T Type; };
template<class T> struct UnderlyingType<Nanoseconds<T>> { typedef T Type; };
template<class T> struct UnderlyingType<Seconds<T>> { typedef T Type; };
template<std::size_t size, class T> struct UnderlyingType<Vector<size, T>> {
typedef T Type;
};

Loading…
Cancel
Save