Tensor
A C++ expression template library for computations on N dimensional tensors
tensor_static_cpu.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------------------------------------
2 /// @file Header file for tensor specialization with a static 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_STATIC_CPU_HPP
24 #define FTL_TENSOR_STATIC_CPU_HPP
25 
26 #include <iostream>
27 #include "mapper.hpp"
28 #include "tensor_expression_static_cpu.hpp" // NOTE: Only including expression specialization for
29  // static cpu implementation -- all specializations
30  // are provided by tensor_expressions.hpp
31 
32 #include <type_traits>
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 namespace ftl {
40 
41 // Forward declaration of TensorInterface so that we can provide the specialization
42 template <typename Traits>
43 class TensorInterface;
44 
45 // Type alias for static cpu tensor to make the code more readable
46 template <typename DT, size_t SF, size_t... SR>
47 using StaticTensorCpu = TensorInterface<TensorTraits<DT, CPU, SF, SR...>>;
48 
49 // Specialization for a tensor using a static container and a CPU device
50 template <typename DT, size_t SF, size_t... SR>
51 class TensorInterface<TensorTraits<DT, CPU, SF, SR...>> : public TensorExpression<
52  StaticTensorCpu<DT, SF, SR...> ,
53  TensorTraits<DT, CPU, SF, SR...>> {
54 public:
55  // ---------------------------------------- ALIAS'S -----------------------------------------------------
56  using traits = TensorTraits<DT, CPU, SF, SR...>;
57  using size_type = typename traits::size_type;
58  using data_type = typename traits::data_type;
59  using container_type = typename traits::container_type;
60  using data_container = typename container_type::data_container;
61  using dim_container = typename container_type::dim_container;
62  // ------------------------------------------------------------------------------------------------------
63 
64  // ------------------------------------------------------------------------------------------------------
65  /// @brief Default constructor, converts the compile time list of dimension sizes to an array
66  // ------------------------------------------------------------------------------------------------------
68 
69  // ------------------------------------------------------------------------------------------------------
70  /// @brief Constructor for when the data is given as an lvalue
71  /// @param[in] data The data to use for the tensor
72  // ------------------------------------------------------------------------------------------------------
74 
75  // ------------------------------------------------------------------------------------------------------
76  /// @brief Constructor for when the data is specified as a literal list
77  /// @param[in] first_value The first value in the literal list -- must be data_type
78  /// @param[in] other_values The other values which make up the data
79  /// @tparam TR The type of the rest of the values
80  // ------------------------------------------------------------------------------------------------------
81  template <typename... TR>
82  TensorInterface(DT&& first_value, TR&&... other_values);
83 
84  // ------------------------------------------------------------------------------------------------------
85  /// @brief Constructor for creation from a tensor expression -- this is only used for simple
86  /// expressions (which do not modify the rank and/or dimension sizes) -- such as addition
87  /// and subtraction. Rank modifying expressions-- such as multiplication and slicing -- have
88  /// specialized constructors (to be implemented).
89  /// @param[in] expression The expression instance to create the static tensor from
90  /// @tparam Expression The type of the expression
91  // ------------------------------------------------------------------------------------------------------
92  template <typename Expression, typename Traits>
94 
95  // ------------------------------------------------------------------------------------------------------
96  /// @brief Gets the rank (number of dimensions) of the tensor
97  /// @return The rank (number of dimensions) of the tensor
98  // ------------------------------------------------------------------------------------------------------
99  constexpr size_type rank() const { return sizeof...(SR) + 1; }
100 
101  // ------------------------------------------------------------------------------------------------------
102  /// @brief Gets the size (total number of elements) in the tensor
103  /// @return The size of the tensor
104  // ------------------------------------------------------------------------------------------------------
105  constexpr size_type size() const { return _data.size(); }
106 
107  // TODO: Add out of range exception
108  // ------------------------------------------------------------------------------------------------------
109  /// @brief Gets the size (total number of elements) in a specific dimension of the tensor, if the
110  /// dimension is valid
111  /// @param[in] dim The dimension to get the size of
112  /// @return The size of the requested dimension of the tensor if valid, otherwise 0
113  // ------------------------------------------------------------------------------------------------------
114  inline size_type size(const size_type dim) const { return dim < rank() ? _dim_sizes[dim] : 0; }
115 
116  // ------------------------------------------------------------------------------------------------------
117  /// @brief Gets a reference to the container holding the sizes of the dimensions for the tensor
118  /// @return A constant reference to the dimension sizes of the tensor
119  // ------------------------------------------------------------------------------------------------------
120  constexpr const dim_container& dim_sizes() const { return _dim_sizes; }
121 
122  // ------------------------------------------------------------------------------------------------------
123  /// @brief Initializes each element of the tensor between a range using a uniform ditribution
124  /// @param[in] min The minimum value of an element after the initialization
125  /// @param[in] max The max value of an element after the initialization
126  // ------------------------------------------------------------------------------------------------------
127  void initialize(const data_type min, const data_type max);
128 
129  // ------------------------------------------------------------------------------------------------------
130  /// @brief Gets an element from the tensor
131  /// @param[in] i The index of the element in the tensor
132  /// @return A reference to the element at the index i in the tensor
133  // ------------------------------------------------------------------------------------------------------
134  inline data_type& operator[](size_type i) { return _data[i]; }
135 
136  // ------------------------------------------------------------------------------------------------------
137  /// @brief Gets an element from the tensor
138  /// @param[in] i The index of the element in the tensor
139  /// @return The value of the element at the index i in the tensor
140  // ------------------------------------------------------------------------------------------------------
141  inline const data_type& operator[](size_type i) const { return _data[i]; }
142 
143  // ------------------------------------------------------------------------------------------------------
144  /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
145  /// checking as bound checking implementations will be provided through .at()
146  /// @param[in] index_dim_one The index of the element in dimension 1
147  /// @param[in] index_dim_other The index of the element in the other dimensions
148  /// @tparam IF The type of the first index parameter
149  /// @tparam IR The types of the rest of the index parameters
150  /// @return A reference to the element at the position given by the indices
151  // ------------------------------------------------------------------------------------------------------
152  template <typename IF, typename... IR>
153  DT& operator()(IF index_dim_one, IR... index_dim_other);
154 
155  // ------------------------------------------------------------------------------------------------------
156  /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
157  /// checking as bound checking implementations will be provided through .at()
158  /// @param[in] index_dim_one The index of the element in dimension 1
159  /// @param[in] index_dim_other The index of the element in the other dimensions
160  /// @tparam IF The type of the first index parameter
161  /// @tparam IR The types of the rest of the index parameters
162  /// @return The value of the element at the position given by the indices
163  // ------------------------------------------------------------------------------------------------------
164  template <typename IF, typename... IR>
165  DT operator()(IF index_dim_one, IR... index_dim_other) const;
166 private:
167  data_container _data; //!< The data container which holds all the data
168  dim_container _dim_sizes; //!< The sizes of the dimensions for the tensor
169 };
170 
171 // ----------------------------------------------- IMPLEMENTATIONS ------------------------------------------
172 
173 // ------------------------------------------------- PUBLIC -------------------------------------------------
174 
175 template <typename DT, size_t SF, size_t...SR>
177 {
178  // Convert the nano::list of dimension sizes to a constant array
179  _dim_sizes = nano::runtime_converter<typename container_type::dimension_sizes>::to_array();
180 };
181 
182 template <typename DT, size_t SF, size_t...SR>
184 : _data(data)
185 {
186  // Convert the nano::list of dimension sizes to a constant array
187  _dim_sizes = nano::runtime_converter<typename container_type::dimension_sizes>::to_array();
188 }
189 
190 template <typename DT, size_t SF, size_t...SR> template <typename... TR>
191 TensorInterface<TensorTraits<DT, CPU, SF, SR...>>::TensorInterface(DT&& first_value, TR&&... other_values)
192 : _data{{std::forward<DT>(first_value), std::forward<TR>(other_values)...}}
193 {
194  // Convert the nano::list of dimension sizes to a constant array
195  _dim_sizes = nano::runtime_converter<typename container_type::dimension_sizes>::to_array();
196 }
197 
198 template <typename DT, size_t SF, size_t...SR> template <typename E, typename T>
200 {
201  // Convert the nano::list of dimension sizes to a constant array
202  _dim_sizes = nano::runtime_converter<typename container_type::dimension_sizes>::to_array();
203  for (size_type i = 0; i != size(); ++i) _data[i] = expression[i];
204 }
205 
206 template <typename DT, size_t SF, size_t... SR>
207 void TensorInterface<TensorTraits<DT, CPU, SF, SR...>>::initialize(const data_type min, const data_type max)
208 {
209  std::random_device rand_device;
210  std::mt19937 gen(rand_device());
211  std::uniform_real_distribution<> dist(min, max);
212  for (auto& element : _data) element = static_cast<data_type>(dist(gen));
213 }
214 
215 template <typename DT, size_t SF, size_t...SR> template <typename IF, typename... IR>
216 DT& TensorInterface<TensorTraits<DT, CPU, SF, SR...>>::operator()(IF dim_one_index, IR... other_dim_indices)
217 {
218  using dimension_sizes = typename container_type::dimension_sizes;
219  return _data[StaticMapper::indices_to_index<dimension_sizes>(dim_one_index, other_dim_indices...)];
220 }
221 
222 template <typename DT, size_t SF, size_t...SR> template <typename IF, typename... IR>
223 DT TensorInterface<TensorTraits<DT, CPU, SF, SR...>>::operator()(IF dim_one_index, IR... other_dim_indices) const
224 {
225  using dimension_sizes = typename container_type::dimension_sizes;
226  return _data[StaticMapper::indices_to_index<dimension_sizes>(dim_one_index, other_dim_indices...)];
227 }
228 
229 } // End namespace ftl
230 #endif // FTL_TENSOR_STATIC_CPU_HPP
typename traits::size_type size_type
Definition: tensor_static_cpu.hpp:57
typename container_type::data_container data_container
Definition: tensor_static_cpu.hpp:60
Definition: tensor_dynamic_cpu.hpp:44
constexpr size_type size() const
Gets the size (total number of elements) in the tensor.
Definition: tensor_static_cpu.hpp:105
constexpr const dim_container & dim_sizes() const
Gets a reference to the container holding the sizes of the dimensions for the tensor.
Definition: tensor_static_cpu.hpp:120
typename traits::container_type container_type
Definition: tensor_static_cpu.hpp:59
const data_type & operator[](size_type i) const
Gets an element from the tensor.
Definition: tensor_static_cpu.hpp:141
typename traits::data_type data_type
Definition: tensor_static_cpu.hpp:58
Definition: mapper.hpp:37
Defines a general tensor expression so that opertions on tensor expressions can be defined the syntax...
Definition: tensor_expression_interface.hpp:49
constexpr size_type rank() const
Gets the rank (number of dimensions) of the tensor.
Definition: tensor_static_cpu.hpp:99
typename container_type::dim_container dim_container
Definition: tensor_static_cpu.hpp:61
data_type & operator[](size_type i)
Gets an element from the tensor.
Definition: tensor_static_cpu.hpp:134
size_type size(const size_type dim) const
Gets the size (total number of elements) in a specific dimension of the tensor, if the dimension is v...
Definition: tensor_static_cpu.hpp:114
Traits class which specifies parameters for a tensor, such as what type of container it uses and what...
Definition: tensor_traits.hpp:48