Tensor
A C++ expression template library for computations on N dimensional tensors
mapper.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------------------------------------
2 /// @file Header file for mapper related classes and variables for mapping linear indices to multiple
3 /// dimensions and from mapping multiple dimensions to a linear index etc for both static and dynamic
4 /// containers
5 // ----------------------------------------------------------------------------------------------------------
6 
7 /*
8  * ----------------------------------------------------------------------------------------------------------
9  * Header file for mapper class
10  * Copyright (C) 2015 Rob Clucas robclu1818@gmail.com
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published
14  * by the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  * ----------------------------------------------------------------------------------------------------------
26  */
27 
28 #ifndef FTL_MAPPER_HPP
29 #define FTL_MAPPER_HPP
30 
31 #include <nano/nano.hpp>
32 
33 #include <type_traits>
34 #include <utility>
35 #include <numeric>
36 
37 namespace ftl {
38 
39 namespace detail {
40 
41 // ----------------------------------------------------------------------------------------------------------
42 /// @struct MapToIndexStatic
43 /// @brief Takes a list of indices and a list of dimension sizes, and determines the offset of an
44 /// element given by the indices, in contiguous memory
45 /// @tparam DimSizes The sizes of each of the dimensions
46 /// @tparam Indices The value of the element in each of the indices
47 // ----------------------------------------------------------------------------------------------------------
48 template <typename DimSizes, typename... Indices>
50 
51 // Recursive case
52 template <typename DimSizes, typename IF, typename... IR>
53 struct MapToIndexStatic<DimSizes, IF, IR...>
54 {
55  // On each iteration the product of the size of all previous dimensions must be calculated
56  // to determine the memory offset of this dimension, so determine the stopping index
57  using end_index = typename std::conditional<
58  DimSizes::size - sizeof...(IR) == 1 ,
59  typename nano::size_t<0> ,
60  typename nano::size_t<DimSizes::size - sizeof...(IR) - 2>>::type;
61 
62  // The product sum of the previous dimensions (previous iterations) so if we are on iteration
63  // 3 then this is the product of the size of dimension 0 and 1
64  static constexpr size_t dim_product_sum = nano::accumulate<DimSizes, 0, end_index::value, 1>::result;
65 
66  // The offset calculation
67  static constexpr size_t offset(size_t current_offset, IF&& index_first, IR&&... indices_rest)
68  {
69  // Recursively call until the terminating case
70  // If first iteration use index_first as offset
71  // if other iteration, add mult with prev products
72  return DimSizes::size - sizeof...(IR) == 1
73  ? MapToIndexStatic<DimSizes, IR...>::offset(current_offset + index_first ,
74  std::forward<IR>(indices_rest)... )
75  : MapToIndexStatic<DimSizes, IR...>::offset(current_offset + index_first * dim_product_sum,
76  std::forward<IR>(indices_rest)... );
77  }
78 };
79 
80 // Terminating (base) case
81 template <typename DimSizes>
82 struct MapToIndexStatic<DimSizes>
83 {
84  // Just need to return the result here
85  static constexpr size_t offset(size_t current_offset) { return current_offset; }
86 };
87 
88 // Dynamic implementation
89 template <size_t Iteration, typename Container>
90 size_t MapToIndexDynamic(const Container& dim_sizes ,
91  size_t current_offset )
92 {
93  return current_offset;
94 }
95 
96 template <size_t Iteration, typename Container, typename IF, typename... IR>
97 size_t MapToIndexDynamic(const Container& dim_sizes ,
98  size_t current_offset ,
99  IF index_first ,
100  IR... indices_rest )
101 {
102  size_t num_indices = sizeof...(IR);
103  current_offset += std::accumulate(dim_sizes.begin() ,
104  dim_sizes.end() - num_indices - 1 ,
105  1 ,
106  std::multiplies<size_t>() ) * index_first;
107  // Keep iterating
108  return MapToIndexDynamic<Iteration + 1>(dim_sizes, current_offset, indices_rest...);
109 }
110 
111 } // End namespace detail
112 
113 // ----------------------------------------------------------------------------------------------------------
114 /// @struct StaticMapper
115 /// @brief Interface which provides static mapping (uses TMP to determine some of the mapping variables
116 /// at compile time for improved performance) from indices to a single offset index and from an
117 /// index offset to a list of indices
118 // ----------------------------------------------------------------------------------------------------------
119 struct StaticMapper {
120 
121 // ----------------------------------------------------------------------------------------------------------
122 /// @brief Maps any number of indices which represent the location of an index in a multi-dimensional
123 /// space, to a singe index offset in the contiguous memory which is representing that
124 /// multi-dimensional space
125 /// @param[in] index_first The index of the element in the first dimension
126 /// @param[in] indices_rest The indices of the element in the other dimensions
127 /// @tparam DimSizes The list of dimension sizes for the multi-dimensional space
128 /// @tparam IF The type of index_first
129 /// @tparam IR The types of indices_rest
130 // ----------------------------------------------------------------------------------------------------------
131 template <typename DimSizes, typename IF, typename... IR>
132 static constexpr size_t indices_to_index(IF&& index_first, IR&&... indices_rest)
133 {
135  std::forward<IF>(index_first) ,
136  std::forward<IR>(indices_rest)... );
137 }
138 
139 };
140 
142 
143 template <typename Container, typename IF, typename... IR>
144 static size_t indices_to_index(const Container& dim_sizes ,
145  IF index_first ,
146  IR... indices_rest)
147 {
148  return detail::MapToIndexDynamic<1>(dim_sizes, index_first, indices_rest...);
149 }
150 
151 };
152 
153 } // End namespace ftl
154 #endif // FTL_MAPPER_HPP
Interface which provides static mapping (uses TMP to determine some of the mapping variables at compi...
Definition: mapper.hpp:119
size_t MapToIndexDynamic(const Container &dim_sizes, size_t current_offset)
Definition: mapper.hpp:90
static constexpr size_t offset(size_t current_offset)
Definition: mapper.hpp:85
Definition: mapper.hpp:37
Definition: mapper.hpp:141
static size_t indices_to_index(const Container &dim_sizes, IF index_first, IR...indices_rest)
Definition: mapper.hpp:144
static constexpr size_t offset(size_t current_offset, IF &&index_first, IR &&...indices_rest)
Definition: mapper.hpp:67
Takes a list of indices and a list of dimension sizes, and determines the offset of an element given ...
Definition: mapper.hpp:49
static constexpr size_t indices_to_index(IF &&index_first, IR &&...indices_rest)
Maps any number of indices which represent the location of an index in a multi-dimensional space...
Definition: mapper.hpp:132
typename std::conditional< DimSizes::size-sizeof...(IR)==1, typename nano::size_t< 0 >, typename nano::size_t< DimSizes::size-sizeof...(IR)-2 >>::type end_index
Definition: mapper.hpp:60