From 408399ddffa8356a6343ae3740438c0f3d12d1f5 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 5 Mar 2013 21:58:52 +0000 Subject: [PATCH] Added FloatVectorOperations::findMinimum and findMaximum --- .../buffers/juce_FloatVectorOperations.cpp | 76 +++++++++++++++++-- .../buffers/juce_FloatVectorOperations.h | 6 ++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp index 12b4d3f5b3..c647c1a677 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp @@ -49,6 +49,61 @@ namespace FloatVectorHelpers _mm_empty(); #endif } + + static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept + { + #if JUCE_USE_SSE_INTRINSICS + const int numLongOps = num / 4; + + if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available()) + { + __m128 val; + + #define JUCE_MINIMUMMAXIMUM_SSE_LOOP(loadOp, minMaxOp) \ + val = loadOp (src); \ + src += 4; \ + for (int i = 1; i < numLongOps; ++i) \ + { \ + const __m128 s = loadOp (src); \ + val = minMaxOp (val, s); \ + src += 4; \ + } + + if (isMinimum) + { + if (FloatVectorHelpers::isAligned (src)) { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_load_ps, _mm_min_ps) } + else { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_loadu_ps, _mm_min_ps) } + } + else + { + if (FloatVectorHelpers::isAligned (src)) { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_load_ps, _mm_max_ps) } + else { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_loadu_ps,_mm_max_ps) } + } + + float localVal; + + { + float vals[4]; + _mm_storeu_ps (vals, val); + FloatVectorHelpers::mmEmpty(); + + localVal = isMinimum ? jmin (vals[0], vals[1], vals[2], vals[3]) + : jmax (vals[0], vals[1], vals[2], vals[3]); + } + + num &= 3; + + for (int i = 0; i < num; ++i) + localVal = isMinimum ? jmin (localVal, src[i]) + : jmax (localVal, src[i]); + + return localVal; + } + #endif + + return isMinimum ? juce::findMinimum (src, num) + : juce::findMaximum (src, num); + } } #define JUCE_BEGIN_SSE_OP \ @@ -255,14 +310,11 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n num &= 3; - if (num != 0) + for (int i = 0; i < num; ++i) { - for (int i = 0; i < num; ++i) - { - const float s = src[i]; - localMin = jmin (localMin, s); - localMax = jmax (localMax, s); - } + const float s = src[i]; + localMin = jmin (localMin, s); + localMax = jmax (localMax, s); } minResult = localMin; @@ -273,3 +325,13 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n juce::findMinAndMax (src, num, minResult, maxResult); } + +float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept +{ + return FloatVectorHelpers::findMinimumOrMaximum (src, num, true); +} + +float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept +{ + return FloatVectorHelpers::findMinimumOrMaximum (src, num, false); +} diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h index 5d51b72698..0eeae822c1 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h @@ -68,6 +68,12 @@ public: /** Finds the miniumum and maximum values in the given array. */ static void JUCE_CALLTYPE findMinAndMax (const float* src, int numValues, float& minResult, float& maxResult) noexcept; + + /** Finds the miniumum value in the given array. */ + static float JUCE_CALLTYPE findMinimum (const float* src, int numValues) noexcept; + + /** Finds the maximum value in the given array. */ + static float JUCE_CALLTYPE findMaximum (const float* src, int numValues) noexcept; };