Tensor
A C++ expression template library for computations on N dimensional tensors
tensor_dynamic_cpu.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------------------------------------
2 /// @file Header file for tensor specialization with a dynamic container using the cpu.
3 // ----------------------------------------------------------------------------------------------------------
4 
5 /*
6  * ----------------------------------------------------------------------------------------------------------
7  * Tensor is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Tensor is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with Tensor; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  * ----------------------------------------------------------------------------------------------------------
21  */
22 
23 #ifndef FTL_TENSOR_DYNAMIC_CPU_HPP
24 #define FTL_TENSOR_DYNAMIC_CPU_HPP
25 
26 #include "mapper.hpp"
27 #include "tensor_expression_dynamic_cpu.hpp" // NOTE: Only including expression specialization for
28  // dynamic cpu implementation -- all specializations
29  // are provided by tensor_expressions.hpp
30 
31 #include <initializer_list>
32 #include <numeric>
33 
34 // NOTE : Using long template names results in extremely bulky code, so the following abbreviations are
35 // used to reduve the bulk for template parameters:
36 // - DT = Dtype = data type
37 // - SF = SizeFirst = size of first dimension
38 // - SR = SizeRest = size of other dimensions
39 // - CPU = CPU = CPU device used for computation
40 namespace ftl {
41 
42 // Forward declaration of TensorInterface so that we can provide the specialization
43 template <typename Traits>
45 
46 // Type alias for dynamic cpu tensor to make the code more readable
47 template <typename DT>
49 
50 // Specialization for a tensor using a dynamic container and CPU devices
51 template <typename DT>
52 class TensorInterface<TensorTraits<DT, CPU>> : public TensorExpression<DynamicTensorCpu<DT> ,
53  TensorTraits<DT, CPU>> {
54 public:
55  // ---------------------------------------- ALIAS'S -----------------------------------------------------
57  using container_type = typename traits::container_type;
58  using data_container = typename traits::data_container;
59  using dim_container = typename traits::dim_container;
60  using data_type = typename traits::data_type;
61  using size_type = typename traits::size_type;
62  // ------------------------------------------------------------------------------------------------------
63 
64  // ------------------------------------------------------------------------------------------------------
65  /// @brief Default constructor - sets the data to have no elements, the rank to the specified rank
66  // ------------------------------------------------------------------------------------------------------
67  explicit TensorInterface(size_type rank) : _data(0), _rank(rank), _dim_sizes(rank) {}
68 
69  // ------------------------------------------------------------------------------------------------------
70  /// @brief Constructor using vectors to set the dimension sizes and the data of the tensor. Moves the
71  /// data if the data are passed as rvalue references.
72  /// @param dim_sizes The sizes of each of the dimensions for the tensor.
73  /// @param data The data for the tensor.
74  // ------------------------------------------------------------------------------------------------------
75  TensorInterface(dim_container& dim_sizes, data_container& data);
76 
77  // ------------------------------------------------------------------------------------------------------
78  /// @brief Constructor using vectors to set the dimension sizes and the data of the tensor. Moves the
79  /// data if the data are passed as rvalue references.
80  /// @param dim_sizes The sizes of each of the dimensions for the tensor.
81  /// @param data The data for the tensor.
82  // ------------------------------------------------------------------------------------------------------
83  TensorInterface(dim_container&& dim_sizes, data_container&& data);
84 
85  // ------------------------------------------------------------------------------------------------------
86  /// @brief Constructor using an initializer list - sets the size of each of the dimensions to the
87  /// values in the intializer_list and the total number of elements equal to the product of
88  /// the dimension sizes.
89  /// @param[in] dim_sizes The list of dimension sizes where the nth element in the list sets the size
90  /// of the nth dimension of the tensor.
91  // ------------------------------------------------------------------------------------------------------
92  TensorInterface(std::initializer_list<size_type> dim_sizes);
93 
94  // ------------------------------------------------------------------------------------------------------
95  /// @brief Constructor for creation from a tensor expression -- this is only used for simple
96  /// expressions (which do not modify the rank and/or dimension sizes) -- such as addition
97  /// and subtraction. Rank modifying expressions-- such as multiplication and slicing -- have
98  /// specialized constructors (to be implemented).
99  /// @param[in] expression The expression instance to create the static tensor from
100  /// @tparam Expression The type of the expressionA
101  /// @tparam Traits The tensor traits of the expression
102  // ------------------------------------------------------------------------------------------------------
103  template <typename Expression, typename Traits>
105 
106  // ------------------------------------------------------------------------------------------------------
107  /// @brief Gets the rank (number of dimensions) of the tensor.
108  /// @return The rank (number of dimensions) of the tensor.
109  // ------------------------------------------------------------------------------------------------------
110  inline size_type rank() const { return _rank; }
111 
112  // ------------------------------------------------------------------------------------------------------
113  /// @brief Gets the size (total number of elements) of the tensor
114  /// @return The total number of elements in the tensor.
115  // ------------------------------------------------------------------------------------------------------
116  inline size_type size() const { return _data.size(); }
117 
118  // NOTE: need to add out of range exception here too
119  // ------------------------------------------------------------------------------------------------------
120  /// @brief Gets the size of a specific dimension of the tensor, if the requested dimension is
121  /// invalid then 0 is returned.
122  /// @param[in] dim The dimension for which the size must be returned.
123  /// @return The number of elements in the requested dimension, if the dimension is a valid dimension
124  /// for the tensor, otherwise 0 is returned.
125  // ------------------------------------------------------------------------------------------------------
126  inline size_t size(const int dim) const { return dim < _rank ? _dim_sizes[dim] : 0; }
127 
128  // ------------------------------------------------------------------------------------------------------
129  /// @brief Gets a vector holding the size of each dimension of the tensor.
130  /// @return A vector holding the size of each dimension of the tensor.
131  // ------------------------------------------------------------------------------------------------------
132  const dim_container& dim_sizes() const { return _dim_sizes; }
133 
134  // ------------------------------------------------------------------------------------------------------
135  /// @brief Gets the tensor data.
136  /// @return The data for the tensor.
137  // ------------------------------------------------------------------------------------------------------
138  const data_container& data() const { return _data; }
139 
140  // ------------------------------------------------------------------------------------------------------
141  /// @brief Initializes each element of the tensor between a range using a uniform ditribution
142  /// @param[in] min The minimum value of an element after the initialization
143  /// @param[in] max The max value of an element after the initialization
144  // ------------------------------------------------------------------------------------------------------
145  void initialize(const data_type min, const data_type max);
146 
147  // ------------------------------------------------------------------------------------------------------
148  /// @brief Gets the element at position i in the tensor's data vector, by refernce
149  /// @param[in] i The index of the element to access.
150  /// @return The element at position i in the tensor's data vecor.
151  // ------------------------------------------------------------------------------------------------------
152  inline data_type& operator[](size_type i) { return _data[i]; }
153 
154  // ------------------------------------------------------------------------------------------------------
155  /// @brief Gets the element at position i in the tensor's data vector, by value.
156  /// @param[in] i The index of the element to access.
157  /// @return The element at position i in the tensor's data vector.
158  // ------------------------------------------------------------------------------------------------------
159  inline const data_type& operator[](size_type i) const { return _data[i]; }
160 
161  // ------------------------------------------------------------------------------------------------------
162  /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
163  /// checking as bound checking implementations will be provided through .at()
164  /// @param[in] index_dim_one The index of the element in dimension 1
165  /// @param[in] index_dim_other The index of the element in the other dimensions
166  /// @tparam IF The type of the first index parameter
167  /// @tparam IR The types of the rest of the index parameters
168  /// @return A reference to the element at the position given by the indices
169  // ------------------------------------------------------------------------------------------------------
170  template <typename IF, typename... IR>
171  DT& operator()(IF index_dim_one, IR... index_dim_other);
172 
173  // ------------------------------------------------------------------------------------------------------
174  /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
175  /// checking as bound checking implementations will be provided through .at()
176  /// @param[in] index_dim_one The index of the element in dimension 1
177  /// @param[in] index_dim_other The index of the element in the other dimensions
178  /// @tparam IF The type of the first index parameter
179  /// @tparam IR The types of the rest of the index parameters
180  /// @return The value of the element at the position given by the indices
181  // ------------------------------------------------------------------------------------------------------
182  template <typename IF, typename... IR>
183  DT operator()(IF index_dim_one, IR... index_dim_other) const;
184 private:
185  data_container _data; //!< Data for the tensor
186  dim_container _dim_sizes; //!< Sizes of the dimensions for the tensor
187  size_type _rank; //!< The rank (number of dimensions) in the tensor
188 };
189 
190 // ------------------------------------------- IMPLEMENTATIONS ----------------------------------------------
191 
192 // ----------------------------------------------- PUBLIC ---------------------------------------------------
193 
194 template <typename DT>
195 TensorInterface<TensorTraits<DT, CPU>>::TensorInterface(std::initializer_list<size_type> dim_sizes)
196 : _data(std::accumulate(dim_sizes.begin(), dim_sizes.end(), 1, std::multiplies<size_type>())),
197  _rank(dim_sizes.size())
198 {
199  for (auto& element : dim_sizes) _dim_sizes.push_back(element);
200 }
201 
202 template <typename DT>
204 : _data(data), _rank(dim_sizes.size()), _dim_sizes(dim_sizes)
205 {
206  // TODO: Add exception checking that the number of elements in the data container is the same as the
207  // product of the sizes of the dimensions that were given
208 
209 }
210 
211 template <typename DT>
213 : _data(data), _rank(dim_sizes.size()), _dim_sizes(dim_sizes)
214 {
215  // TODO: Add exception checking that the number of elements in the data container is the same as the
216  // product of the sizes of the dimensions that were given
217 
218 }
219 
220 template <typename DT> template <typename E, typename T>
222 : _data(expression.size()), _dim_sizes(expression.dim_sizes()), _rank(expression.rank())
223 {
224  for (size_type i = 0; i != size(); ++i) _data[i] = expression[i];
225 }
226 
227 template <typename DT>
228 void TensorInterface<TensorTraits<DT, CPU>>::initialize(const data_type min, const data_type max)
229 {
230  std::random_device rand_device;
231  std::mt19937 gen(rand_device());
232  std::uniform_real_distribution<> dist(min, max);
233  for (auto& element : _data) element = static_cast<data_type>(dist(gen));
234 }
235 
236 template <typename DT> template <typename IF, typename... IR>
237 DT& TensorInterface<TensorTraits<DT, CPU>>::operator()(IF dim_one_index, IR... other_dim_indices)
238 {
239  return _data[DynamicMapper::indices_to_index(_dim_sizes, dim_one_index, other_dim_indices...)];
240 }
241 
242 template <typename DT> template <typename IF, typename... IR>
243 DT TensorInterface<TensorTraits<DT, CPU>>::operator()(IF dim_one_index, IR... other_dim_indices) const
244 {
245  return _data[DynamicMapper::indices_to_index(_dim_sizes, dim_one_index, other_dim_indices...)];
246 }
247 
248 } // End namespace ftl
249 #endif // FTL_TENSOR_DYNAMIC_CPU_HPP
size_type size() const
Gets the size (total number of elements) of the tensor.
Definition: tensor_dynamic_cpu.hpp:116
size_t size(const int dim) const
Gets the size of a specific dimension of the tensor, if the requested dimension is invalid then 0 is ...
Definition: tensor_dynamic_cpu.hpp:126
typename traits::data_type data_type
Definition: tensor_dynamic_cpu.hpp:60
typename traits::data_container data_container
Definition: tensor_dynamic_cpu.hpp:58
Definition: tensor_dynamic_cpu.hpp:44
const dim_container & dim_sizes() const
Gets a vector holding the size of each dimension of the tensor.
Definition: tensor_dynamic_cpu.hpp:132
typename traits::dim_container dim_container
Definition: tensor_dynamic_cpu.hpp:59
TensorInterface(size_type rank)
Default constructor - sets the data to have no elements, the rank to the specified rank...
Definition: tensor_dynamic_cpu.hpp:67
typename traits::container_type container_type
Definition: tensor_dynamic_cpu.hpp:57
Definition: mapper.hpp:37
static size_t indices_to_index(const Container &dim_sizes, IF index_first, IR...indices_rest)
Definition: mapper.hpp:144
Defines a general tensor expression so that opertions on tensor expressions can be defined the syntax...
Definition: tensor_expression_interface.hpp:49
typename traits::size_type size_type
Definition: tensor_dynamic_cpu.hpp:61
data_type & operator[](size_type i)
Gets the element at position i in the tensor's data vector, by refernce.
Definition: tensor_dynamic_cpu.hpp:152
const data_container & data() const
Gets the tensor data.
Definition: tensor_dynamic_cpu.hpp:138
size_type rank() const
Gets the rank (number of dimensions) of the tensor.
Definition: tensor_dynamic_cpu.hpp:110
const data_type & operator[](size_type i) const
Gets the element at position i in the tensor's data vector, by value.
Definition: tensor_dynamic_cpu.hpp:159
Traits class which specifies parameters for a tensor, such as what type of container it uses and what...
Definition: tensor_traits.hpp:48