From 8795ffb03c1bb84a0d93e4ece153ceaa86118594 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Fri, 1 Dec 2017 16:13:40 +0000 Subject: COMPMID-700: Adds CPPPermute function Change-Id: I8f6adc67f6e6157710fca540f217d70e6f297217 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/111721 Tested-by: BSG Visual Compute Jenkins server to access repositories on http://mpd-gerrit.cambridge.arm.com Reviewed-by: Anthony Barbier --- SConscript | 3 + arm_compute/core/CPP/CPPKernels.h | 1 + arm_compute/core/CPP/kernels/CPPPermuteKernel.h | 93 +++++++++++++ arm_compute/core/Dimensions.h | 15 +- arm_compute/core/Helpers.h | 18 +++ arm_compute/core/Strides.h | 3 +- arm_compute/core/Types.h | 4 + arm_compute/core/utils/misc/utility.h | 72 ++++++++++ arm_compute/runtime/CPP/CPPFunctions.h | 30 ++++ arm_compute/runtime/CPP/ICPPSimpleFunction.h | 48 +++++++ arm_compute/runtime/CPP/functions/CPPPermute.h | 57 ++++++++ src/core/CPP/kernels/CPPPermuteKernel.cpp | 169 +++++++++++++++++++++++ src/core/NEON/kernels/NEMinMaxLocationKernel.cpp | 35 ++--- src/runtime/CPP/ICPPSimpleFunction.cpp | 38 +++++ src/runtime/CPP/functions/CPPPermute.cpp | 41 ++++++ tests/SConscript | 4 + tests/validation/CPP/Permute.cpp | 122 ++++++++++++++++ tests/validation/fixtures/PermuteFixture.h | 112 +++++++++++++++ tests/validation/reference/Permute.cpp | 66 +++++++++ tests/validation/reference/Permute.h | 43 ++++++ 20 files changed, 944 insertions(+), 30 deletions(-) create mode 100644 arm_compute/core/CPP/kernels/CPPPermuteKernel.h create mode 100644 arm_compute/core/utils/misc/utility.h create mode 100644 arm_compute/runtime/CPP/CPPFunctions.h create mode 100644 arm_compute/runtime/CPP/ICPPSimpleFunction.h create mode 100644 arm_compute/runtime/CPP/functions/CPPPermute.h create mode 100644 src/core/CPP/kernels/CPPPermuteKernel.cpp create mode 100644 src/runtime/CPP/ICPPSimpleFunction.cpp create mode 100644 src/runtime/CPP/functions/CPPPermute.cpp create mode 100644 tests/validation/CPP/Permute.cpp create mode 100644 tests/validation/fixtures/PermuteFixture.h create mode 100644 tests/validation/reference/Permute.cpp create mode 100644 tests/validation/reference/Permute.h diff --git a/SConscript b/SConscript index 91dc60166a..3637858626 100644 --- a/SConscript +++ b/SConscript @@ -142,6 +142,9 @@ core_files += Glob('src/core/CPP/kernels/*.cpp') core_files += Glob('src/core/utils/*/*.cpp') runtime_files = Glob('src/runtime/*.cpp') +runtime_files += Glob('src/runtime/CPP/ICPPSimpleFunction.cpp') +runtime_files += Glob('src/runtime/CPP/functions/*.cpp') + # CLHarrisCorners uses the Scheduler to run CPP kernels runtime_files += Glob('src/runtime/CPP/SingleThreadScheduler.cpp') diff --git a/arm_compute/core/CPP/CPPKernels.h b/arm_compute/core/CPP/CPPKernels.h index 1eabfa9437..f55f41b0eb 100644 --- a/arm_compute/core/CPP/CPPKernels.h +++ b/arm_compute/core/CPP/CPPKernels.h @@ -27,6 +27,7 @@ /* Header regrouping all the CPP kernels */ #include "arm_compute/core/CPP/kernels/CPPCornerCandidatesKernel.h" #include "arm_compute/core/CPP/kernels/CPPDetectionWindowNonMaximaSuppressionKernel.h" +#include "arm_compute/core/CPP/kernels/CPPPermuteKernel.h" #include "arm_compute/core/CPP/kernels/CPPSortEuclideanDistanceKernel.h" #endif /* __ARM_COMPUTE_CPPKERNELS_H__ */ diff --git a/arm_compute/core/CPP/kernels/CPPPermuteKernel.h b/arm_compute/core/CPP/kernels/CPPPermuteKernel.h new file mode 100644 index 0000000000..31011e4a5c --- /dev/null +++ b/arm_compute/core/CPP/kernels/CPPPermuteKernel.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_CPPPERMUTEKERNEL_H__ +#define __ARM_COMPUTE_CPPPERMUTEKERNEL_H__ + +#include "arm_compute/core/CPP/ICPPKernel.h" + +namespace arm_compute +{ +class ITensor; + +/** CPP kernel to perform tensor permutation. + * + * Permutes given a permutation vector + */ +class CPPPermuteKernel : public ICPPKernel +{ +public: + /** Default constructor */ + CPPPermuteKernel(); + /** Prevent instances of this class from being copied (As this class contains pointers) */ + CPPPermuteKernel(const CPPPermuteKernel &) = delete; + /** Prevent instances of this class from being copied (As this class contains pointers) */ + CPPPermuteKernel &operator=(const CPPPermuteKernel &) = delete; + /** Allow instances of this class to be moved */ + CPPPermuteKernel(CPPPermuteKernel &&) = default; + /** Allow instances of this class to be moved */ + CPPPermuteKernel &operator=(CPPPermuteKernel &&) = default; + /** Default destructor */ + ~CPPPermuteKernel() = default; + + /** Set the input and output of the kernel. + * + * @param[in] input The input tensor to permute. Data types supported: U8/S8/QS8/QASYMM8/U16/S16/QS16/F16/U32/S32/F32 + * @param[out] output The output tensor. Data types supported: Same as @p input + * @param[in] perm Permutation vector + */ + void configure(const ITensor *input, ITensor *output, const PermutationVector &perm); + /** Static function to check if given info will lead to a valid configuration of @ref CPPPermuteKernel + * + * @param[in] input The input tensor to permute. Data types supported: U8/S8/QS8/QASYMM8/U16/S16/QS16/F16/U32/S32/F32 + * @param[in] output The output tensor. Data types supported: Same as @p input + * @param[in] perm Permutation vector + * + * @return an error status + */ + static Error validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm); + + // Inherited methods overridden: + void run(const Window &window, const ThreadInfo &info) override; + +private: + /** Template function to run the permute + * + * @param[in] window Region on which to execute the kernel. (Must be a valid region of the window returned by window()). + */ + template + void run_permute(const Window &window); + + /** Common signature for all the specialised permute functions + * + * @param[in] window Region on which to execute the kernel. + */ + using PermuteFunctionPtr = void (CPPPermuteKernel::*)(const Window &window); + + PermuteFunctionPtr _func; + const ITensor *_input; + ITensor *_output; + PermutationVector _perm; +}; +} // namespace arm_compute +#endif /*__ARM_COMPUTE_CPPPERMUTEKERNEL_H__ */ diff --git a/arm_compute/core/Dimensions.h b/arm_compute/core/Dimensions.h index 912b9d57d7..ae8d6c3503 100644 --- a/arm_compute/core/Dimensions.h +++ b/arm_compute/core/Dimensions.h @@ -100,7 +100,20 @@ public: * * @return The size of the requested dimension. */ - T operator[](size_t dimension) const + const T &operator[](size_t dimension) const + { + ARM_COMPUTE_ERROR_ON(dimension >= num_max_dimensions); + return _id[dimension]; + } + /** Generic accessor to get the size of any dimension + * + * @note Precondition: dimension < Dimensions::num_max_dimensions + * + * @param[in] dimension Dimension of the wanted size + * + * @return The size of the requested dimension. + */ + T &operator[](size_t dimension) { ARM_COMPUTE_ERROR_ON(dimension >= num_max_dimensions); return _id[dimension]; diff --git a/arm_compute/core/Helpers.h b/arm_compute/core/Helpers.h index 13d1f6c99f..1be24e1841 100644 --- a/arm_compute/core/Helpers.h +++ b/arm_compute/core/Helpers.h @@ -33,6 +33,7 @@ #include "arm_compute/core/TensorShape.h" #include "arm_compute/core/Types.h" #include "arm_compute/core/Window.h" +#include "arm_compute/core/utils/misc/utility.h" #include #include @@ -459,6 +460,23 @@ inline Strides compute_strides(const ITensorInfo &info) return compute_strides(info, info.element_size()); } +/** Permutes given Dimensions according to a permutation vector + * + * @warning Validity of permutation is not checked + * + * @param[in, out] dimensions Dimensions to permute + * @param[in] perm Permutation vector + */ +template +inline void permute(Dimensions &dimensions, const PermutationVector &perm) +{ + auto copy_dimensions = utility::make_array::num_max_dimensions>(dimensions.begin(), dimensions.end()); + for(unsigned int i = 0; i < perm.num_dimensions(); ++i) + { + dimensions[i] = copy_dimensions[perm[i]]; + } +} + /* Auto initialize the tensor info (shape, number of channels, data type and fixed point position) if the current assignment is empty. * * @param[in,out] info Tensor info used to check and assign. diff --git a/arm_compute/core/Strides.h b/arm_compute/core/Strides.h index 329fafb5f8..105fdfde4e 100644 --- a/arm_compute/core/Strides.h +++ b/arm_compute/core/Strides.h @@ -26,7 +26,6 @@ #include "arm_compute/core/Dimensions.h" #include "arm_compute/core/Error.h" -#include "arm_compute/core/Types.h" #include #include @@ -58,5 +57,5 @@ public: /** Default destructor */ ~Strides() = default; }; -} +} // namespace arm_compute #endif /*__ARM_COMPUTE_STRIDES_H__*/ diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 4ecaec1eb9..36ec38ff68 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -25,6 +25,7 @@ #define __ARM_COMPUTE_TYPES_H__ #include "arm_compute/core/Coordinates.h" +#include "arm_compute/core/Strides.h" #include "arm_compute/core/TensorShape.h" #include "support/Half.h" @@ -38,6 +39,9 @@ namespace arm_compute /** 16-bit floating point type */ using half = half_float::half; +/** Permutation vector */ +using PermutationVector = Strides; + /** Image colour formats */ enum class Format { diff --git a/arm_compute/core/utils/misc/utility.h b/arm_compute/core/utils/misc/utility.h new file mode 100644 index 0000000000..898d0cdea8 --- /dev/null +++ b/arm_compute/core/utils/misc/utility.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_MISC_UTILITY_H__ +#define __ARM_COMPUTE_MISC_UTILITY_H__ + +#include + +namespace arm_compute +{ +namespace utility +{ +/** @cond */ +template +struct index_sequence +{ +}; + +template +struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... > +{ +}; + +template +struct index_sequence_generator<0u, S...> : index_sequence +{ + using type = index_sequence; +}; + +template +using index_sequence_t = typename index_sequence_generator::type; +/** @endcond */ + +namespace detail +{ +template ::value_type, sizeof...(S)>> +T make_array(Iterator first, index_sequence) +{ + return T{ { first[S]... } }; +} +} // namespace detail + +template +std::array::value_type, N> make_array(Iterator first, Iterator last) +{ + return detail::make_array(first, index_sequence_t {}); +} +} // namespace misc +} // namespace arm_compute +#endif /* __ARM_COMPUTE_MISC_UTILITY_H__ */ diff --git a/arm_compute/runtime/CPP/CPPFunctions.h b/arm_compute/runtime/CPP/CPPFunctions.h new file mode 100644 index 0000000000..1f01ffac82 --- /dev/null +++ b/arm_compute/runtime/CPP/CPPFunctions.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_CPPFUNCTIONS_H__ +#define __ARM_COMPUTE_CPPFUNCTIONS_H__ + +/* Header regrouping all the CPP functions */ +#include "arm_compute/runtime/CPP/functions/CPPPermute.h" + +#endif /* __ARM_COMPUTE_CPPFUNCTIONS_H__ */ diff --git a/arm_compute/runtime/CPP/ICPPSimpleFunction.h b/arm_compute/runtime/CPP/ICPPSimpleFunction.h new file mode 100644 index 0000000000..d1bd232588 --- /dev/null +++ b/arm_compute/runtime/CPP/ICPPSimpleFunction.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_ICPPSIMPLEFUNCTION_H__ +#define __ARM_COMPUTE_ICPPSIMPLEFUNCTION_H__ + +#include "arm_compute/core/CPP/ICPPKernel.h" +#include "arm_compute/runtime/IFunction.h" + +#include + +namespace arm_compute +{ +/** Basic interface for functions which have a single CPP kernel */ +class ICPPSimpleFunction : public IFunction +{ +public: + /** Constructor */ + ICPPSimpleFunction(); + + // Inherited methods overridden: + void run() override final; + +protected: + std::unique_ptr _kernel; /**< Kernel to run */ +}; +} // namespace arm_compute +#endif /*__ARM_COMPUTE_ICPPSIMPLEFUNCTION_H__ */ diff --git a/arm_compute/runtime/CPP/functions/CPPPermute.h b/arm_compute/runtime/CPP/functions/CPPPermute.h new file mode 100644 index 0000000000..b7643608ab --- /dev/null +++ b/arm_compute/runtime/CPP/functions/CPPPermute.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_CPPPERMUTE_H__ +#define __ARM_COMPUTE_CPPPERMUTE_H__ + +#include "arm_compute/runtime/CPP/ICPPSimpleFunction.h" + +#include "arm_compute/core/Types.h" + +namespace arm_compute +{ +class ITensor; + +/** Basic function to run @ref CPPPermuteKernel */ +class CPPPermute : public ICPPSimpleFunction +{ +public: + /** Configure the permute CPP kernel + * + * @param[in] input The input tensor to permute. Data types supported: U8/S8/QS8/QASYMM8/U16/S16/QS16/F16/U32/S32/F32 + * @param[out] output The output tensor. Data types supported: Same as @p input + * @param[in] perm Permutation vector + */ + void configure(const ITensor *input, ITensor *output, const PermutationVector &perm); + /** Static function to check if given info will lead to a valid configuration of @ref CPPPermute + * + * @param[in] input The input tensor to permute. Data types supported: U8/S8/QS8/QASYMM8/U16/S16/QS16/F16/U32/S32/F32 + * @param[in] output The output tensor. Data types supported: Same as @p input + * @param[in] perm Permutation vector + * + * @return an error status + */ + static Error validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm); +}; +} +#endif /* __ARM_COMPUTE_CPPPERMUTE_H__ */ diff --git a/src/core/CPP/kernels/CPPPermuteKernel.cpp b/src/core/CPP/kernels/CPPPermuteKernel.cpp new file mode 100644 index 0000000000..55cc00ffbf --- /dev/null +++ b/src/core/CPP/kernels/CPPPermuteKernel.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/CPP/kernels/CPPPermuteKernel.h" + +#include "arm_compute/core/Error.h" +#include "arm_compute/core/Helpers.h" +#include "arm_compute/core/ITensor.h" +#include "arm_compute/core/TensorInfo.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/core/Validate.h" + +#include +#include + +using namespace arm_compute; + +namespace +{ +TensorShape get_output_shape(const ITensorInfo *input, const PermutationVector &perm) +{ + TensorShape output_shape = input->tensor_shape(); + permute(output_shape, perm); + return output_shape; +} + +Error validate_arguments(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm) +{ + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8, DataType::S8, DataType::QS8, DataType::QASYMM8, + DataType::U16, DataType::S16, DataType::QS16, + DataType::U32, DataType::S32, + DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_MSG(input->num_dimensions() < 3, "Invalid input size!"); + ARM_COMPUTE_RETURN_ERROR_ON_MSG(perm.num_dimensions() != 3 && ((perm[0] != 2 && perm[1] != 0 && perm[2] != 1) || (perm[0] != 1 && perm[1] != 2 && perm[2] != 0)), + "Only [2, 0, 1] and [1, 2, 0] permutation is supported"); + + // Validate configured output + if(output->total_size() != 0) + { + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(), get_output_shape(input, perm)); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_FIXED_POINT(input, output); + } + + return Error{}; +} +} // namespace + +template +void CPPPermuteKernel::run_permute(const Window &window) +{ + const int output_stride_x = _output->info()->strides_in_bytes().x(); + const int output_stride_y = _output->info()->strides_in_bytes().y(); + const int output_stride_z = _output->info()->strides_in_bytes().z(); + + Window window_out(window); + window_out.set(Window::DimX, Window::Dimension(0, 0, 0)); + window_out.set(Window::DimY, Window::Dimension(0, 0, 0)); + window_out.set(Window::DimZ, Window::Dimension(0, 0, 0)); + + // Create iterators + Iterator in(_input, window); + Iterator out(_output, window_out); + + // Run [2, 0, 1] permute + if(_perm[0] == 2 && _perm[1] == 0 && _perm[2] == 1) + { + execute_window_loop(window, [&](const Coordinates & id) + { + const int idx = id.y() * output_stride_z + id.x() * output_stride_y + id.z() * output_stride_x; + *(reinterpret_cast(out.ptr() + idx)) = *(reinterpret_cast(in.ptr())); + }, + in, out); + } + // Run [1, 2, 0] permute + else + { + execute_window_loop(window, [&](const Coordinates & id) + { + const int idx = id.x() * output_stride_z + id.z() * output_stride_y + id.y() * output_stride_x; + *(reinterpret_cast(out.ptr() + idx)) = *(reinterpret_cast(in.ptr())); + }, + in, out); + } +} + +CPPPermuteKernel::CPPPermuteKernel() + : _func(), _input(nullptr), _output(nullptr), _perm() +{ +} + +void CPPPermuteKernel::configure(const ITensor *input, ITensor *output, const PermutationVector &perm) +{ + ARM_COMPUTE_ERROR_ON_NULLPTR(input, output); + + // Output auto inizialitation if not yet initialized + auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(get_output_shape(input->info(), perm))); + + // Perform validation step + ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), output->info(), perm)); + + _input = input; + _output = output; + _perm = perm; + + switch(input->info()->element_size()) + { + case 1: + _func = &CPPPermuteKernel::run_permute; + break; + case 2: + _func = &CPPPermuteKernel::run_permute; + break; + case 4: + _func = &CPPPermuteKernel::run_permute; + break; + default: + ARM_COMPUTE_ERROR("Element size not supported"); + break; + } + + // Configure kernel window + Window win = calculate_max_window(*input->info(), Steps()); + + // The CPPPermute doesn't need padding so update_window_and_padding() can be skipped + Coordinates coord; + coord.set_num_dimensions(output->info()->num_dimensions()); + output->info()->set_valid_region(ValidRegion(coord, output->info()->tensor_shape())); + + ICPPKernel::configure(win); +} + +Error CPPPermuteKernel::validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm) +{ + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, output, perm)); + return Error{}; +} + +void CPPPermuteKernel::run(const Window &window, const ThreadInfo &info) +{ + ARM_COMPUTE_UNUSED(info); + ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); + ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICPPKernel::window(), window); + + if(_func != nullptr) + { + (this->*_func)(window); + } +} diff --git a/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp b/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp index c7dc03c8c8..ad66acd8fa 100644 --- a/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp +++ b/src/core/NEON/kernels/NEMinMaxLocationKernel.cpp @@ -32,6 +32,7 @@ #include "arm_compute/core/Types.h" #include "arm_compute/core/Validate.h" #include "arm_compute/core/Window.h" +#include "arm_compute/core/utils/misc/utility.h" #include #include @@ -319,34 +320,14 @@ bool NEMinMaxLocationKernel::is_parallelisable() const return false; } -template -struct index_seq -{ - index_seq() = default; - index_seq(const index_seq &) = default; - index_seq &operator=(const index_seq &) = default; - index_seq(index_seq &&) noexcept = default; - index_seq &operator=(index_seq &&) noexcept = default; - virtual ~index_seq() = default; -}; -template -struct gen_index_seq : gen_index_seq < N - 1, N - 1, S... > -{ -}; -template -struct gen_index_seq<0u, S...> : index_seq -{ - using type = index_seq; -}; - -template -struct NEMinMaxLocationKernel::create_func_table> +template +struct NEMinMaxLocationKernel::create_func_table> { static const NEMinMaxLocationKernel::MinMaxLocFunction func_table[sizeof...(N)]; }; -template -const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table>::func_table[sizeof...(N)] = +template +const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table>::func_table[sizeof...(N)] = { &NEMinMaxLocationKernel::minmax_loc... }; @@ -378,13 +359,13 @@ void NEMinMaxLocationKernel::configure(const IImage *input, void *min, void *max switch(input->info()->data_type()) { case DataType::U8: - _func = create_func_table::type>::func_table[table_idx]; + _func = create_func_table>::func_table[table_idx]; break; case DataType::S16: - _func = create_func_table::type>::func_table[table_idx]; + _func = create_func_table>::func_table[table_idx]; break; case DataType::F32: - _func = create_func_table::type>::func_table[table_idx]; + _func = create_func_table>::func_table[table_idx]; break; default: ARM_COMPUTE_ERROR("Unsupported data type"); diff --git a/src/runtime/CPP/ICPPSimpleFunction.cpp b/src/runtime/CPP/ICPPSimpleFunction.cpp new file mode 100644 index 0000000000..42a2d2228c --- /dev/null +++ b/src/runtime/CPP/ICPPSimpleFunction.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/runtime/CPP/ICPPSimpleFunction.h" + +#include "arm_compute/runtime/Scheduler.h" + +using namespace arm_compute; + +ICPPSimpleFunction::ICPPSimpleFunction() // NOLINT + : _kernel() +{ +} + +void ICPPSimpleFunction::run() +{ + Scheduler::get().schedule(_kernel.get(), Window::DimY); +} diff --git a/src/runtime/CPP/functions/CPPPermute.cpp b/src/runtime/CPP/functions/CPPPermute.cpp new file mode 100644 index 0000000000..5b92718542 --- /dev/null +++ b/src/runtime/CPP/functions/CPPPermute.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/runtime/CPP/functions/CPPPermute.h" + +#include "arm_compute/core/CPP/kernels/CPPPermuteKernel.h" +#include "support/ToolchainSupport.h" + +using namespace arm_compute; + +void CPPPermute::configure(const ITensor *input, ITensor *output, const PermutationVector &perm) +{ + auto k = arm_compute::support::cpp14::make_unique(); + k->configure(input, output, perm); + _kernel = std::move(k); +} + +Error CPPPermute::validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm) +{ + return CPPPermuteKernel::validate(input, output, perm); +} diff --git a/tests/SConscript b/tests/SConscript index 37ec95f589..240a8fba45 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -87,6 +87,10 @@ files_validation += Glob('validation/reference/*.cpp') files_validation += Glob('validation/UNIT/*/*.cpp') files_validation += Glob('validation/UNIT/*.cpp') +# Add CPP tests +filter_pattern = test_env['test_filter'] +files_validation += Glob('validation/CPP/' + filter_pattern) + if env['opencl']: Import('opencl') filter_pattern = test_env['test_filter'] diff --git a/tests/validation/CPP/Permute.cpp b/tests/validation/CPP/Permute.cpp new file mode 100644 index 0000000000..7f27f3cfff --- /dev/null +++ b/tests/validation/CPP/Permute.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CPP/functions/CPPPermute.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/PermuteFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace +{ +const auto PermuteParametersSmall = combine(concat(datasets::Small3DShapes(), datasets::Small4DShapes()), + framework::dataset::make("PermutationVector", { PermutationVector(2U, 0U, 1U), PermutationVector(1U, 2U, 0U) })); +const auto PermuteParametersLarge = combine(concat(datasets::Large3DShapes(), datasets::Large4DShapes()), + framework::dataset::make("PermutationVector", { PermutationVector(2U, 0U, 1U), PermutationVector(1U, 2U, 0U) })); +} // namespace +TEST_SUITE(CPP) +TEST_SUITE(Permute) + +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::Small4DShapes(), framework::dataset::make("DataType", { DataType::S8, DataType::U8, DataType::S16, DataType::U16, DataType::U32, DataType::S32, DataType::F16, DataType::F32 })), + shape, data_type) +{ + // Define permutation vector + const PermutationVector perm(2U, 0U, 1U); + + // Permute shapes + TensorShape output_shape = shape; + permute(output_shape, perm); + + // Create tensors + Tensor ref_src = create_tensor(shape, data_type); + Tensor dst = create_tensor(output_shape, data_type); + + // Create and Configure function + CPPPermute perm_func; + perm_func.configure(&ref_src, &dst, perm); + + // Validate valid region + const ValidRegion valid_region = shape_to_valid_region(output_shape); + validate(dst.info()->valid_region(), valid_region); +} + +template +using CPPPermuteFixture = PermuteValidationFixture; + +TEST_SUITE(U8) +FIXTURE_DATA_TEST_CASE(RunSmall, CPPPermuteFixture, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture, framework::DatasetMode::NIGHTLY, combine(PermuteParametersLarge, framework::dataset::make("DataType", DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE(U16) +FIXTURE_DATA_TEST_CASE(RunSmall, CPPPermuteFixture, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture, framework::DatasetMode::NIGHTLY, combine(PermuteParametersLarge, framework::dataset::make("DataType", DataType::U16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE(U32) +FIXTURE_DATA_TEST_CASE(RunSmall, CPPPermuteFixture, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture, framework::DatasetMode::NIGHTLY, combine(PermuteParametersLarge, framework::dataset::make("DataType", DataType::U32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/fixtures/PermuteFixture.h b/tests/validation/fixtures/PermuteFixture.h new file mode 100644 index 0000000000..3aae384706 --- /dev/null +++ b/tests/validation/fixtures/PermuteFixture.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_TEST_PERMUTE_FIXTURE +#define ARM_COMPUTE_TEST_PERMUTE_FIXTURE + +#include "arm_compute/core/Helpers.h" +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/Tensor.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/reference/Permute.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template +class PermuteValidationFixture : public framework::Fixture +{ +public: + template + void setup(TensorShape shape, PermutationVector perm, DataType data_type) + { + _target = compute_target(shape, data_type, perm); + _reference = compute_reference(shape, data_type, perm); + } + +protected: + template + void fill(U &&tensor) + { + library->fill_tensor_uniform(tensor, 0); + } + + TensorType compute_target(const TensorShape &shape, DataType data_type, PermutationVector perm) + { + // Permute shapes + TensorShape output_shape = shape; + permute(output_shape, perm); + + // Create tensors + TensorType src = create_tensor(shape, data_type); + TensorType dst = create_tensor(output_shape, data_type); + + // Create and configure function + FunctionType perm_func; + perm_func.configure(&src, &dst, perm); + + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + src.allocator()->allocate(); + dst.allocator()->allocate(); + + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + fill(AccessorType(src)); + + // Compute function + perm_func.run(); + + return dst; + } + + SimpleTensor compute_reference(const TensorShape &shape, DataType data_type, PermutationVector perm) + { + // Create reference + SimpleTensor src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::permute(src, perm); + } + + TensorType _target{}; + SimpleTensor _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_PERMUTE_FIXTURE */ diff --git a/tests/validation/reference/Permute.cpp b/tests/validation/reference/Permute.cpp new file mode 100644 index 0000000000..4a12ca6959 --- /dev/null +++ b/tests/validation/reference/Permute.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "Permute.h" + +#include "arm_compute/core/Types.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor permute(const SimpleTensor &src, PermutationVector perm) +{ + // Permute shapes + TensorShape dst_shape = src.shape(); + permute(dst_shape, perm); + + // Create reference + SimpleTensor dst{ dst_shape, src.data_type() }; + + // Compute reference + for(int i = 0; i < src.num_elements(); ++i) + { + Coordinates coord = index2coord(src.shape(), i); + permute(coord, perm); + const size_t dst_index = coord2index(dst.shape(), coord); + + dst[dst_index] = src[i]; + } + + return dst; +} + +template SimpleTensor permute(const SimpleTensor &src, PermutationVector perm); +template SimpleTensor permute(const SimpleTensor &src, PermutationVector perm); +template SimpleTensor permute(const SimpleTensor &src, PermutationVector perm); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/reference/Permute.h b/tests/validation/reference/Permute.h new file mode 100644 index 0000000000..295ad2b2ef --- /dev/null +++ b/tests/validation/reference/Permute.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_TEST_PERMUTE_H__ +#define __ARM_COMPUTE_TEST_PERMUTE_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor permute(const SimpleTensor &src, PermutationVector perm); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_PERMUTE_H__ */ -- cgit v1.2.1