Introduce 'nnfw::util::tensor' namespace (#440)
author박종현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh1302.park@samsung.com>
Thu, 5 Apr 2018 01:53:39 +0000 (10:53 +0900)
committer서상민/동작제어Lab(SR)/Senior Engineer/삼성전자 <sangmin7.seo@samsung.com>
Thu, 5 Apr 2018 01:53:39 +0000 (10:53 +0900)
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 <jh1302.park@samsung.com>
include/util/tensor/Index.h [new file with mode: 0644]
include/util/tensor/IndexIterator.h [new file with mode: 0644]
include/util/tensor/Shape.h [new file with mode: 0644]
src/util/CMakeLists.txt
src/util/examples/tensor_index_iterator.cpp [new file with mode: 0644]

diff --git a/include/util/tensor/Index.h b/include/util/tensor/Index.h
new file mode 100644 (file)
index 0000000..d620483
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __NNFW_UTIL_TENSOR_INDEX_H__
+#define __NNFW_UTIL_TENSOR_INDEX_H__
+
+#include <cstdint>
+#include <cstddef>
+
+#include <vector>
+#include <initializer_list>
+
+namespace nnfw
+{
+namespace util
+{
+namespace tensor
+{
+
+struct Index
+{
+public:
+  Index(size_t rank)
+  {
+    _offsets.resize(rank);
+  }
+
+public:
+  Index(std::initializer_list<int32_t> 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<int32_t> _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 (file)
index 0000000..61c23cb
--- /dev/null
@@ -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 <typename Callable> 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 <typename Callable> 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 (file)
index 0000000..3211952
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __NNFW_UTIL_TENSOR_SHAPE_H__
+#define __NNFW_UTIL_TENSOR_SHAPE_H__
+
+#include <cstdint>
+#include <cstddef>
+#include <vector>
+#include <initializer_list>
+
+namespace nnfw
+{
+namespace util
+{
+namespace tensor
+{
+
+class Shape
+{
+public:
+  Shape(size_t rank)
+  {
+    _dimensions.resize(rank);
+  }
+
+public:
+  Shape(const std::initializer_list<int32_t> &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<int32_t> _dimensions;
+};
+
+} // namespace tensor
+} // namespace util
+} // namespace nnfw
+
+#endif // __NNFW_UTIL_TENSOR_SHAPE_H__
index 2427766..3725781 100644 (file)
@@ -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 (file)
index 0000000..b5358e3
--- /dev/null
@@ -0,0 +1,22 @@
+#include "util/tensor/IndexIterator.h"
+
+#include <iostream>
+
+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;
+}