Tatooine
base_tensor.h
Go to the documentation of this file.
1#ifndef TATOOINE_BASE_TENSOR_H
2#define TATOOINE_BASE_TENSOR_H
3//==============================================================================
4#include <tatooine/crtp.h>
12
13#include <cassert>
14#include <type_traits>
15//==============================================================================
16namespace tatooine {
17//==============================================================================
18template <typename Tensor, arithmetic_or_complex ValueType,
19 std::size_t FixedDim, std::size_t... Dims>
20struct tensor_slice;
21//------------------------------------------------------------------------------
22template <typename Tensor, arithmetic_or_complex ValueType, std::size_t... Dims>
23struct base_tensor : crtp<Tensor> {
24 using value_type = ValueType;
26 using this_type = base_tensor<Tensor, ValueType, Dims...>;
30 template <einstein_notation::index... Is>
33 template <einstein_notation::index... Is>
35
36 static_assert(is_arithmetic<ValueType> || is_complex<ValueType>,
37 "A tensor can only hold real or complex values.");
38 static_assert(sizeof...(Dims) > 0,
39 "base tensor needs to have more than one dimension defined.");
40 //============================================================================
41 static auto constexpr rank() { return sizeof...(Dims); }
42 //------------------------------------------------------------------------------
43 static auto constexpr num_components() {
45 }
46 //------------------------------------------------------------------------------
47 static auto constexpr dimensions() { return std::array{Dims...}; }
48 //------------------------------------------------------------------------------
49 static auto constexpr dimension(std::size_t const i) {
50 return dimensions()[i];
51 }
52 //------------------------------------------------------------------------------
53 static auto constexpr is_static() -> bool { return true; }
54 static auto constexpr is_tensor() -> bool { return true; }
55 //------------------------------------------------------------------------------
56 static auto constexpr indices() { return multidim_size_t::indices(); }
57 //------------------------------------------------------------------------------
58 static auto constexpr for_indices(invocable<decltype(Dims)...> auto&& f) {
59 for_loop(std::forward<decltype(f)>(f), Dims...);
60 }
61 //============================================================================
62 constexpr base_tensor() = default;
63 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
64 template <static_tensor Other>
65 requires(same_dimensions<this_type, Other>()) &&
67 explicit constexpr base_tensor(Other&& other) {
68 assign(std::forward<Other>(other));
69 }
70 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
71 template <static_tensor Other>
72 requires(same_dimensions<this_type, Other>()) &&
74 auto constexpr operator=(Other&& other) -> base_tensor& {
75 assign(std::forward<Other>(other));
76 return *this;
77 }
78 //============================================================================
79 template <static_tensor Other>
80 requires(same_dimensions<this_type, Other>()) &&
82 auto constexpr assign(Other&& other) -> void {
83 for_indices([this, &other](auto const... is) {
84 this->at(is...) = static_cast<value_type>(other(is...));
85 });
86 }
87 //----------------------------------------------------------------------------
88 template <einstein_notation::index... Is>
89 requires(sizeof...(Is) == rank())
90 auto constexpr at(Is const... /*is*/) {
91 return indexed_type<Is...>{as_derived()};
92 }
93 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94 template <einstein_notation::index... Is>
95 requires(sizeof...(Is) == rank())
96 auto constexpr at(Is const... /*is*/) const {
97 return const_indexed_type<Is...>{as_derived()};
98 }
99 //----------------------------------------------------------------------------
100 template <einstein_notation::index... Is>
101 requires(sizeof...(Is) == rank())
102 auto constexpr operator()(Is const... is) const {
103 return at(is...);
104 }
105 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
106 template <einstein_notation::index... Is>
107 requires(sizeof...(Is) == rank())
108 auto constexpr operator()(Is const... is) {
109 return at(is...);
110 }
111 //----------------------------------------------------------------------------
112 auto constexpr at(integral auto const... is) const -> decltype(auto)
113 requires(sizeof...(is) == rank())
114 {
115 return as_derived().at(is...);
116 }
117 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118 auto constexpr at(integral auto const... is) -> decltype(auto)
119 requires(sizeof...(is) == rank())
120 {
121 return as_derived().at(is...);
122 } //----------------------------------------------------------------------------
123 private:
124 template <std::size_t... Seq>
125 auto constexpr at(integral_range auto const& is,
126 std::index_sequence<Seq...> /*seq*/) -> decltype(auto) {
127 return at(is[Seq]...);
128 }
129 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
130 template <std::size_t... Seq>
131 auto constexpr at(integral_range auto const& is,
132 std::index_sequence<Seq...> /*seq*/) const
133 -> decltype(auto) {
134 return at(is[Seq]...);
135 }
136 //----------------------------------------------------------------------------
137 public:
138 auto constexpr at(integral_range auto const& is) -> decltype(auto) {
139 assert(is.size() == rank());
140 return at(is, std::make_index_sequence<rank()>{});
141 }
142 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
143 auto constexpr at(integral_range auto const& is) const -> decltype(auto) {
144 assert(is.size() == rank());
145 return at(is, std::make_index_sequence<rank()>{});
146 }
147 //----------------------------------------------------------------------------
148 auto constexpr operator()(integral auto const... is) const -> decltype(auto)
149 requires(sizeof...(is) == rank())
150 {
151 return at(is...);
152 }
153 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
154 auto constexpr operator()(integral auto const... is) -> decltype(auto)
155 requires(sizeof...(is) == rank())
156 {
157 return at(is...);
158 }
159 //----------------------------------------------------------------------------
160 template <std::size_t FixedDim, std::size_t... Is>
161 auto constexpr slice(std::size_t fixed_index, std::index_sequence<Is...>)
162 -> decltype(auto) {
163 if constexpr (rank() > 1) {
164 static_assert(
165 FixedDim < rank(),
166 "Fixed dimensions must be in range of number of dimensions.");
167 return tensor_slice<Tensor, ValueType, FixedDim,
168 dimension(sliced_indices<rank(), FixedDim>()[Is])...>{
169 &as_derived(), fixed_index};
170 } else {
171 return at(fixed_index);
172 }
173 }
174 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 template <std::size_t FixedDim>
176 auto constexpr slice(std::size_t fixed_index) -> decltype(auto) {
177 if constexpr (rank() > 1) {
178 static_assert(
179 FixedDim < rank(),
180 "Fixed dimensions must be in range of number of dimensions.");
181 return slice<FixedDim>(fixed_index,
182 std::make_index_sequence<rank() - 1>{});
183 } else {
184 return at(fixed_index);
185 }
186 }
187 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
188 template <std::size_t FixedDim, std::size_t... Is>
189 auto constexpr slice(std::size_t fixed_index,
190 std::index_sequence<Is...>) const {
191 static_assert(FixedDim < rank(),
192 "fixed dimensions must be in range of number of dimensions");
193 return tensor_slice<Tensor const, ValueType, FixedDim,
194 dimension(sliced_indices<rank(), FixedDim>()[Is])...>{
195 &as_derived(), fixed_index};
196 }
197 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
198 template <std::size_t FixedDim>
199 [[nodiscard]] auto constexpr slice(std::size_t fixed_index) const {
200 static_assert(FixedDim < rank(),
201 "fixed dimensions must be in range of number of dimensions");
202 return slice<FixedDim>(fixed_index, std::make_index_sequence<rank() - 1>{});
203 }
204
205 //----------------------------------------------------------------------------
206 static auto constexpr array_index(integral auto const... is) {
207 static_assert(sizeof...(is) == rank(),
208 "number of indices does not match number of dimensions");
210 }
211
212 //----------------------------------------------------------------------------
213 template <typename OtherTensor, typename OtherValueType>
216 for_indices([&](auto const... is) {
217 at(is...) += static_cast<ValueType>(other(is...));
218 });
219 return *this;
220 }
221 //----------------------------------------------------------------------------
222 auto operator+=(convertible_to<ValueType> auto const& other) -> auto& {
223 for_indices([&](auto const... is) { at(is...) += other; });
224 return *this;
225 }
226 //----------------------------------------------------------------------------
227 template <typename OtherTensor, typename OtherValueType>
230 for_indices([&](auto const... is) {
231 at(is...) -= static_cast<ValueType>(other(is...));
232 });
233 return *this;
234 }
235 //----------------------------------------------------------------------------
236 auto operator-=(convertible_to<ValueType> auto const& other) -> auto& {
237 for_indices([&](auto const... is) { at(is...) -= other; });
238 return *this;
239 }
240 //----------------------------------------------------------------------------
241 auto operator*=(convertible_to<ValueType> auto const& other) -> auto& {
242 for_indices([&](auto const... is) { at(is...) *= other; });
243 return *this;
244 }
245 //----------------------------------------------------------------------------
246 auto operator/=(convertible_to<ValueType> auto const& other) -> auto& {
247 for_indices([&](auto const... is) { at(is...) /= other; });
248 return *this;
249 }
250 //----------------------------------------------------------------------------
251 auto isnan() const {
252 auto b = false;
253 for_indices([&](auto const... is) {
254 if (std::isnan(at(is...))) {
255 b = true;
256 return false;
257 }
258 return true;
259 });
260 return b;
261 }
262 //----------------------------------------------------------------------------
263 auto isinf() const {
264 auto b = false;
265 for_indices([&](auto const... is) {
266 if (std::isinf(at(is...))) {
267 b = true;
268 return false;
269 }
270 return true;
271 });
272 return b;
273 }
274};
275//==============================================================================
276template <arithmetic_or_complex ValueType, std::size_t... Dims>
277struct tensor;
278template <arithmetic_or_complex ValueType, std::size_t M, std::size_t N>
279struct mat;
280template <arithmetic_or_complex ValueType, std::size_t N>
281struct vec;
282//==============================================================================
283} // namespace tatooine
284//==============================================================================
286//==============================================================================
287#endif
Definition: concepts.h:39
Definition: concepts.h:91
Definition: concepts.h:21
Definition: concepts.h:121
Definition: algorithm.h:6
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
tensor< real_number, Dimensions... > Tensor
Definition: tensor.h:184
constexpr auto sliced_indices()
creates an index sequence and removes an element from it
Definition: utility.h:33
constexpr auto for_loop(Iteration &&iteration, execution_policy::sequential_t, Ranges(&&... ranges)[2]) -> void
Use this function for creating a sequential nested loop.
Definition: for_loop.h:336
Definition: base_tensor.h:23
static auto constexpr rank()
Definition: base_tensor.h:41
auto constexpr slice(std::size_t fixed_index, std::index_sequence< Is... >) -> decltype(auto)
Definition: base_tensor.h:161
auto operator+=(base_tensor< OtherTensor, OtherValueType, Dims... > const &other) -> auto &
Definition: base_tensor.h:214
auto constexpr at(integral_range auto const &is, std::index_sequence< Seq... >) -> decltype(auto)
Definition: base_tensor.h:125
auto constexpr assign(Other &&other) -> void
Definition: base_tensor.h:82
auto constexpr at(integral_range auto const &is) const -> decltype(auto)
Definition: base_tensor.h:143
auto constexpr at(integral_range auto const &is) -> decltype(auto)
Definition: base_tensor.h:138
auto constexpr at(integral_range auto const &is, std::index_sequence< Seq... >) const -> decltype(auto)
Definition: base_tensor.h:131
auto isinf() const
Definition: base_tensor.h:263
auto constexpr at(integral auto const ... is) -> decltype(auto) requires(sizeof...(is)==rank())
Definition: base_tensor.h:118
auto constexpr slice(std::size_t fixed_index) const
Definition: base_tensor.h:199
auto operator/=(convertible_to< ValueType > auto const &other) -> auto &
Definition: base_tensor.h:246
static auto constexpr dimension(std::size_t const i)
Definition: base_tensor.h:49
auto operator-=(base_tensor< OtherTensor, OtherValueType, Dims... > const &other) -> auto &
Definition: base_tensor.h:228
ValueType value_type
Definition: base_tensor.h:24
auto operator-=(convertible_to< ValueType > auto const &other) -> auto &
Definition: base_tensor.h:236
constexpr base_tensor(Other &&other)
Definition: base_tensor.h:67
auto constexpr slice(std::size_t fixed_index) -> decltype(auto)
Definition: base_tensor.h:176
auto constexpr at(Is const ...) const
Definition: base_tensor.h:96
auto operator+=(convertible_to< ValueType > auto const &other) -> auto &
Definition: base_tensor.h:222
auto isnan() const
Definition: base_tensor.h:251
static auto constexpr array_index(integral auto const ... is)
Definition: base_tensor.h:206
static auto constexpr num_components()
Definition: base_tensor.h:43
auto constexpr operator()(integral auto const ... is) -> decltype(auto) requires(sizeof...(is)==rank())
Definition: base_tensor.h:154
auto constexpr operator()(integral auto const ... is) const -> decltype(auto) requires(sizeof...(is)==rank())
Definition: base_tensor.h:148
auto constexpr slice(std::size_t fixed_index, std::index_sequence< Is... >) const
Definition: base_tensor.h:189
static auto constexpr is_static() -> bool
Definition: base_tensor.h:53
auto operator*=(convertible_to< ValueType > auto const &other) -> auto &
Definition: base_tensor.h:241
auto constexpr operator=(Other &&other) -> base_tensor &
Definition: base_tensor.h:74
static auto constexpr is_tensor() -> bool
Definition: base_tensor.h:54
static auto constexpr for_indices(invocable< decltype(Dims)... > auto &&f)
Definition: base_tensor.h:58
constexpr base_tensor()=default
static auto constexpr dimensions()
Definition: base_tensor.h:47
auto constexpr at(integral auto const ... is) const -> decltype(auto) requires(sizeof...(is)==rank())
Definition: base_tensor.h:112
static auto constexpr indices()
Definition: base_tensor.h:56
auto constexpr at(Is const ...)
Definition: base_tensor.h:90
Definition: crtp.h:7
constexpr auto as_derived() -> derived_type &
returns casted as_derived data
Definition: crtp.h:11
type_list< Indices... > indices
Definition: indexed_dynamic_tensor.h:41
Definition: indexed_static_tensor.h:22
Definition: static_multidim_size.h:81
static auto constexpr num_components()
Definition: static_multidim_size.h:83
Definition: tensor_slice.h:13
Definition: tensor.h:17
Definition: index_order.h:17