diff options
author | Chunseok Lee <chunseok.lee@samsung.com> | 2021-10-19 11:32:46 +0900 |
---|---|---|
committer | Chunseok Lee <chunseok.lee@samsung.com> | 2021-10-19 11:32:46 +0900 |
commit | 33ae5d70a1ed85d215c1293ed63afbf3517b07d5 (patch) | |
tree | 9f1ace0f4760a8f7903ef15e2e92f1d1401e4b1e /runtime/libs/ndarray | |
parent | f4cf19e579a19c5346ccb2aad55bfd251065e447 (diff) | |
download | nnfw-33ae5d70a1ed85d215c1293ed63afbf3517b07d5.tar.gz nnfw-33ae5d70a1ed85d215c1293ed63afbf3517b07d5.tar.bz2 nnfw-33ae5d70a1ed85d215c1293ed63afbf3517b07d5.zip |
Imported Upstream version 1.18.0upstream/1.18.0submit/tizen/20211028.014856submit/tizen/20211019.023737accepted/tizen/unified/20211101.140244
Diffstat (limited to 'runtime/libs/ndarray')
-rw-r--r-- | runtime/libs/ndarray/CMakeLists.txt | 23 | ||||
-rw-r--r-- | runtime/libs/ndarray/example/CMakeLists.txt | 4 | ||||
-rw-r--r-- | runtime/libs/ndarray/example/example_array.cpp | 76 | ||||
-rw-r--r-- | runtime/libs/ndarray/example/example_no_array.cpp | 85 | ||||
-rw-r--r-- | runtime/libs/ndarray/include/ndarray/Array.h | 195 | ||||
-rw-r--r-- | runtime/libs/ndarray/include/ndarray/Common.h | 22 | ||||
-rw-r--r-- | runtime/libs/ndarray/include/ndarray/ContiguousSpan.h | 108 | ||||
-rw-r--r-- | runtime/libs/ndarray/include/ndarray/Shape.h | 66 | ||||
-rw-r--r-- | runtime/libs/ndarray/src/Array.cpp | 27 | ||||
-rw-r--r-- | runtime/libs/ndarray/src/ContiguousSpan.cpp | 31 | ||||
-rw-r--r-- | runtime/libs/ndarray/src/detail/cxx14.h | 67 | ||||
-rw-r--r-- | runtime/libs/ndarray/test/CMakeLists.txt | 18 | ||||
-rw-r--r-- | runtime/libs/ndarray/test/ndarray_test.cpp | 122 |
13 files changed, 844 insertions, 0 deletions
diff --git a/runtime/libs/ndarray/CMakeLists.txt b/runtime/libs/ndarray/CMakeLists.txt new file mode 100644 index 000000000..f88f13186 --- /dev/null +++ b/runtime/libs/ndarray/CMakeLists.txt @@ -0,0 +1,23 @@ +add_library(ndarray STATIC src/Array.cpp src/ContiguousSpan.cpp) + +set_target_properties(ndarray PROPERTIES POSITION_INDEPENDENT_CODE ON) + +target_include_directories(ndarray PUBLIC include) +#can't make this private because of c++ templates +target_include_directories(ndarray PUBLIC src) + +option(NDARRAY_INLINE_TEMPLATES "Set to ON to disable extern declarations for common types") + +if(${NDARRAY_INLINE_TEMPLATES}) + target_compile_definitions(ndarray PUBLIC -DNDARRAY_INLINE_TEMPLATES=1) +endif() + +target_link_libraries(ndarray PRIVATE nnfw_common) +target_link_libraries(ndarray PRIVATE nnfw_coverage) + +if(NOT ENABLE_TEST) + return() +endif(NOT ENABLE_TEST) + +add_subdirectory(test) +add_subdirectory(example) diff --git a/runtime/libs/ndarray/example/CMakeLists.txt b/runtime/libs/ndarray/example/CMakeLists.txt new file mode 100644 index 000000000..c4b575dad --- /dev/null +++ b/runtime/libs/ndarray/example/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(example_no_array example_no_array.cpp) + +add_executable(example_array example_array.cpp) +target_link_libraries(example_array PRIVATE ndarray) diff --git a/runtime/libs/ndarray/example/example_array.cpp b/runtime/libs/ndarray/example/example_array.cpp new file mode 100644 index 000000000..85d274681 --- /dev/null +++ b/runtime/libs/ndarray/example/example_array.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ndarray/Array.h" + +#include <iostream> +#include <iterator> + +using namespace ndarray; + +void gather_array(const Array<float> &input, Array<float> &output, const Array<int> &indices) +{ + assert(indices.shape().rank() == 3); + assert(input.shape().rank() == 3); + assert(indices.shape().dim(1) == input.shape().rank()); + + for (size_t i = 0; i < indices.shape().dim(0); ++i) + { + for (size_t j = 0; j < indices.shape().dim(1); ++j) + { + auto index = indices.slice(i, j); + output.slice(i, j).assign(input.slice(index[0], index[1])); + } + } +} + +int main() +{ + // fill tensor of shape[3,3,4] with sequential numbers from [0..36) + Shape in_shape{3, 3, 4}; + std::vector<float> input_data(in_shape.element_count()); + for (size_t i = 0; i < in_shape.element_count(); ++i) + input_data[i] = i; + + Array<float> input(input_data.data(), in_shape); + + // select column-vectors on main diagonal + Shape indices_shape{1, 3, 2}; + std::vector<int> indices_data(indices_shape.element_count()); + Array<int> indices(indices_data.data(), indices_shape); + + indices.slice(0, 0) = {0, 0}; + indices.slice(0, 1) = {1, 1}; + indices.slice(0, 2) = {2, 2}; + + Shape output_shape{1, 3, 4}; + std::vector<float> output_data(output_shape.element_count()); + + Array<float> output(output_data.data(), output_shape); + + gather_array(input, output, indices); + + for (size_t i = 0; i < indices_shape.dim(0); ++i) + { + for (size_t j = 0; j < indices_shape.dim(1); ++j) + { + auto output_piece = output.slice(i, j); + std::ostream_iterator<int> cout_it(std::cout, ", "); + std::copy(output_piece.begin(), output_piece.end(), cout_it); + std::cout << std::endl; + } + } +} diff --git a/runtime/libs/ndarray/example/example_no_array.cpp b/runtime/libs/ndarray/example/example_no_array.cpp new file mode 100644 index 000000000..3a4d05dca --- /dev/null +++ b/runtime/libs/ndarray/example/example_no_array.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <array> +#include <vector> +#include <algorithm> +#include <cassert> +#include <iostream> + +void gather_no_array(const float *in_data, const std::array<size_t, 3> &dims, float *out_data, + const std::array<size_t, 3> &out_dims, //[nselections, + const int *indices, const std::array<size_t, 3> &indices_dims) +{ + assert(indices_dims[1] == dims.size()); + + for (int i = 0; i < indices_dims[0]; ++i) + { + for (int j = 0; j < indices_dims[1]; ++j) + { + const int *index_ptr = indices + i * indices_dims[2] * indices_dims[1] + j * indices_dims[2]; + + size_t in_offset = index_ptr[0] * dims[2] * dims[1] + index_ptr[1] * dims[2]; + + const float *in_ptr = in_data + in_offset; + + size_t out_offset = i * out_dims[2] * out_dims[1] + j * out_dims[2]; + + float *out_ptr = out_data + out_offset; + + for (int k = 0; k < dims[2]; ++k) + { + out_ptr[k] = in_ptr[k]; + } + } + } +} + +int main() +{ + std::array<size_t, 3> in_dims{3, 3, 4}; + std::vector<float> input(3 * 3 * 4); + for (size_t i = 0; i < 3 * 3 * 4; ++i) + input[i] = i; + + std::array<size_t, 3> indices_shape{1, 3, 2}; + std::vector<int> indices(1 * 3 * 2); + + indices[0] = 0; + indices[1] = 0; + indices[2] = 1; + indices[3] = 1; + indices[4] = 2; + indices[5] = 2; + + std::array<size_t, 3> output_dims{1, 3, 4}; + std::vector<float> output(1 * 3 * 4); + + gather_no_array(input.data(), in_dims, output.data(), output_dims, indices.data(), indices_shape); + + for (size_t i = 0; i < output_dims[0]; ++i) + { + for (size_t j = 0; j < output_dims[1]; ++j) + { + auto out_ptr = output.data() + i * output_dims[1] * output_dims[2] + j * output_dims[2]; + for (size_t k = 0; k < output_dims[2]; ++k) + { + std::cout << out_ptr[k] << ", "; + } + std::cout << std::endl; + } + } +} diff --git a/runtime/libs/ndarray/include/ndarray/Array.h b/runtime/libs/ndarray/include/ndarray/Array.h new file mode 100644 index 000000000..09e791763 --- /dev/null +++ b/runtime/libs/ndarray/include/ndarray/Array.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDARRAY_ARRAY_H_ +#define _NDARRAY_ARRAY_H_ + +#include "Common.h" + +#include "ContiguousSpan.h" +#include "Shape.h" + +#if __cplusplus < 201402L +#include "detail/cxx14.h" //integer_sequence and make_index_dequence definitions +#else +#include <utility> +#endif + +#include <algorithm> +#include <cassert> +#include <type_traits> +#include <array> +#include <tuple> +#include <cstddef> + +namespace ndarray +{ + +// there is no index_sequence before c++14 +#if __cplusplus < 201402L + +template <size_t... Nums> using index_sequence = cxx14::index_sequence<Nums...>; + +template <size_t Num> using make_index_sequence = cxx14::make_index_sequence<Num>; + +#else + +template <size_t... Nums> using index_sequence = std::index_sequence<Nums...>; + +template <size_t _Num> using make_index_sequence = std::make_index_sequence<_Num>; + +#endif //__cplusplus < 201402L + +struct Strides +{ + explicit Strides(Shape s) : _strides{} { fillStrides(s); } + + int operator[](size_t idx) const noexcept { return _strides[idx]; } + + // since we don't have c++14 fold expression + template <typename Seq, typename... Ts> struct _calc_offset; + + template <size_t Num, size_t... Nums, typename T, typename... Ts> + struct _calc_offset<index_sequence<Num, Nums...>, T, Ts...> + { + static constexpr size_t get(const std::array<int, 8> &strides, int x, Ts... xs) + { + return _calc_offset<index_sequence<Nums...>, Ts...>::get(strides, xs...) + + x * std::get<Num>(strides); + } + }; + + template <size_t Num, typename T> struct _calc_offset<index_sequence<Num>, T> + { + static constexpr size_t get(const std::array<int, 8> &strides, int x) + { + return x * std::get<Num>(strides); + } + }; + + template <typename Seq, typename... Ts> constexpr size_t offset(Seq, Ts... x) const noexcept + { + // return ( 0 + ... + (std::get<Nums>(_strides) * x)); in c++14 + return _calc_offset<Seq, Ts...>::get(_strides, x...); + } + +private: + void fillStrides(const Shape &s) noexcept + { + int rank = s.rank(); + _strides[rank - 1] = 1; + for (int d = rank - 2; d >= 0; --d) + { + _strides[d] = _strides[d + 1] * s.dim(d + 1); + } + } + + std::array<int, NDARRAY_MAX_DIMENSION_COUNT> _strides; +}; + +template <typename T> class Array +{ +public: + Array(T *data, Shape shape) noexcept : _data(data), _shape(shape), _strides(shape) {} + + Array(const Array &) = delete; + + Array(Array &&a) noexcept : _data(a._data), _shape(a._shape), _strides(a._strides) + { + a._data = nullptr; + } + + template <typename... Ts> T &at(Ts... x) const noexcept { return _at(static_cast<size_t>(x)...); } + + /** + * @brief returns last dimension as ContigniousSpan + * @param x indices of slice to take. See tests for usage details + * @return slice at given position + */ + template <typename... Ts> ContiguousSpan<T, std::is_const<T>::value> slice(Ts... x) noexcept + { + assert(sizeof...(Ts) == _shape.rank() - 1); + return {&at(x..., 0ul), _shape.dim(_shape.rank() - 1)}; + } + + /** + * @brief returns last dimension as ContigniousSpan + * @param x indices of slice to take. See tests for usage details + * @return slice at given position + */ + template <typename... Ts> ContiguousSpan<T, true> slice(Ts... x) const noexcept + { + assert(sizeof...(Ts) == _shape.rank() - 1); + return {&at(x..., 0ul), _shape.dim(_shape.rank() - 1)}; + } + + ContiguousSpan<T, std::is_const<T>::value> flat() noexcept + { + return {_data, _shape.element_count()}; + } + + ContiguousSpan<T, true> flat() const noexcept { return {_data, _shape.element_count()}; } + + const Shape &shape() const noexcept { return _shape; } + +private: + template <typename... Ts> T &_at(Ts... x) const noexcept + { + assert(sizeof...(x) == _shape.rank()); + using Indices = make_index_sequence<sizeof...(Ts)>; + return _data[offset(Indices{}, x...)]; + } + + template <typename... Ts, size_t... Nums> + size_t offset(index_sequence<Nums...> seq, Ts... x) const noexcept + { + static_assert( + sizeof...(Ts) == sizeof...(Nums), + "Sanity check failed. Generated index sequence size is not equal to argument count"); + + return _strides.offset(seq, x...); + } + + T *_data; + Shape _shape; + Strides _strides; +}; + +template <typename To, typename From> Array<To> array_cast(Array<From> &&from, Shape newShape) +{ + assert(from.shape().element_count() / (sizeof(To) / sizeof(From)) == newShape.element_count()); + return Array<To>(reinterpret_cast<To *>(from.flat().data()), newShape); +} + +template <typename To, typename From> +Array<const To> array_cast(const Array<From> &from, Shape newShape) +{ + assert(from.shape().element_count() / (sizeof(To) / sizeof(From)) == newShape.element_count()); + return Array<To>(reinterpret_cast<const To *>(from.flat().data()), newShape); +} + +#ifndef NDARRAY_INLINE_TEMPLATES + +extern template class Array<float>; +extern template class Array<int32_t>; +extern template class Array<uint32_t>; +extern template class Array<uint8_t>; + +#endif // NDARRAY_INLINE_TEMPLATES + +} // namespace ndarray + +#endif //_NDARRAY_ARRAY_H_ diff --git a/runtime/libs/ndarray/include/ndarray/Common.h b/runtime/libs/ndarray/include/ndarray/Common.h new file mode 100644 index 000000000..aa0cc6fe2 --- /dev/null +++ b/runtime/libs/ndarray/include/ndarray/Common.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDARRAY_COMMON_H_ +#define _NDARRAY_COMMON_H_ + +#define NDARRAY_MAX_DIMENSION_COUNT 8 + +#endif //_NDARRAY_COMMON_H_ diff --git a/runtime/libs/ndarray/include/ndarray/ContiguousSpan.h b/runtime/libs/ndarray/include/ndarray/ContiguousSpan.h new file mode 100644 index 000000000..b322b77db --- /dev/null +++ b/runtime/libs/ndarray/include/ndarray/ContiguousSpan.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDARRAY_CONTIGNIOUS_SPAN_H_ +#define _NDARRAY_CONTIGNIOUS_SPAN_H_ + +#include <type_traits> +#include <vector> +#include <cstdint> +#include <cstddef> +#include <cassert> + +namespace ndarray +{ + +template <typename T, bool isConst = false> class ContiguousSpan +{ +public: + using pointer_type = typename std::conditional<isConst, const T *, T *>::type; + using reference_type = typename std::conditional<isConst, const T &, T &>::type; + using iterator_type = pointer_type; + + ContiguousSpan(pointer_type data, size_t len) noexcept : _data(data), _len(len) {} + + template <typename It> + explicit ContiguousSpan(It first, It last) noexcept + : _data(&*first), _len(std::distance(first, last)) + { + } + + ContiguousSpan(const ContiguousSpan &) = delete; + + ContiguousSpan(ContiguousSpan &&s) noexcept : _data(s._data), _len(s._len) { s._data = nullptr; } + + operator ContiguousSpan<T, true>() { return ContiguousSpan<T, true>{_data, _len}; } + + reference_type operator[](size_t idx) const noexcept { return _data[idx]; } + + reference_type at(size_t idx) const noexcept { return _data[idx]; } + + ContiguousSpan<T, isConst> offset(size_t offset) + { + assert(offset <= _len); + return {_data + offset, _len - offset}; + } + + template <typename From, bool _ = isConst> + typename std::enable_if<!_, void>::type assign(const From &f) noexcept + { + assignFrom(std::begin(f), std::end(f)); + } + + template <typename U, bool _ = isConst> + typename std::enable_if<!_, ContiguousSpan &>::type + operator=(std::initializer_list<U> list) noexcept + { + assignFrom(std::begin(list), std::end(list)); + return *this; + } + + template <typename It, bool _ = isConst> + typename std::enable_if<!_, void>::type assignFrom(It first, It last) noexcept + { + std::copy(first, last, begin()); + } + + size_t size() const { return _len; } + + iterator_type begin() const { return iterator_type{_data}; } + + iterator_type end() const { return iterator_type{_data + _len}; } + + pointer_type data() { return _data; } + +private: + pointer_type _data; + size_t _len; +}; + +#ifndef NDARRAY_INLINE_TEMPLATES + +extern template class ContiguousSpan<float, true>; +extern template class ContiguousSpan<float, false>; +extern template class ContiguousSpan<int32_t, true>; +extern template class ContiguousSpan<int32_t, false>; +extern template class ContiguousSpan<uint32_t, true>; +extern template class ContiguousSpan<uint32_t, false>; +extern template class ContiguousSpan<uint8_t, true>; +extern template class ContiguousSpan<uint8_t, false>; + +#endif // NDARRAY_INLINE_TEMPLATES + +} // namespace ndarray + +#endif //_NDARRAY_CONTIGNIOUS_SPAN_H_ diff --git a/runtime/libs/ndarray/include/ndarray/Shape.h b/runtime/libs/ndarray/include/ndarray/Shape.h new file mode 100644 index 000000000..fa58613b8 --- /dev/null +++ b/runtime/libs/ndarray/include/ndarray/Shape.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDARRAY_SHAPE_H_ +#define _NDARRAY_SHAPE_H_ + +#include "Common.h" + +#include <array> +#include <cassert> +#include <cstddef> + +namespace ndarray +{ + +class Shape +{ +public: + //_dims{} here and later since array does not have std::initializer_list ctor + // and aggregate initialization is not allowed here + explicit Shape(size_t rank) noexcept : _dims{}, _rank(rank) + { + std::fill(_dims.begin(), _dims.end(), 0); + } + + Shape(std::initializer_list<size_t> list) noexcept : _dims{}, _rank(list.size()) + { + std::copy(list.begin(), list.end(), _dims.begin()); + } + + size_t dim(int i) const noexcept { return _dims.at(i); } + + size_t &dim(int i) noexcept { return _dims.at(i); } + + size_t element_count() const noexcept + { + uint32_t res = 1; + for (size_t i = 0; i < rank(); ++i) + res *= dim(i); + assert(res <= 0xffffffff); + return res; + } + + size_t rank() const noexcept { return _rank; } + +private: + std::array<size_t, NDARRAY_MAX_DIMENSION_COUNT> _dims; + size_t _rank; +}; + +} // namespace ndarray + +#endif //_NDARRAY_SHAPE_H_ diff --git a/runtime/libs/ndarray/src/Array.cpp b/runtime/libs/ndarray/src/Array.cpp new file mode 100644 index 000000000..f9c9de9d3 --- /dev/null +++ b/runtime/libs/ndarray/src/Array.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ndarray/Array.h" + +namespace ndarray +{ + +template class Array<float>; +template class Array<int32_t>; +template class Array<uint32_t>; +template class Array<uint8_t>; + +} // namespace ndarray diff --git a/runtime/libs/ndarray/src/ContiguousSpan.cpp b/runtime/libs/ndarray/src/ContiguousSpan.cpp new file mode 100644 index 000000000..e06cfc2a1 --- /dev/null +++ b/runtime/libs/ndarray/src/ContiguousSpan.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ndarray/ContiguousSpan.h" + +namespace ndarray +{ + +template class ContiguousSpan<float, true>; +template class ContiguousSpan<float, false>; +template class ContiguousSpan<int32_t, true>; +template class ContiguousSpan<int32_t, false>; +template class ContiguousSpan<uint32_t, true>; +template class ContiguousSpan<uint32_t, false>; +template class ContiguousSpan<uint8_t, true>; +template class ContiguousSpan<uint8_t, false>; + +} // namespace ndarray diff --git a/runtime/libs/ndarray/src/detail/cxx14.h b/runtime/libs/ndarray/src/detail/cxx14.h new file mode 100644 index 000000000..8b78fb985 --- /dev/null +++ b/runtime/libs/ndarray/src/detail/cxx14.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDARRAY_CXX14_H_ +#define _NDARRAY_CXX14_H_ + +namespace ndarray +{ + +namespace cxx14 +{ + +template <size_t... Nums> struct index_sequence +{ + using value_type = size_t; + + static constexpr std::size_t size() noexcept { return sizeof...(Nums); } +}; + +namespace detail +{ + +template <size_t v, typename Seq> struct _append; + +template <size_t v, size_t... Nums> struct _append<v, index_sequence<Nums...>> +{ + using result = index_sequence<Nums..., v>; +}; + +template <size_t Len> struct make_index_sequence +{ + using result = + typename detail::_append<Len - 1, typename make_index_sequence<Len - 1>::result>::result; +}; + +template <> struct make_index_sequence<1> +{ + using result = index_sequence<0>; +}; + +template <> struct make_index_sequence<0> +{ + using result = index_sequence<>; +}; + +} // namespace detail + +template <size_t Num> using make_index_sequence = typename detail::make_index_sequence<Num>::result; + +} // namespace cxx14 + +} // namespace ndarray + +#endif //_NDARRAY_CXX14_H_ diff --git a/runtime/libs/ndarray/test/CMakeLists.txt b/runtime/libs/ndarray/test/CMakeLists.txt new file mode 100644 index 000000000..be1ed6510 --- /dev/null +++ b/runtime/libs/ndarray/test/CMakeLists.txt @@ -0,0 +1,18 @@ +if(NOT TARGET ndarray) + return() +endif() + +add_executable(ndarray_test ndarray_test.cpp) + +target_link_libraries(ndarray_test PRIVATE ndarray) + +nnfw_find_package(GTest) +if(NOT GTest_FOUND) + message(STATUS "GTest not avaialble. Skipping NDArray test build") + return() +endif(NOT GTest_FOUND) + +target_link_libraries(ndarray_test PUBLIC gtest gtest_main ${LIB_PTHREAD}) + +add_test(ndarray_test ndarray_test) +install(TARGETS ndarray_test DESTINATION unittest_standalone) diff --git a/runtime/libs/ndarray/test/ndarray_test.cpp b/runtime/libs/ndarray/test/ndarray_test.cpp new file mode 100644 index 000000000..4b5ad5765 --- /dev/null +++ b/runtime/libs/ndarray/test/ndarray_test.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" + +#include "ndarray/Array.h" + +using namespace ndarray; + +TEST(NDArray_tests, basic_data_test) +{ + + float raw_data[] = {1, 2, 3, 4}; + + Array<float> data22{raw_data, {2, 2}}; + + ASSERT_FLOAT_EQ(data22.at(0, 0), 1); + ASSERT_FLOAT_EQ(data22.at(0, 1), 2); + ASSERT_FLOAT_EQ(data22.at(1, 0), 3); + ASSERT_FLOAT_EQ(data22.at(1, 1), 4); + ASSERT_EQ(data22.shape().rank(), 2); + ASSERT_EQ(data22.shape().dim(0), 2); + ASSERT_EQ(data22.shape().dim(1), 2); + + Array<float> data14{raw_data, {1, 4}}; + ASSERT_FLOAT_EQ(data14.at(0, 0), 1); + ASSERT_FLOAT_EQ(data14.at(0, 1), 2); + ASSERT_FLOAT_EQ(data14.at(0, 2), 3); + ASSERT_FLOAT_EQ(data14.at(0, 3), 4); + ASSERT_EQ(data14.shape().rank(), 2); + ASSERT_EQ(data14.shape().dim(0), 1); + ASSERT_EQ(data14.shape().dim(1), 4); + + ContiguousSpan<float> cs = data22.flat(); + ASSERT_EQ(cs.size(), 4); + ASSERT_FLOAT_EQ(cs.at(3), 4); + + Array<float> lv = std::move(data14); + ASSERT_FLOAT_EQ(lv.at(0, 0), 1); + ASSERT_FLOAT_EQ(lv.at(0, 1), 2); + ASSERT_FLOAT_EQ(lv.at(0, 2), 3); + ASSERT_FLOAT_EQ(lv.at(0, 3), 4); +} + +TEST(NDArray_tests, slice_write_test) +{ + float raw_data[4] = {0}; + + Array<float> data22{raw_data, {2, 2}}; + + data22.slice(1) = {1, 2}; + + ASSERT_FLOAT_EQ(data22.at(0, 0), 0); + ASSERT_FLOAT_EQ(data22.at(0, 1), 0); + ASSERT_FLOAT_EQ(data22.at(1, 0), 1); + ASSERT_FLOAT_EQ(data22.at(1, 1), 2); +} + +TEST(NDArray_tests, slice_read_test) +{ + float raw_data[4] = {1, 2, 3, 4}; + + Array<float> data22{raw_data, {2, 2}}; + + auto slice = data22.slice(1); + + ASSERT_FLOAT_EQ(slice[0], 3); + ASSERT_FLOAT_EQ(slice[1], 4); +} + +TEST(NDArray_tests, multidim_test) +{ + float raw_data[5] = {0, 1, 2, 3, 4}; + + Array<float> data22{raw_data, {1, 1, 1, 1, 5}}; + + ASSERT_FLOAT_EQ(data22.at(0, 0, 0, 0, 0), 0); + ASSERT_FLOAT_EQ(data22.at(0, 0, 0, 0, 1), 1); + ASSERT_FLOAT_EQ(data22.at(0, 0, 0, 0, 2), 2); + ASSERT_FLOAT_EQ(data22.at(0, 0, 0, 0, 3), 3); + ASSERT_FLOAT_EQ(data22.at(0, 0, 0, 0, 4), 4); +} + +TEST(NDArray_tests, slice_assign_test) +{ + std::vector<float> v1{1, 2, 3, 4, 5}; + std::vector<float> v2(5); + + ContiguousSpan<float> span1(v1.begin(), v1.end()); + ContiguousSpan<float> span2(v2.begin(), v2.end()); + + span2.assign(span1); + + ASSERT_EQ(v1, v2); + ASSERT_EQ(span1.size(), 5); + ASSERT_EQ(span2.size(), 5); + + ASSERT_EQ(span2.at(2), 3); + ASSERT_EQ(span2.at(4), 5); + + ASSERT_EQ(*(span1.data() + 2), *(span1.data() + 2)); + + ContiguousSpan<float> span3(span2.offset(1)); + ASSERT_EQ(span3.size(), 4); + ASSERT_EQ(span3.at(0), 2); + ASSERT_EQ(span3.at(1), 3); + ASSERT_EQ(span3.at(2), 4); + ASSERT_EQ(span3.at(3), 5); +} |