diff --git a/src/Math/Functions.h b/src/Math/Functions.h index f3e2f091d..c1b330ca7 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -280,6 +280,22 @@ template inline Vector lerp(const V } #endif +/** +@brief Fused multiply-add + +Computes and returns @f$ ab + c @f$. +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline T fma(const T& a, const T& b, const T& c); +#else +template inline typename std::enable_if::value, T>::type fma(T a, T b, T c) { + return std::fma(a, b, c); +} +template inline Vector fma(const Vector& a, const Vector& b, const Vector& c) { + return a*b + c; +} +#endif + /** @brief Normalize integral value diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index cda253c74..25e519f92 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -41,6 +41,7 @@ class FunctionsTest: public Corrade::TestSuite::Tester { void sqrtInverted(); void clamp(); void lerp(); + void fma(); void normalizeUnsigned(); void normalizeSigned(); void denormalizeUnsigned(); @@ -74,6 +75,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::sqrtInverted, &FunctionsTest::clamp, &FunctionsTest::lerp, + &FunctionsTest::fma, &FunctionsTest::normalizeUnsigned, &FunctionsTest::normalizeSigned, &FunctionsTest::denormalizeUnsigned, @@ -148,6 +150,14 @@ void FunctionsTest::lerp() { CORRADE_COMPARE(Math::lerp(c, d, 0.25f), Vector3ub(4, 96, 56)); } +void FunctionsTest::fma() { + CORRADE_COMPARE(Math::fma(2.0f, 3.0f, 0.75f), 6.75f); + CORRADE_COMPARE(Math::fma(Vector3( 2.0f, 1.5f, 0.5f), + Vector3( 3.0f, 2.0f, -1.0f), + Vector3(0.75f, 0.25f, 0.1f)), + Vector3(6.75f, 3.25f, -0.4f)); +} + void FunctionsTest::normalizeUnsigned() { CORRADE_COMPARE((Math::normalize(0)), 0.0f); CORRADE_COMPARE((Math::normalize(255)), 1.0f);