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/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/Accelerate/AccelerateRange.h b/VectorisationWrappers/Accelerate/AccelerateRange.h new file mode 100644 index 0000000..9b5f9ce --- /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& Position, int Stride = 1) + { + 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& Position, int Stride = 1) + { + 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); + } +} 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/AccelerateRangeUnitTests.cpp b/VectorisationWrappers/AccelerateRangeUnitTests.cpp new file mode 100644 index 0000000..f840aa4 --- /dev/null +++ b/VectorisationWrappers/AccelerateRangeUnitTests.cpp @@ -0,0 +1,53 @@ +#include +#include "Accelerate/AccelerateRange.h" +#include +#include + +TEMPLATE_TEST_CASE("Accelerate Ranges Unit Tests", "[Accelerate Ranges]", float, double) +{ + using T = TestType; + + constexpr auto bufferSize = 256; + constexpr auto minimumIndex = 2; + constexpr auto maximumIndex = 18; + + const T minValue = static_cast(-1.0); + const T maxValue = static_cast(1.0); + + std::vector buffer(bufferSize, static_cast(0)); + + buffer.at(minimumIndex) = minValue; + buffer.at(maximumIndex) = maxValue; + + SECTION("Minimum Value") + { + T outputValue = static_cast(-10.0); + Vectorised::Range::minimumValue(buffer.data(), bufferSize, outputValue); + REQUIRE(outputValue == minValue); + } + + SECTION("Minimum Value with Index") + { + 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") + { + T outputValue = static_cast(-10.0); + Vectorised::Range::maximumValue(buffer.data(), bufferSize, outputValue); + REQUIRE(outputValue == maxValue); + } + + SECTION("Maximum Value with Index") + { + T outputValue = static_cast(-10.0); + int index = -1; + Vectorised::Range::maximumValueIndex(buffer.data(), bufferSize, outputValue, index); + REQUIRE(outputValue == maxValue); + REQUIRE(index == maximumIndex); + } +} diff --git a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp index 4af6848..43be4bc 100644 --- a/VectorisationWrappers/AccelerateWrapperUnitTests.cpp +++ b/VectorisationWrappers/AccelerateWrapperUnitTests.cpp @@ -14,44 +14,32 @@ TEST_CASE("VDSP wrapper testing", "[VDSP Wrapper]") SECTION ("Addition Test") { - vivi::VectorisedDSP::additionVectorised (input.data(), output.data(), 256); - - for (const auto buffer : { &input, &output }) - { - for (const auto SampleValue : *buffer) - REQUIRE (SampleValue == 1.f); - } + Vectorised::additionVectorised (input.data(), output.data(), 256); } SECTION ("Subtraction Test") { - vivi::VectorisedDSP::subtractionVectorised (input.data(), output.data(), 256); - - for (const auto buffer : { &input, &output }) - { - for (const auto SampleValue : *buffer) - REQUIRE (SampleValue == 0.f); - } + Vectorised::subtractionVectorised (input.data(), output.data(), 256); } 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 +47,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