--- /dev/null
+#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__
--- /dev/null
+#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__
--- /dev/null
+#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__
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)
--- /dev/null
+#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;
+}