PLaSK library
Loading...
Searching...
No Matches
lazydata.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__LAZYDATA_H
15#define PLASK__LAZYDATA_H
16
17#include "data.hpp"
18#include "parallel.hpp"
19#include "utils/openmp.hpp"
20
21#include "vector/tensor2.hpp"
22#include "vector/tensor3.hpp"
23#include "utils/iterators.hpp"
24
25namespace plask {
26
33template <typename T>
35
36 typedef T CellType;
37
38 virtual ~LazyDataImpl() {}
39
45 virtual T at(std::size_t index) const = 0;
46
51 virtual std::size_t size() const = 0;
52
57 virtual DataVector<const T> getAll() const {
58 DataVector<T> res(this->size());
59 std::exception_ptr error;
61 for (openmp_size_t i = 0; i < res.size(); ++i) {
62 if (error) continue;
63 try {
64 res[i] = this->at(i);
65 } catch(...) {
66 #pragma omp critical
67 error = std::current_exception();
68 }
69 }
70 if (error) std::rethrow_exception(error);
71 return res;
72 }
73
74 virtual DataVector<T> claim() const {
75 return this->getAll().claim();
76 }
77};
78
82template <typename T>
84
86 std::size_t size_;
87
88 ConstValueLazyDataImpl(std::size_t size, const T& value): value_(value), size_(size) {}
89
90 T at(std::size_t) const override { return value_; }
91
92 std::size_t size() const override { return size_; }
93
95
96};
97
103template <typename T>
105
107
109
110 T at(std::size_t index) const override { return vec[index]; }
111
112 std::size_t size() const override { return vec.size(); }
113
114 DataVector<const T> getAll() const override { return vec; }
115
116 DataVector<T> claim() const override { return vec.claim(); }
117};
118
122template <typename T>
124
125 protected:
126 std::size_t siz;
127 std::function<T(std::size_t)> func;
128
129 public:
130 LazyDataDelegateImpl(std::size_t size, std::function<T(std::size_t)> func): siz(size), func(std::move(func)) {}
131
132 T at(std::size_t index) const override { return func(index); }
133
134 std::size_t size() const override { return siz; }
135};
136
137
138
139/*
140 * Base class for lazy data (vector) that holds reference to destination mesh (dst_mesh).
141 */
142/*template <typename T, typename DstMeshType>
143struct LazyDataWithMeshImpl: public LazyDataImpl<T> {
144
145 shared_ptr<const DstMeshType> dst_mesh;
146
147 LazyDataWithMeshImpl(shared_ptr<const DstMeshType> dst_mesh): dst_mesh(dst_mesh) {}
148
149 std::size_t size() const override { return dst_mesh->size(); }
150
151};*/
152
160template <typename T>
161class LazyData {
162
163 //TODO change back to unique_ptr when move to lambda capture (C++14) will be supported:
164 //std::unique_ptr< const LazyDataImpl<T> > impl;
166
167public:
168
169 typedef T CellType;
172
177 LazyData(const LazyDataImpl<T>* impl = nullptr): impl(impl) {}
178
184 LazyData(std::size_t size, T value): impl(new ConstValueLazyDataImpl<T>(size, value)) {}
185
192
198 LazyData(std::size_t size, std::function<T(std::size_t)> func):
199 impl(new LazyDataDelegateImpl<T>(size, std::move(func))) {}
200
201 void reset(const LazyDataImpl<T>* new_impl = nullptr) { impl.reset(new_impl); }
202
203 void reset(std::size_t size, T value) { impl.reset(new ConstValueLazyDataImpl<T>(size, value)); }
204
207
208 void reset(std::size_t size, std::function<T(std::size_t)> func) {
209 impl.reset(new LazyDataDelegateImpl<T>(size, std::move(func)));
210 }
211
212 /*LazyData(const LazyData&) = default;
213 LazyData(LazyData&&) = default;
214 LazyData& operator=(const LazyData&) & = default;
215 LazyData& operator=(LazyData&&) & = default;*/
216
222 T operator[](std::size_t index) const { return impl->at(index); }
223
229 T at(std::size_t index) const { return impl->at(index); }
230
231 DataVector<const T> nonLazy() const { return impl->getAll(); }
232
233 operator DataVector<const T> () const { return impl->getAll(); }
234
236 return impl->claim();
237 //TODO jeśli używany shared_ptr, to co z przypadkiem gdy impl ma więcej niż 1 referencję? wtedy powinno być zrobione impl->getAll()->claim();
238 // (w przypadku trzymania data vectora zostanie on skopiowany)
239 }
240
245 std::size_t size() const { return impl->size(); }
246
254
256 const_iterator begin() const { return const_iterator(this, 0); }
257
259 const_iterator end() const { return const_iterator(this, size()); }
260
261 bool isNotNull() const { return bool(impl); }
262
263 bool isNull() const { return !impl; }
264};
265
266template <typename T, typename ScaleT, typename ReturnedType = typename std::remove_cv<decltype(T()*ScaleT())>::type>
267struct ScaledLazyDataImpl: public LazyDataImpl<ReturnedType> {
268
270
272
275
276 ReturnedType at(std::size_t index) const override { return data[index] * scale; }
277
278 std::size_t size() const override { return data.size(); }
279
280};
281
288template<typename T, typename S>
290 return new ScaledLazyDataImpl<T, S>(std::move(data), scale);
291}
292
299template<typename T, typename S>
301 return new ScaledLazyDataImpl<T, S>(std::move(data), scale);
302}
303
309template<class T1, class T2> inline
311{ return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
312
318template<class T1, class T2> inline
320{ return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
321
327template<class T1, class T2> inline
328bool operator== (DataVector<T1> const& a, LazyData<T2> const& b) { return b == a; }
329
335template<class T1, class T2> inline bool operator!=(LazyData<T1> const& a, LazyData<T2> const& b) { return !(a==b); }
336template<class T1, class T2> inline bool operator!=(LazyData<T1> const& a, DataVector<T2> const& b) { return !(a==b); }
337template<class T1, class T2> inline bool operator!=(DataVector<T1> const& a, LazyData<T2> const& b) { return !(a==b); }
338
344template<class T1, class T2> inline bool
345operator< (LazyData<T1> const& a, LazyData<T2> const& b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
346
347template<class T1, class T2> inline bool
348operator< (DataVector<T1> const& a, LazyData<T2> const& b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
349
350template<class T1, class T2> inline bool
351operator< (LazyData<T1> const& a, DataVector<T2> const& b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
352
358template<class T1, class T2> inline bool operator> (LazyData<T1> const& a, LazyData<T2> const& b) { return b < a; }
359template<class T1, class T2> inline bool operator> (DataVector<T1> const& a, LazyData<T2> const& b) { return b < a; }
360template<class T1, class T2> inline bool operator> (LazyData<T1> const& a, DataVector<T2> const& b) { return b < a; }
361
367template<class T1, class T2> inline bool operator<= (LazyData<T1> const& a, LazyData<T2> const& b) { return !(b < a); }
368template<class T1, class T2> inline bool operator<= (DataVector<T1> const& a, LazyData<T2> const& b) { return !(b < a); }
369template<class T1, class T2> inline bool operator<= (LazyData<T1> const& a, DataVector<T2> const& b) { return !(b < a); }
370
376template<class T1, class T2> inline bool operator>= (LazyData<T1> const& a, LazyData<T2> const& b) { return !(a < b); }
377template<class T1, class T2> inline bool operator>= (DataVector<T1> const& a, LazyData<T2> const& b) { return !(a < b); }
378template<class T1, class T2> inline bool operator>= (LazyData<T1> const& a, DataVector<T2> const& b) { return !(a < b); }
379
386template<class T>
387std::ostream& operator<<(std::ostream& out, LazyData<T> const& to_print) {
388 out << '['; return print_seq(out, to_print.begin(), to_print.end()) << ']';
389}
390
391
392#ifdef _MSC_VER // MSVC requires this while MingW does not accept it
393
394#define PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA(...) \
395 PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_CLASS(LazyData<__VA_ARGS__>); \
396 PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_STRUCT(LazyDataImpl<__VA_ARGS__>);
397
405
406#endif
407
408
413template <typename T>
414struct SafeDataImpl: public LazyDataImpl<T> {
415
417 const T safe_value;
418
425
426 std::size_t size() const override { return src.size(); }
427
428 T at(std::size_t i) const override { return remove_nan(src.at(i), safe_value); }
429};
430
436template <typename T>
437inline LazyData<T> SafeData(const LazyData<T>& src, const T safe_value=Zero<T>()) {
438 return LazyData<T>(new SafeDataImpl<T>(src, safe_value));
439}
440
441} // namespace plask
442
443#endif // PLASK__LAZYDATA_H