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
25
namespace
plask
{
26
33
template
<
typename
T>
34
struct
LazyDataImpl
{
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
;
60
PLASK_OMP_PARALLEL_FOR
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
82
template
<
typename
T>
83
struct
ConstValueLazyDataImpl
:
public
LazyDataImpl
<T> {
84
85
T
value_
;
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
94
DataVector<const T>
getAll
()
const override
{
return
DataVector<const T>
(
size_
,
value_
); }
95
96
};
97
103
template
<
typename
T>
104
struct
LazyDataFromVectorImpl
:
public
LazyDataImpl
<T> {
105
106
DataVector<const T>
vec
;
107
108
LazyDataFromVectorImpl
(
DataVector<const T>
vec
):
vec
(
vec
) {}
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
122
template
<
typename
T>
123
struct
LazyDataDelegateImpl
:
public
LazyDataImpl
<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>
143
struct 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
160
template
<
typename
T>
161
class
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;
165
shared_ptr< const LazyDataImpl<T>
> impl;
166
167
public
:
168
169
typedef
T
CellType
;
170
typedef
DataVector<T>
DataVectorType
;
171
typedef
DataVector<const T>
DataVectorOfConstType
;
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
190
LazyData
(
DataVector<const T>
data_vector
): impl(
new
LazyDataFromVectorImpl
<T>(
data_vector
)) {}
191
LazyData
(
DataVector<T>
data_vector
): impl(
new
LazyDataFromVectorImpl
<T>(
data_vector
)) {}
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
205
void
reset
(
DataVector<const T>
data_vector
) { impl.reset(
new
LazyDataFromVectorImpl<T>
(
data_vector
)); }
206
void
reset
(
DataVector<T>
data_vector
) { impl.reset(
new
LazyDataFromVectorImpl<T>
(
data_vector
)); }
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
235
DataVector<T>
claim
()
const
{
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
251
typedef
IndexedIterator< const LazyData, T >
const_iterator
;
252
typedef
const_iterator
iterator
;
253
typedef
const_iterator
Iterator
;
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
266
template
<
typename
T,
typename
ScaleT,
typename
ReturnedType =
typename
std::remove_cv<decltype(T()*ScaleT())>::type>
267
struct
ScaledLazyDataImpl
:
public
LazyDataImpl
<ReturnedType> {
268
269
LazyData<T>
data
;
270
271
ScaleT
scale
;
272
273
ScaledLazyDataImpl
(
LazyData<T>
data
,
const
ScaleT
&
scale
)
274
:
data
(
std
::move(
data
)),
scale
(
scale
) {}
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
288
template
<
typename
T,
typename
S>
289
LazyData<typename ScaledLazyDataImpl<T, S>::CellType
>
operator*
(
LazyData<T>
data,
const
S& scale) {
290
return
new
ScaledLazyDataImpl<T, S>
(std::move(data), scale);
291
}
292
299
template
<
typename
T,
typename
S>
300
LazyData<typename ScaledLazyDataImpl<T, S>::CellType
>
operator*
(
const
S& scale,
LazyData<T>
data) {
301
return
new
ScaledLazyDataImpl<T, S>
(std::move(data), scale);
302
}
303
309
template
<
class
T1,
class
T2>
inline
310
bool
operator==
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
)
311
{
return
a
.size() ==
b
.size() && std::equal(
a
.begin(),
a
.end(),
b
.begin()); }
312
318
template
<
class
T1,
class
T2>
inline
319
bool
operator==
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
)
320
{
return
a
.size() ==
b
.size() && std::equal(
a
.begin(),
a
.end(),
b
.begin()); }
321
327
template
<
class
T1,
class
T2>
inline
328
bool
operator==
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
b
==
a
; }
329
335
template
<
class
T1,
class
T2>
inline
bool
operator!=
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
a
==
b
); }
336
template
<
class
T1,
class
T2>
inline
bool
operator!=
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
) {
return
!(
a
==
b
); }
337
template
<
class
T1,
class
T2>
inline
bool
operator!=
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
a
==
b
); }
338
344
template
<
class
T1,
class
T2>
inline
bool
345
operator<
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
std::lexicographical_compare(
a
.begin(),
a
.end(),
b
.begin(),
b
.end()); }
346
347
template
<
class
T1,
class
T2>
inline
bool
348
operator<
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
std::lexicographical_compare(
a
.begin(),
a
.end(),
b
.begin(),
b
.end()); }
349
350
template
<
class
T1,
class
T2>
inline
bool
351
operator<
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
) {
return
std::lexicographical_compare(
a
.begin(),
a
.end(),
b
.begin(),
b
.end()); }
352
358
template
<
class
T1,
class
T2>
inline
bool
operator>
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
b
<
a
; }
359
template
<
class
T1,
class
T2>
inline
bool
operator>
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
b
<
a
; }
360
template
<
class
T1,
class
T2>
inline
bool
operator>
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
) {
return
b
<
a
; }
361
367
template
<
class
T1,
class
T2>
inline
bool
operator<=
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
b
<
a
); }
368
template
<
class
T1,
class
T2>
inline
bool
operator<=
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
b
<
a
); }
369
template
<
class
T1,
class
T2>
inline
bool
operator<=
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
) {
return
!(
b
<
a
); }
370
376
template
<
class
T1,
class
T2>
inline
bool
operator>=
(
LazyData<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
a
<
b
); }
377
template
<
class
T1,
class
T2>
inline
bool
operator>=
(
DataVector<T1>
const
&
a
,
LazyData<T2>
const
&
b
) {
return
!(
a
<
b
); }
378
template
<
class
T1,
class
T2>
inline
bool
operator>=
(
LazyData<T1>
const
&
a
,
DataVector<T2>
const
&
b
) {
return
!(
a
<
b
); }
379
386
template
<
class
T>
387
std::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
398
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(Tensor3<
complex<double>
>)
399
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(Tensor2<
double
>)
400
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(Vec<3,
complex
<
double
>>)
401
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(Vec<3,
double
>)
402
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(Vec<2,
double
>)
403
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(
double
)
404
PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_FOR_LAZY_DATA
(
complex
<
double
>)
405
406
#endif
407
408
413
template
<
typename
T>
414
struct
SafeDataImpl
:
public
LazyDataImpl
<T> {
415
416
const
LazyData<T>
src
;
417
const
T
safe_value
;
418
424
SafeDataImpl
(
const
LazyData<T>
&
src
,
const
T
safe_value
=
Zero<T>
()):
src
(
src
),
safe_value
(
safe_value
) {}
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
436
template
<
typename
T>
437
inline
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
plask
lazydata.hpp
Generated by
1.9.8