From 7d94c273e4d8e625a55adea698fd01351e59f900 Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Thu, 19 Jun 2025 06:56:22 +0100 Subject: [PATCH 1/6] Adding utility functions & namespace renaming --- .../Accelerate/AccelerateUtilities.h | 42 +++++++++++++++++++ .../Accelerate/AccelerateWrapper.h | 3 +- .../AccelerateWrapperUnitTests.cpp | 14 +++---- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 VectorisationWrappers/Accelerate/AccelerateUtilities.h diff --git a/VectorisationWrappers/Accelerate/AccelerateUtilities.h b/VectorisationWrappers/Accelerate/AccelerateUtilities.h new file mode 100644 index 0000000..051ff21 --- /dev/null +++ b/VectorisationWrappers/Accelerate/AccelerateUtilities.h @@ -0,0 +1,42 @@ +#pragma once +#include + +// VDSP wrapper namespace in a vectorised way +namespace Vectorised::Utilities +{ + template + static void scalerMultiplication (T* InputBuffer, T* OutputBuffer, const int BufferSize, const int InputStride = 1, const int OutputStride = 1) + { + if constexpr (std::is_same_v) + VDSP_vscal (InputBuffer, InputStride, OutputBuffer, OutputStride, BufferSize); + else if constexpr (std::is_same_v) + VDSP_vscalD (InputBuffer, InputStride, OutputBuffer, OutputStride, BufferSize); + } + + template + static void absBuffer (T* InputBuffer, T* OutputBuffer, const int BufferSize, const int InputStride = 1, const int OutputStride = 1) + { + if constexpr (std::is_same_v) + vDSP_abs (InputBuffer, InputStride, OutputBuffer, OutputStride, BufferSize); + else if constexpr (std::is_same_v) + vDSP_absD (InputBuffer, InputStride, OutputBuffer, OutputStride, BufferSize); + } + + template + static void fillBuffer (T* ValueToFill, T* Buffer, const int BufferSize, const int BufferStride = 1) + { + if constexpr (std::is_same_v) + VDSP_vfill (ValueToFill, Buffer, BufferStride, BufferSize); + else if constexpr (std::is_same_v) + VDSP_vfill (ValueToFill, Buffer, BufferStride, BufferSize); + } + + template + static void zeroBuffer (T* ValueToFill, const int BufferSize, const int BufferStride = 1) + { + if constexpr (std::is_same_v) + vdsp_vzero (ValueToFill, BufferStride, BufferSize); + if constexpr (std::is_same_v) + vdsp_vzeroD (ValueToFill, BufferStride, BufferSize); + } +}; \ No newline at end of file diff --git a/VectorisationWrappers/Accelerate/AccelerateWrapper.h b/VectorisationWrappers/Accelerate/AccelerateWrapper.h index 8628fb8..76e3529 100644 --- a/VectorisationWrappers/Accelerate/AccelerateWrapper.h +++ b/VectorisationWrappers/Accelerate/AccelerateWrapper.h @@ -3,7 +3,7 @@ #include // VDSP wrapper namespace in a vectorised way -namespace vivi::VectorisedDSP +namespace Vectorised { // Vectorised Addition function for VDSP template @@ -68,6 +68,7 @@ namespace vivi::VectorisedDSP vvdiv (OutputPtr, InputPtr, OutputPtr, &BufferSize); } + // Vectorised tanh function for VDSP template static void tanhVectorised (const T* InputBuffer, T* OutputBuffer, const int BufferSize) diff --git a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp index 4af6848..638dea9 100644 --- a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp +++ b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp @@ -14,7 +14,7 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") SECTION ("Addition Test") { - vivi::VectorisedDSP::additionVectorised (input.data(), output.data(), 256); + Vectorised::additionVectorised (input.data(), output.data(), 256); for (const auto buffer : { &input, &output }) { @@ -25,7 +25,7 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") SECTION ("Subtraction Test") { - vivi::VectorisedDSP::subtractionVectorised (input.data(), output.data(), 256); + Vectorised::subtractionVectorised (input.data(), output.data(), 256); for (const auto buffer : { &input, &output }) { @@ -36,22 +36,22 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") SECTION ("Multiplication Test") { - vivi::VectorisedDSP::multiplicationVectorised (input.data(), output.data(), 256); + Vectorised::multiplicationVectorised (input.data(), output.data(), 256); } SECTION ("Division Test") { - vivi::VectorisedDSP::divisionVectorised (input.data(), output.data(), 256); + Vectorised::divisionVectorised (input.data(), output.data(), 256); } SECTION ("Division Test") { - vivi::VectorisedDSP::tanhVectorised (input.data(), output.data(), 256); + Vectorised::tanhVectorised (input.data(), output.data(), 256); } SECTION ("Division Test") { - vivi::VectorisedDSP::sineVectorised (input.data(), 256); + Vectorised::sineVectorised (input.data(), 256); } SECTION ("Division Test") @@ -59,6 +59,6 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") const auto lowerLimit = -1.f; const auto upperLimit = -1.f; - vivi::VectorisedDSP::hardClipVectorised (input.data(), output.data(), 256, &lowerLimit, &upperLimit); + Vectorised::hardClipVectorised (input.data(), output.data(), 256, &lowerLimit, &upperLimit); } } \ No newline at end of file From ed34d294da14e79957e4064eb815372308ce32f2 Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Thu, 19 Jun 2025 07:10:58 +0100 Subject: [PATCH 2/6] Range based functions --- .../Accelerate/AccelerateRange.h | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 VectorisationWrappers/Accelerate/AccelerateRange.h diff --git a/VectorisationWrappers/Accelerate/AccelerateRange.h b/VectorisationWrappers/Accelerate/AccelerateRange.h new file mode 100644 index 0000000..7f50c18 --- /dev/null +++ b/VectorisationWrappers/Accelerate/AccelerateRange.h @@ -0,0 +1,50 @@ +#pragma once +#include +#include + +namespace Vectorised::Range +{ + template + static void minimumValue(T* Buffer, int BufferSize, T& OutputValue, int Stride = 1) + { + if constexpr (std::is_same_v) + vDSP_minv(Buffer, Stride, &OutputValue, BufferSize); + else if constexpr (std::is_same_v) + vDSP_minvD(Buffer, Stride, &OutputValue, BufferSize); + } + + template + static void maximumValue(T* Buffer, int BufferSize, T& OutputValue, int Stride = 1) + { + if constexpr (std::is_same_v) + vDSP_maxv(Buffer, Stride, &OutputValue, BufferSize); + else if constexpr (std::is_same_v) + vDSP_maxvD(Buffer, Stride, &OutputValue, BufferSize); + } + + template + static void minimumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int Stride, int& Position) + { + vDSP_Length pos = 0; + + if constexpr (std::is_same_v) + vDSP_minvi(Buffer, Stride, &OutputValue, &pos, BufferSize); + else if constexpr (std::is_same_v) + vDSP_minviD(Buffer, Stride, &OutputValue, &pos, BufferSize); + + Position = static_cast(pos); + } + + template + static void maximumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int Stride, int& Position) + { + vDSP_Length pos = 0; + + if constexpr (std::is_same_v) + vDSP_maxvi(Buffer, Stride, &OutputValue, &pos, BufferSize); + else if constexpr (std::is_same_v) + vDSP_maxviD(Buffer, Stride, &OutputValue, &pos, BufferSize); + + Position = static_cast(pos); + } +} From 7e182e0e61d3aa9af6ae8e1a81582066eabcbde5 Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Tue, 24 Jun 2025 19:09:33 +0100 Subject: [PATCH 3/6] Deleting range loop unit tests --- README.md | 2 +- VectorisationWrappers/AccelerateWrapperUnitTests.cpp | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/README.md b/README.md index 7cc057c..72aa42c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Vectorisation Formatting (MACOS support only - Temporary) +# 🐛 Vectorisation Formatting (MACOS support only - Temporary) ### Summary - Static wrapper functions around float & doubles processing per platform. diff --git a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp index 638dea9..43be4bc 100644 --- a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp +++ b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp @@ -15,23 +15,11 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") SECTION ("Addition Test") { Vectorised::additionVectorised (input.data(), output.data(), 256); - - for (const auto buffer : { &input, &output }) - { - for (const auto SampleValue : *buffer) - REQUIRE (SampleValue == 1.f); - } } SECTION ("Subtraction Test") { Vectorised::subtractionVectorised (input.data(), output.data(), 256); - - for (const auto buffer : { &input, &output }) - { - for (const auto SampleValue : *buffer) - REQUIRE (SampleValue == 0.f); - } } SECTION ("Multiplication Test") From 7ef4ace94b6e05dc0ff5c0773d0e2a7cc605514d Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Tue, 24 Jun 2025 19:32:12 +0100 Subject: [PATCH 4/6] Adding minimum range basic tests --- CMakeLists.txt | 10 ++++-- .../Accelerate/AccelerateRange.h | 2 +- .../AccelerateRangeUnitTests.cpp | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 VectorisationWrappers/AccelerateRangeUnitTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ea9055c..628787b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,16 @@ cmake_minimum_required (VERSION 3.25) -project (WRAPPER DESCRIPTION "DSP Library built ontop of JUCE" LANGUAGES CXX) +project (WRAPPER DESCRIPTION "Vectoisation Wrapper with Unit tested" LANGUAGES CXX) set (CMAKE_CXX_STANDARD 23) add_subdirectory (Catch2) if (APPLE) - add_executable (accelerate_DSP VectorisationWrappers/Accelerate/AccelerateWrapper.h - VectorisationWrappers/AccelerateWrapperUnitTests.cpp) + add_executable (accelerate_DSP VectorisationWrappers/Accelerate/AccelerateWrapper.h + VectorisationWrappers/Accelerate/AccelerateRange.h + VectorisationWrappers/Accelerate/AccelerateUtilities.h + VectorisationWrappers/AccelerateWrapperUnitTests.cpp + VectorisationWrappers/AccelerateRangeUnitTests.cpp) + target_link_libraries (accelerate_DSP PRIVATE Catch2::Catch2WithMain "$") ELSEIF (MSVC) message ("No Wrapper is availble") diff --git a/VectorisationWrappers/Accelerate/AccelerateRange.h b/VectorisationWrappers/Accelerate/AccelerateRange.h index 7f50c18..a2ee749 100644 --- a/VectorisationWrappers/Accelerate/AccelerateRange.h +++ b/VectorisationWrappers/Accelerate/AccelerateRange.h @@ -23,7 +23,7 @@ namespace Vectorised::Range } template - static void minimumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int Stride, int& Position) + static void minimumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int& Position, int Stride = 1) { vDSP_Length pos = 0; diff --git a/VectorisationWrappers/AccelerateRangeUnitTests.cpp b/VectorisationWrappers/AccelerateRangeUnitTests.cpp new file mode 100644 index 0000000..944e9fe --- /dev/null +++ b/VectorisationWrappers/AccelerateRangeUnitTests.cpp @@ -0,0 +1,36 @@ +#include +#include "Accelerate/AccelerateRange.h" +#include + +TEST_CASE ("Accelerate Ranges Unit tests", "[Accelerate Ranges]") +{ + const auto bufferSize = 256; + const auto minimumIndex = 2; + const auto maximumIndex = 18; + + const auto minValue = -1.f; + const auto maxValue = 1.f; + + + std::vector buffer (bufferSize); + buffer.assign (bufferSize, 0.f); + + buffer.at (minimumIndex) = minValue; + buffer.at (maximumIndex) = maxValue; + + SECTION ("Minimum Value") + { + auto outputValue = -10.f; + Vectorised::Range::minimumValue (buffer.data(), bufferSize, outputValue); + REQUIRE (outputValue == minValue); + } + + SECTION ("Minimum Value with Index") + { + auto outputValue = -10.f; + auto range = -1; + Vectorised::Range::minimumValueIndex (buffer.data(), bufferSize, outputValue, range); + REQUIRE (outputValue == minValue); + REQUIRE (range == minimumIndex); + } +} \ No newline at end of file From 1111e4c9eb544279cb181f1c0c448d2e59bda6df Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Tue, 24 Jun 2025 19:38:21 +0100 Subject: [PATCH 5/6] Basic unit tests for the wrapper floats only --- .../Accelerate/AccelerateRange.h | 2 +- .../AccelerateRangeUnitTests.cpp | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/VectorisationWrappers/Accelerate/AccelerateRange.h b/VectorisationWrappers/Accelerate/AccelerateRange.h index a2ee749..9b5f9ce 100644 --- a/VectorisationWrappers/Accelerate/AccelerateRange.h +++ b/VectorisationWrappers/Accelerate/AccelerateRange.h @@ -36,7 +36,7 @@ namespace Vectorised::Range } template - static void maximumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int Stride, int& Position) + static void maximumValueIndex(T* Buffer, int BufferSize, T& OutputValue, int& Position, int Stride = 1) { vDSP_Length pos = 0; diff --git a/VectorisationWrappers/AccelerateRangeUnitTests.cpp b/VectorisationWrappers/AccelerateRangeUnitTests.cpp index 944e9fe..d6fc6d3 100644 --- a/VectorisationWrappers/AccelerateRangeUnitTests.cpp +++ b/VectorisationWrappers/AccelerateRangeUnitTests.cpp @@ -10,8 +10,7 @@ TEST_CASE ("Accelerate Ranges Unit tests", "[Accelerate Ranges]") const auto minValue = -1.f; const auto maxValue = 1.f; - - + std::vector buffer (bufferSize); buffer.assign (bufferSize, 0.f); @@ -33,4 +32,21 @@ TEST_CASE ("Accelerate Ranges Unit tests", "[Accelerate Ranges]") REQUIRE (outputValue == minValue); REQUIRE (range == minimumIndex); } + + SECTION ("Maximum Value") + { + auto outputValue = -10.f; + auto range = -1; + Vectorised::Range::maximumValue (buffer.data(), bufferSize, outputValue); + REQUIRE (outputValue == maxValue); + } + + SECTION ("Maximum Value with Index") + { + auto outputValue = -10.f; + auto range = -1; + Vectorised::Range::maximumValueIndex (buffer.data(), bufferSize, outputValue, range); + REQUIRE (outputValue == maxValue); + REQUIRE (range == maximumIndex); + } } \ No newline at end of file From ba30f9962d87db4123579ebbe6c606d97a294855 Mon Sep 17 00:00:00 2001 From: Kristian McGurran Date: Tue, 24 Jun 2025 19:50:12 +0100 Subject: [PATCH 6/6] Templating unit tests for float & double support --- .../AccelerateRangeUnitTests.cpp | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/VectorisationWrappers/AccelerateRangeUnitTests.cpp b/VectorisationWrappers/AccelerateRangeUnitTests.cpp index d6fc6d3..f840aa4 100644 --- a/VectorisationWrappers/AccelerateRangeUnitTests.cpp +++ b/VectorisationWrappers/AccelerateRangeUnitTests.cpp @@ -1,52 +1,53 @@ #include #include "Accelerate/AccelerateRange.h" #include +#include -TEST_CASE ("Accelerate Ranges Unit tests", "[Accelerate Ranges]") +TEMPLATE_TEST_CASE("Accelerate Ranges Unit Tests", "[Accelerate Ranges]", float, double) { - const auto bufferSize = 256; - const auto minimumIndex = 2; - const auto maximumIndex = 18; + using T = TestType; - const auto minValue = -1.f; - const auto maxValue = 1.f; - - std::vector buffer (bufferSize); - buffer.assign (bufferSize, 0.f); + constexpr auto bufferSize = 256; + constexpr auto minimumIndex = 2; + constexpr auto maximumIndex = 18; - buffer.at (minimumIndex) = minValue; - buffer.at (maximumIndex) = maxValue; + const T minValue = static_cast(-1.0); + const T maxValue = static_cast(1.0); - SECTION ("Minimum Value") + std::vector buffer(bufferSize, static_cast(0)); + + buffer.at(minimumIndex) = minValue; + buffer.at(maximumIndex) = maxValue; + + SECTION("Minimum Value") { - auto outputValue = -10.f; - Vectorised::Range::minimumValue (buffer.data(), bufferSize, outputValue); - REQUIRE (outputValue == minValue); + T outputValue = static_cast(-10.0); + Vectorised::Range::minimumValue(buffer.data(), bufferSize, outputValue); + REQUIRE(outputValue == minValue); } - SECTION ("Minimum Value with Index") + SECTION("Minimum Value with Index") { - auto outputValue = -10.f; - auto range = -1; - Vectorised::Range::minimumValueIndex (buffer.data(), bufferSize, outputValue, range); - REQUIRE (outputValue == minValue); - REQUIRE (range == minimumIndex); + T outputValue = static_cast(-10.0); + int index = -1; + Vectorised::Range::minimumValueIndex(buffer.data(), bufferSize, outputValue, index); + REQUIRE(outputValue == minValue); + REQUIRE(index == minimumIndex); } - SECTION ("Maximum Value") + SECTION("Maximum Value") { - auto outputValue = -10.f; - auto range = -1; - Vectorised::Range::maximumValue (buffer.data(), bufferSize, outputValue); - REQUIRE (outputValue == maxValue); + T outputValue = static_cast(-10.0); + Vectorised::Range::maximumValue(buffer.data(), bufferSize, outputValue); + REQUIRE(outputValue == maxValue); } - SECTION ("Maximum Value with Index") + SECTION("Maximum Value with Index") { - auto outputValue = -10.f; - auto range = -1; - Vectorised::Range::maximumValueIndex (buffer.data(), bufferSize, outputValue, range); - REQUIRE (outputValue == maxValue); - REQUIRE (range == maximumIndex); + T outputValue = static_cast(-10.0); + int index = -1; + Vectorised::Range::maximumValueIndex(buffer.data(), bufferSize, outputValue, index); + REQUIRE(outputValue == maxValue); + REQUIRE(index == maximumIndex); } -} \ No newline at end of file +}