From 8c1f357193279b515b087d8740943ad942cfc9b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=A2=85=ED=98=84/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Senior=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Thu, 5 Apr 2018 10:53:39 +0900 Subject: [PATCH] Introduce 'nnfw::util::tensor' namespace (#440) This commit introduces 'nnfw::util::tensor' namespace which will include various helpers for tensor (ND-array) object. Currently, 'nnfw::util::tensor' namespace includes the following classes and funtiont: - class Index - class Shape - class IndexIterator - method iterate Signed-off-by: Jonghyun Park --- include/util/tensor/Index.h | 46 +++++++++++++++ include/util/tensor/IndexIterator.h | 88 +++++++++++++++++++++++++++++ include/util/tensor/Shape.h | 45 +++++++++++++++ src/util/CMakeLists.txt | 3 + src/util/examples/tensor_index_iterator.cpp | 22 ++++++++ 5 files changed, 204 insertions(+) create mode 100644 include/util/tensor/Index.h create mode 100644 include/util/tensor/IndexIterator.h create mode 100644 include/util/tensor/Shape.h create mode 100644 src/util/examples/tensor_index_iterator.cpp diff --git a/include/util/tensor/Index.h b/include/util/tensor/Index.h new file mode 100644 index 0000000..d620483 --- /dev/null +++ b/include/util/tensor/Index.h @@ -0,0 +1,46 @@ +#ifndef __NNFW_UTIL_TENSOR_INDEX_H__ +#define __NNFW_UTIL_TENSOR_INDEX_H__ + +#include +#include + +#include +#include + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +struct Index +{ +public: + Index(size_t rank) + { + _offsets.resize(rank); + } + +public: + Index(std::initializer_list offsets) : _offsets{offsets} + { + // DO NOTHING + } + +public: + size_t rank(void) const { return _offsets.size(); } + +public: + int32_t at(size_t n) const { return _offsets.at(n); } + int32_t &at(size_t n) { return _offsets.at(n); } + +private: + std::vector _offsets; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_H__ diff --git a/include/util/tensor/IndexIterator.h b/include/util/tensor/IndexIterator.h new file mode 100644 index 0000000..61c23cb --- /dev/null +++ b/include/util/tensor/IndexIterator.h @@ -0,0 +1,88 @@ +#ifndef __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ +#define __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ + +#include "util/tensor/Shape.h" +#include "util/tensor/Index.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class IndexIterator +{ +public: + IndexIterator(const Shape &shape) : _shape(shape) + { + // DO NOTHING + } + +public: + // Allow move, but disallow copy + IndexIterator(IndexIterator &&) = default; + IndexIterator(const IndexIterator &) = delete; + +public: + template IndexIterator &iter(Callable fn) + { + Index index(_shape.rank()); + + for (size_t d = 0; d < _shape.rank(); ++d) + { + index.at(d) = 0; + } + + size_t cursor = 0; + + while (cursor < _shape.rank()) + { + fn(index); + + if (index.at(cursor) + 1 < _shape.dim(cursor)) + { + index.at(cursor) += 1; + } + else + { + while ((cursor < _shape.rank()) && (index.at(cursor) + 1 == _shape.dim(cursor))) + { + ++cursor; + } + + if (cursor == _shape.rank()) + { + break; + } + + index.at(cursor) += 1; + + for (size_t d = 0; d < cursor; ++d) + { + index.at(d) = 0; + } + + cursor = 0; + } + } + + return (*this); + } + +private: + const Shape &_shape; +}; + +IndexIterator iterate(const Shape &shape) { return IndexIterator{shape}; } + +template IndexIterator &operator<<(IndexIterator &&it, Callable cb) +{ + return it.iter(cb); +} + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ diff --git a/include/util/tensor/Shape.h b/include/util/tensor/Shape.h new file mode 100644 index 0000000..3211952 --- /dev/null +++ b/include/util/tensor/Shape.h @@ -0,0 +1,45 @@ +#ifndef __NNFW_UTIL_TENSOR_SHAPE_H__ +#define __NNFW_UTIL_TENSOR_SHAPE_H__ + +#include +#include +#include +#include + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class Shape +{ +public: + Shape(size_t rank) + { + _dimensions.resize(rank); + } + +public: + Shape(const std::initializer_list &dimensions) : _dimensions{dimensions} + { + // DO NOTHING + } + +public: + size_t rank(void) const { return _dimensions.size(); } + +public: + int32_t dim(size_t n) const { return _dimensions.at(n); } + int32_t &dim(size_t n) { return _dimensions.at(n); } + +private: + std::vector _dimensions; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_SHAPE_H__ diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 2427766..3725781 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -9,3 +9,6 @@ target_include_directories(nnfw_util PUBLIC ${NNFW_INCLUDE_DIR}) install(TARGETS nnfw_util RUNTIME DESTINATION bin COMPONENT libraries LIBRARY DESTINATION lib COMPONENT libraries) + +add_executable(nnfw_util_tensor_index_iterator "examples/tensor_index_iterator.cpp") +target_link_libraries(nnfw_util_tensor_index_iterator nnfw_util) diff --git a/src/util/examples/tensor_index_iterator.cpp b/src/util/examples/tensor_index_iterator.cpp new file mode 100644 index 0000000..b5358e3 --- /dev/null +++ b/src/util/examples/tensor_index_iterator.cpp @@ -0,0 +1,22 @@ +#include "util/tensor/IndexIterator.h" + +#include + +int main(int argc, char **argv) +{ + nnfw::util::tensor::Shape shape{3, 4, 3, 4}; + + std::cout << "Iterate over tensor{3, 4, 3, 4}" << std::endl; + + nnfw::util::tensor::iterate(shape) << [] (const nnfw::util::tensor::Index &index) + { + std::cout << "rank: " << index.rank() << std::endl; + + for (size_t d = 0; d < index.rank(); ++d) + { + std::cout << " offset(" << d << ") = " << index.at(d) << std::endl; + } + }; + + return 0; +} -- 2.7.4