diff options
author | Georgios Pinitas <georgios.pinitas@arm.com> | 2017-12-01 16:13:40 +0000 |
---|---|---|
committer | Anthony Barbier <anthony.barbier@arm.com> | 2018-11-02 16:42:17 +0000 |
commit | 8795ffb03c1bb84a0d93e4ece153ceaa86118594 (patch) | |
tree | 87d6fec8a6422dd195a79c38bbe170afd7106fc3 | |
parent | ab4907325ea264efc26b89ebad7e10522cb823e5 (diff) | |
download | ComputeLibrary-8795ffb03c1bb84a0d93e4ece153ceaa86118594.tar.gz |
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 <bsgcomp@arm.com>
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
-rw-r--r-- | SConscript | 3 | ||||
-rw-r--r-- | arm_compute/core/CPP/CPPKernels.h | 1 | ||||
-rw-r--r-- | arm_compute/core/CPP/kernels/CPPPermuteKernel.h | 93 | ||||
-rw-r--r-- | arm_compute/core/Dimensions.h | 15 | ||||
-rw-r--r-- | arm_compute/core/Helpers.h | 18 | ||||
-rw-r--r-- | arm_compute/core/Strides.h | 3 | ||||
-rw-r--r-- | arm_compute/core/Types.h | 4 | ||||
-rw-r--r-- | arm_compute/core/utils/misc/utility.h | 72 | ||||
-rw-r--r-- | arm_compute/runtime/CPP/CPPFunctions.h | 30 | ||||
-rw-r--r-- | arm_compute/runtime/CPP/ICPPSimpleFunction.h | 48 | ||||
-rw-r--r-- | arm_compute/runtime/CPP/functions/CPPPermute.h | 57 | ||||
-rw-r--r-- | src/core/CPP/kernels/CPPPermuteKernel.cpp | 169 | ||||
-rw-r--r-- | src/core/NEON/kernels/NEMinMaxLocationKernel.cpp | 35 | ||||
-rw-r--r-- | src/runtime/CPP/ICPPSimpleFunction.cpp | 38 | ||||
-rw-r--r-- | src/runtime/CPP/functions/CPPPermute.cpp | 41 | ||||
-rw-r--r-- | tests/SConscript | 4 | ||||
-rw-r--r-- | tests/validation/CPP/Permute.cpp | 122 | ||||
-rw-r--r-- | tests/validation/fixtures/PermuteFixture.h | 112 | ||||
-rw-r--r-- | tests/validation/reference/Permute.cpp | 66 | ||||
-rw-r--r-- | tests/validation/reference/Permute.h | 43 |
20 files changed, 944 insertions, 30 deletions
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 <typename T> + 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 <array> #include <cstddef> @@ -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 <typename T> +inline void permute(Dimensions<T> &dimensions, const PermutationVector &perm) +{ + auto copy_dimensions = utility::make_array<Dimensions<T>::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 <algorithm> #include <array> @@ -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 <array> + +namespace arm_compute +{ +namespace utility +{ +/** @cond */ +template <std::size_t...> +struct index_sequence +{ +}; + +template <std::size_t N, std::size_t... S> +struct index_sequence_generator : index_sequence_generator < N - 1, N - 1, S... > +{ +}; + +template <std::size_t... S> +struct index_sequence_generator<0u, S...> : index_sequence<S...> +{ + using type = index_sequence<S...>; +}; + +template <std::size_t N> +using index_sequence_t = typename index_sequence_generator<N>::type; +/** @endcond */ + +namespace detail +{ +template <std::size_t... S, + typename Iterator, + typename T = std::array<typename std::iterator_traits<Iterator>::value_type, sizeof...(S)>> +T make_array(Iterator first, index_sequence<S...>) +{ + return T{ { first[S]... } }; +} +} // namespace detail + +template <std::size_t N, typename Iterator> +std::array<typename std::iterator_traits<Iterator>::value_type, N> make_array(Iterator first, Iterator last) +{ + return detail::make_array(first, index_sequence_t<N> {}); +} +} // 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 <memory> + +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<ICPPKernel> _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 <cstddef> +#include <cstdint> + +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 <typename T> +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<T *>(out.ptr() + idx)) = *(reinterpret_cast<const T *>(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<T *>(out.ptr() + idx)) = *(reinterpret_cast<const T *>(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<uint8_t>; + break; + case 2: + _func = &CPPPermuteKernel::run_permute<uint16_t>; + break; + case 4: + _func = &CPPPermuteKernel::run_permute<uint32_t>; + 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 <algorithm> #include <arm_neon.h> @@ -319,34 +320,14 @@ bool NEMinMaxLocationKernel::is_parallelisable() const return false; } -template <unsigned int...> -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 <unsigned int N, unsigned int... S> -struct gen_index_seq : gen_index_seq < N - 1, N - 1, S... > -{ -}; -template <unsigned int... S> -struct gen_index_seq<0u, S...> : index_seq<S...> -{ - using type = index_seq<S...>; -}; - -template <class T, unsigned int... N> -struct NEMinMaxLocationKernel::create_func_table<T, index_seq<N...>> +template <class T, std::size_t... N> +struct NEMinMaxLocationKernel::create_func_table<T, utility::index_sequence<N...>> { static const NEMinMaxLocationKernel::MinMaxLocFunction func_table[sizeof...(N)]; }; -template <class T, unsigned int... N> -const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table<T, index_seq<N...>>::func_table[sizeof...(N)] = +template <class T, std::size_t... N> +const NEMinMaxLocationKernel::MinMaxLocFunction NEMinMaxLocationKernel::create_func_table<T, utility::index_sequence<N...>>::func_table[sizeof...(N)] = { &NEMinMaxLocationKernel::minmax_loc<T, bool(N & 8), bool(N & 4), bool(N & 2), bool(N & 1)>... }; @@ -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<uint8_t, gen_index_seq<16>::type>::func_table[table_idx]; + _func = create_func_table<uint8_t, utility::index_sequence_t<16>>::func_table[table_idx]; break; case DataType::S16: - _func = create_func_table<int16_t, gen_index_seq<16>::type>::func_table[table_idx]; + _func = create_func_table<int16_t, utility::index_sequence_t<16>>::func_table[table_idx]; break; case DataType::F32: - _func = create_func_table<float, gen_index_seq<16>::type>::func_table[table_idx]; + _func = create_func_table<float, utility::index_sequence_t<16>>::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<CPPPermuteKernel>(); + 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<Tensor>(shape, data_type); + Tensor dst = create_tensor<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 <typename T> +using CPPPermuteFixture = PermuteValidationFixture<Tensor, Accessor, CPPPermute, T>; + +TEST_SUITE(U8) +FIXTURE_DATA_TEST_CASE(RunSmall, CPPPermuteFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U8))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture<uint8_t>, 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<uint16_t>, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U16))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture<uint16_t>, 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<uint32_t>, framework::DatasetMode::PRECOMMIT, combine(PermuteParametersSmall, framework::dataset::make("DataType", DataType::U32))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, CPPPermuteFixture<uint32_t>, 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 <typename TensorType, typename AccessorType, typename FunctionType, typename T> +class PermuteValidationFixture : public framework::Fixture +{ +public: + template <typename...> + 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 <typename U> + 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<TensorType>(shape, data_type); + TensorType dst = create_tensor<TensorType>(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<T> compute_reference(const TensorShape &shape, DataType data_type, PermutationVector perm) + { + // Create reference + SimpleTensor<T> src{ shape, data_type }; + + // Fill reference + fill(src); + + return reference::permute<T>(src, perm); + } + + TensorType _target{}; + SimpleTensor<T> _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 <typename T> +SimpleTensor<T> permute(const SimpleTensor<T> &src, PermutationVector perm) +{ + // Permute shapes + TensorShape dst_shape = src.shape(); + permute(dst_shape, perm); + + // Create reference + SimpleTensor<T> 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<uint8_t> permute(const SimpleTensor<uint8_t> &src, PermutationVector perm); +template SimpleTensor<uint16_t> permute(const SimpleTensor<uint16_t> &src, PermutationVector perm); +template SimpleTensor<uint32_t> permute(const SimpleTensor<uint32_t> &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 <typename T> +SimpleTensor<T> permute(const SimpleTensor<T> &src, PermutationVector perm); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_PERMUTE_H__ */ |