diff --git a/modules/juce_dsp/containers/juce_SIMDRegister.h b/modules/juce_dsp/containers/juce_SIMDRegister.h index b7c9f2ea25..e03bb1a5e8 100644 --- a/modules/juce_dsp/containers/juce_SIMDRegister.h +++ b/modules/juce_dsp/containers/juce_SIMDRegister.h @@ -328,6 +328,13 @@ struct SIMDRegister /** Returns a scalar which is the sum of all elements of the receiver. */ inline ElementType sum() const noexcept { return CmplxOps::sum (value); } + //============================================================================== + /** Returns the absolute value of each element. */ + static inline SIMDRegister JUCE_VECTOR_CALLTYPE abs (SIMDRegister a) noexcept + { + return a - (a * (expand (ElementType (2)) & lessThan (a, expand (ElementType (0))))); + } + //============================================================================== /** Checks if the given pointer is suffeciently aligned for using SIMD operations. */ static inline bool isSIMDAligned (const ElementType* ptr) noexcept diff --git a/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp b/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp index 861a91f032..44d4868495 100644 --- a/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp +++ b/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp @@ -90,7 +90,7 @@ namespace SIMDRegister_test_internal template struct VecFiller> { - static SIMDRegister fill(Random& random) + static SIMDRegister fill (Random& random) { constexpr int size = (int) SIMDRegister::SIMDNumElements; #ifdef _MSC_VER @@ -735,6 +735,29 @@ public: } }; + struct CheckAbs + { + template + static void run (UnitTest& u, Random& random) + { + type inArray[SIMDRegister::SIMDNumElements]; + type outArray[SIMDRegister::SIMDNumElements]; + + SIMDRegister_test_internal::VecFiller::fill (inArray, SIMDRegister::SIMDNumElements, random); + + SIMDRegister a; + copy (a, inArray); + a = SIMDRegister::abs (a); + + auto calcAbs = [] (type x) -> type { return x >= type (0) ? x : -x; }; + + for (size_t j = 0; j < SIMDRegister::SIMDNumElements; ++j) + outArray[j] = calcAbs (inArray[j]); + + u.expect (vecEqualToArray (a, outArray)); + } + }; + struct CheckBoolEquals { template @@ -813,6 +836,21 @@ public: TheTest::template run(*this, random); } + template + void runTestSigned (const char* unitTestName) + { + beginTest (unitTestName); + + Random random = getRandom(); + + TheTest::template run (*this, random); + TheTest::template run (*this, random); + TheTest::template run (*this, random); + TheTest::template run (*this, random); + TheTest::template run (*this, random); + TheTest::template run (*this, random); + } + void runTest() { runTestForAllTypes ("InitializationTest"); @@ -833,6 +871,8 @@ public: runTestForAllTypes ("CheckMultiplyAdd"); runTestForAllTypes ("CheckSum"); + + runTestSigned ("CheckAbs"); } };