DataContainer.cpp 24.3 KB
Newer Older
Tobias Lasser's avatar
Tobias Lasser committed
1
#include "DataContainer.h"
2
#include "DataContainerFormatter.hpp"
3
#include "FormatConfig.h"
Tobias Lasser's avatar
Tobias Lasser committed
4
#include "DataHandlerCPU.h"
5
6
#include "DataHandlerMapCPU.h"
#include "BlockDescriptor.h"
7
#include "RandomBlocksDescriptor.h"
8
#include "PartitionDescriptor.h"
9
#include "Error.h"
10
#include "TypeCasts.hpp"
David Frank's avatar
David Frank committed
11
#include "Assertions.h"
Tobias Lasser's avatar
Tobias Lasser committed
12
13
14

#include <utility>

Jens Petit's avatar
Jens Petit committed
15
16
namespace elsa
{
Tobias Lasser's avatar
Tobias Lasser committed
17
18

    template <typename data_t>
Jens Petit's avatar
Jens Petit committed
19
20
21
    DataContainer<data_t>::DataContainer(const DataDescriptor& dataDescriptor,
                                         DataHandlerType handlerType)
        : _dataDescriptor{dataDescriptor.clone()},
Jens Petit's avatar
Jens Petit committed
22
23
          _dataHandler{createDataHandler(handlerType, _dataDescriptor->getNumberOfCoefficients())},
          _dataHandlerType{handlerType}
Jens Petit's avatar
Jens Petit committed
24
25
26
27
28
29
30
31
    {
    }

    template <typename data_t>
    DataContainer<data_t>::DataContainer(const DataDescriptor& dataDescriptor,
                                         const Eigen::Matrix<data_t, Eigen::Dynamic, 1>& data,
                                         DataHandlerType handlerType)
        : _dataDescriptor{dataDescriptor.clone()},
Jens Petit's avatar
Jens Petit committed
32
33
          _dataHandler{createDataHandler(handlerType, _dataDescriptor->getNumberOfCoefficients())},
          _dataHandlerType{handlerType}
Tobias Lasser's avatar
Tobias Lasser committed
34
35
    {
        if (_dataHandler->getSize() != data.size())
36
            throw InvalidArgumentError("DataContainer: initialization vector has invalid size");
Jens Petit's avatar
Jens Petit committed
37

Tobias Lasser's avatar
Tobias Lasser committed
38
39
40
41
42
        for (index_t i = 0; i < _dataHandler->getSize(); ++i)
            (*_dataHandler)[i] = data[i];
    }

    template <typename data_t>
Jens Petit's avatar
Jens Petit committed
43
    DataContainer<data_t>::DataContainer(const DataContainer<data_t>& other)
Jens Petit's avatar
Jens Petit committed
44
45
46
        : _dataDescriptor{other._dataDescriptor->clone()},
          _dataHandler{other._dataHandler->clone()},
          _dataHandlerType{other._dataHandlerType}
Jens Petit's avatar
Jens Petit committed
47
48
    {
    }
Tobias Lasser's avatar
Tobias Lasser committed
49
50
51
52
53
54

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator=(const DataContainer<data_t>& other)
    {
        if (this != &other) {
            _dataDescriptor = other._dataDescriptor->clone();
55

56
            if (_dataHandler && canAssign(other._dataHandlerType)) {
57
58
59
                *_dataHandler = *other._dataHandler;
            } else {
                _dataHandler = other._dataHandler->clone();
60
                _dataHandlerType = other._dataHandlerType;
61
            }
Tobias Lasser's avatar
Tobias Lasser committed
62
63
64
65
66
67
        }

        return *this;
    }

    template <typename data_t>
Jens Petit's avatar
Jens Petit committed
68
    DataContainer<data_t>::DataContainer(DataContainer<data_t>&& other) noexcept
Tobias Lasser's avatar
Tobias Lasser committed
69
        : _dataDescriptor{std::move(other._dataDescriptor)},
Jens Petit's avatar
Jens Petit committed
70
71
          _dataHandler{std::move(other._dataHandler)},
          _dataHandlerType{std::move(other._dataHandlerType)}
Tobias Lasser's avatar
Tobias Lasser committed
72
    {
73
74
75
        // leave other in a valid state
        other._dataDescriptor = nullptr;
        other._dataHandler = nullptr;
Tobias Lasser's avatar
Tobias Lasser committed
76
77
78
    }

    template <typename data_t>
79
    DataContainer<data_t>& DataContainer<data_t>::operator=(DataContainer<data_t>&& other)
Tobias Lasser's avatar
Tobias Lasser committed
80
81
    {
        _dataDescriptor = std::move(other._dataDescriptor);
Jens Petit's avatar
Jens Petit committed
82

83
        if (_dataHandler && canAssign(other._dataHandlerType)) {
84
85
86
            *_dataHandler = std::move(*other._dataHandler);
        } else {
            _dataHandler = std::move(other._dataHandler);
87
            _dataHandlerType = std::move(other._dataHandlerType);
88
        }
Tobias Lasser's avatar
Tobias Lasser committed
89

90
91
92
        // leave other in a valid state
        other._dataDescriptor = nullptr;
        other._dataHandler = nullptr;
Tobias Lasser's avatar
Tobias Lasser committed
93
94
95
96

        return *this;
    }

Jens Petit's avatar
Jens Petit committed
97
98
    template <typename data_t>
    const DataDescriptor& DataContainer<data_t>::getDataDescriptor() const
Tobias Lasser's avatar
Tobias Lasser committed
99
100
101
102
    {
        return *_dataDescriptor;
    }

Jens Petit's avatar
Jens Petit committed
103
    template <typename data_t>
Tobias Lasser's avatar
Tobias Lasser committed
104
105
106
107
108
    index_t DataContainer<data_t>::getSize() const
    {
        return _dataHandler->getSize();
    }

Jens Petit's avatar
Jens Petit committed
109
110
    template <typename data_t>
    data_t& DataContainer<data_t>::operator[](index_t index)
Tobias Lasser's avatar
Tobias Lasser committed
111
    {
David Frank's avatar
David Frank committed
112
113
114
        ELSA_VERIFY(index >= 0);
        ELSA_VERIFY(index < getSize());

Tobias Lasser's avatar
Tobias Lasser committed
115
116
117
        return (*_dataHandler)[index];
    }

Jens Petit's avatar
Jens Petit committed
118
119
    template <typename data_t>
    const data_t& DataContainer<data_t>::operator[](index_t index) const
Tobias Lasser's avatar
Tobias Lasser committed
120
    {
David Frank's avatar
David Frank committed
121
122
123
        ELSA_VERIFY(index >= 0);
        ELSA_VERIFY(index < getSize());

124
        return static_cast<const DataHandler<data_t>&>(*_dataHandler)[index];
Tobias Lasser's avatar
Tobias Lasser committed
125
126
    }

David Frank's avatar
David Frank committed
127
128
129
130
131
132
133
134
135
136
137
138
    template <typename data_t>
    data_t DataContainer<data_t>::at(IndexVector_t coordinate) const
    {
        const auto arr = coordinate.array();
        if ((arr < 0).any()
            || (arr >= _dataDescriptor->getNumberOfCoefficientsPerDimension().array()).any()) {
            return 0;
        }

        return (*this)[_dataDescriptor->getIndexFromCoordinate(std::move(coordinate))];
    }

Jens Petit's avatar
Jens Petit committed
139
140
    template <typename data_t>
    data_t& DataContainer<data_t>::operator()(IndexVector_t coordinate)
Tobias Lasser's avatar
Tobias Lasser committed
141
    {
David Frank's avatar
David Frank committed
142
143
144
145
        // const auto arr = coordinate.array();
        // const auto shape = _dataDescriptor->getNumberOfCoefficientsPerDimension().array();
        // ELSA_VERIFY((arr >= 0).all());
        // ELSA_VERIFY((arr < shape).all());
David Frank's avatar
David Frank committed
146
147

        return (*this)[_dataDescriptor->getIndexFromCoordinate(std::move(coordinate))];
Tobias Lasser's avatar
Tobias Lasser committed
148
149
    }

Jens Petit's avatar
Jens Petit committed
150
151
    template <typename data_t>
    const data_t& DataContainer<data_t>::operator()(IndexVector_t coordinate) const
Tobias Lasser's avatar
Tobias Lasser committed
152
    {
David Frank's avatar
David Frank committed
153
154
155
156
        // const auto arr = coordinate.array();
        // const auto shape = _dataDescriptor->getNumberOfCoefficientsPerDimension().array();
        // ELSA_VERIFY((arr >= 0).all());
        // ELSA_VERIFY((arr < shape).all());
David Frank's avatar
David Frank committed
157
158

        return (*this)[_dataDescriptor->getIndexFromCoordinate(coordinate)];
Tobias Lasser's avatar
Tobias Lasser committed
159
160
    }

Jens Petit's avatar
Jens Petit committed
161
162
    template <typename data_t>
    data_t DataContainer<data_t>::dot(const DataContainer<data_t>& other) const
Tobias Lasser's avatar
Tobias Lasser committed
163
164
165
166
    {
        return _dataHandler->dot(*other._dataHandler);
    }

Jens Petit's avatar
Jens Petit committed
167
    template <typename data_t>
168
    GetFloatingPointType_t<data_t> DataContainer<data_t>::squaredL2Norm() const
Tobias Lasser's avatar
Tobias Lasser committed
169
    {
Tobias Lasser's avatar
Tobias Lasser committed
170
171
172
        return _dataHandler->squaredL2Norm();
    }

David Frank's avatar
David Frank committed
173
174
175
176
177
178
    template <typename data_t>
    GetFloatingPointType_t<data_t> DataContainer<data_t>::l2Norm() const
    {
        return _dataHandler->l2Norm();
    }

Andi Braimllari's avatar
Andi Braimllari committed
179
180
181
182
183
184
    template <typename data_t>
    index_t DataContainer<data_t>::l0PseudoNorm() const
    {
        return _dataHandler->l0PseudoNorm();
    }

Tobias Lasser's avatar
Tobias Lasser committed
185
    template <typename data_t>
186
    GetFloatingPointType_t<data_t> DataContainer<data_t>::l1Norm() const
Tobias Lasser's avatar
Tobias Lasser committed
187
188
189
190
191
    {
        return _dataHandler->l1Norm();
    }

    template <typename data_t>
192
    GetFloatingPointType_t<data_t> DataContainer<data_t>::lInfNorm() const
Tobias Lasser's avatar
Tobias Lasser committed
193
194
    {
        return _dataHandler->lInfNorm();
Tobias Lasser's avatar
Tobias Lasser committed
195
196
    }

Jens Petit's avatar
Jens Petit committed
197
    template <typename data_t>
Tobias Lasser's avatar
Tobias Lasser committed
198
199
200
201
202
    data_t DataContainer<data_t>::sum() const
    {
        return _dataHandler->sum();
    }

203
204
205
206
207
208
209
210
211
212
213
214
    template <typename data_t>
    data_t DataContainer<data_t>::minElement() const
    {
        return _dataHandler->minElement();
    }

    template <typename data_t>
    data_t DataContainer<data_t>::maxElement() const
    {
        return _dataHandler->maxElement();
    }

Jonas Jelten's avatar
Jonas Jelten committed
215
    template <typename data_t>
216
    void DataContainer<data_t>::fft(FFTNorm norm) const
Jonas Jelten's avatar
Jonas Jelten committed
217
    {
218
        this->_dataHandler->fft(*this->_dataDescriptor, norm);
Jonas Jelten's avatar
Jonas Jelten committed
219
220
221
    }

    template <typename data_t>
222
    void DataContainer<data_t>::ifft(FFTNorm norm) const
Jonas Jelten's avatar
Jonas Jelten committed
223
    {
224
        this->_dataHandler->ifft(*this->_dataDescriptor, norm);
Jonas Jelten's avatar
Jonas Jelten committed
225
226
    }

Tobias Lasser's avatar
Tobias Lasser committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator+=(const DataContainer<data_t>& dc)
    {
        *_dataHandler += *dc._dataHandler;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator-=(const DataContainer<data_t>& dc)
    {
        *_dataHandler -= *dc._dataHandler;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator*=(const DataContainer<data_t>& dc)
    {
        *_dataHandler *= *dc._dataHandler;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator/=(const DataContainer<data_t>& dc)
    {
        *_dataHandler /= *dc._dataHandler;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator+=(data_t scalar)
    {
        *_dataHandler += scalar;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator-=(data_t scalar)
    {
        *_dataHandler -= scalar;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator*=(data_t scalar)
    {
        *_dataHandler *= scalar;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator/=(data_t scalar)
    {
        *_dataHandler /= scalar;
        return *this;
    }

    template <typename data_t>
    DataContainer<data_t>& DataContainer<data_t>::operator=(data_t scalar)
    {
        *_dataHandler = scalar;
        return *this;
    }

Jens Petit's avatar
Jens Petit committed
290
291
    template <typename data_t>
    template <typename... Args>
Tobias Lasser's avatar
Tobias Lasser committed
292
    std::unique_ptr<DataHandler<data_t>>
Jens Petit's avatar
Jens Petit committed
293
294
        DataContainer<data_t>::createDataHandler(DataHandlerType handlerType, Args&&... args)
    {
Tobias Lasser's avatar
Tobias Lasser committed
295
296
297
        switch (handlerType) {
            case DataHandlerType::CPU:
                return std::make_unique<DataHandlerCPU<data_t>>(std::forward<Args>(args)...);
Jens Petit's avatar
Jens Petit committed
298
299
            case DataHandlerType::MAP_CPU:
                return std::make_unique<DataHandlerCPU<data_t>>(std::forward<Args>(args)...);
300
301
302
303
304
305
#ifdef ELSA_CUDA_VECTOR
            case DataHandlerType::GPU:
                return std::make_unique<DataHandlerGPU<data_t>>(std::forward<Args>(args)...);
            case DataHandlerType::MAP_GPU:
                return std::make_unique<DataHandlerGPU<data_t>>(std::forward<Args>(args)...);
#endif
Tobias Lasser's avatar
Tobias Lasser committed
306
            default:
307
                throw InvalidArgumentError("DataContainer: unknown handler type");
Tobias Lasser's avatar
Tobias Lasser committed
308
309
310
        }
    }

Jens Petit's avatar
Jens Petit committed
311
312
    template <typename data_t>
    DataContainer<data_t>::DataContainer(const DataDescriptor& dataDescriptor,
Jens Petit's avatar
Jens Petit committed
313
314
315
316
317
                                         std::unique_ptr<DataHandler<data_t>> dataHandler,
                                         DataHandlerType dataType)
        : _dataDescriptor{dataDescriptor.clone()},
          _dataHandler{std::move(dataHandler)},
          _dataHandlerType{dataType}
Tobias Lasser's avatar
Tobias Lasser committed
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    {
    }

    template <typename data_t>
    bool DataContainer<data_t>::operator==(const DataContainer<data_t>& other) const
    {
        if (*_dataDescriptor != *other._dataDescriptor)
            return false;

        if (*_dataHandler != *other._dataHandler)
            return false;

        return true;
    }

    template <typename data_t>
    bool DataContainer<data_t>::operator!=(const DataContainer<data_t>& other) const
    {
        return !(*this == other);
    }

Jens Petit's avatar
Jens Petit committed
339
    template <typename data_t>
340
    DataContainer<data_t> DataContainer<data_t>::getBlock(index_t i)
Jens Petit's avatar
Jens Petit committed
341
    {
342
        const auto blockDesc = downcast_safe<BlockDescriptor>(_dataDescriptor.get());
343
        if (!blockDesc)
344
            throw LogicError("DataContainer: cannot get block from not-blocked container");
345
346

        if (i >= blockDesc->getNumberOfBlocks() || i < 0)
347
            throw InvalidArgumentError("DataContainer: block index out of bounds");
348
349
350
351
352

        index_t startIndex = blockDesc->getOffsetOfBlock(i);
        const auto& ithDesc = blockDesc->getDescriptorOfBlock(i);
        index_t blockSize = ithDesc.getNumberOfCoefficients();

353
354
355
356
357
        DataHandlerType newHandlerType = (_dataHandlerType == DataHandlerType::CPU
                                          || _dataHandlerType == DataHandlerType::MAP_CPU)
                                             ? DataHandlerType::MAP_CPU
                                             : DataHandlerType::MAP_GPU;

Jens Petit's avatar
Jens Petit committed
358
        return DataContainer<data_t>{ithDesc, _dataHandler->getBlock(startIndex, blockSize),
359
                                     newHandlerType};
360
361
362
    }

    template <typename data_t>
363
    const DataContainer<data_t> DataContainer<data_t>::getBlock(index_t i) const
364
    {
365
        const auto blockDesc = downcast_safe<BlockDescriptor>(_dataDescriptor.get());
366
        if (!blockDesc)
367
            throw LogicError("DataContainer: cannot get block from not-blocked container");
368
369

        if (i >= blockDesc->getNumberOfBlocks() || i < 0)
370
            throw InvalidArgumentError("DataContainer: block index out of bounds");
371
372
373
374
375

        index_t startIndex = blockDesc->getOffsetOfBlock(i);
        const auto& ithDesc = blockDesc->getDescriptorOfBlock(i);
        index_t blockSize = ithDesc.getNumberOfCoefficients();

376
377
378
379
380
        DataHandlerType newHandlerType = (_dataHandlerType == DataHandlerType::CPU
                                          || _dataHandlerType == DataHandlerType::MAP_CPU)
                                             ? DataHandlerType::MAP_CPU
                                             : DataHandlerType::MAP_GPU;

381
382
        // getBlock() returns a pointer to non-const DH, but that's fine as it gets wrapped in a
        // constant container
Jens Petit's avatar
Jens Petit committed
383
        return DataContainer<data_t>{ithDesc, _dataHandler->getBlock(startIndex, blockSize),
384
                                     newHandlerType};
385
386
387
388
389
390
    }

    template <typename data_t>
    DataContainer<data_t> DataContainer<data_t>::viewAs(const DataDescriptor& dataDescriptor)
    {
        if (dataDescriptor.getNumberOfCoefficients() != getSize())
391
            throw InvalidArgumentError("DataContainer: view must have same size as container");
392

393
394
395
396
397
        DataHandlerType newHandlerType = (_dataHandlerType == DataHandlerType::CPU
                                          || _dataHandlerType == DataHandlerType::MAP_CPU)
                                             ? DataHandlerType::MAP_CPU
                                             : DataHandlerType::MAP_GPU;

Jens Petit's avatar
Jens Petit committed
398
        return DataContainer<data_t>{dataDescriptor, _dataHandler->getBlock(0, getSize()),
399
                                     newHandlerType};
400
401
402
    }

    template <typename data_t>
403
404
    const DataContainer<data_t>
        DataContainer<data_t>::viewAs(const DataDescriptor& dataDescriptor) const
405
406
    {
        if (dataDescriptor.getNumberOfCoefficients() != getSize())
407
            throw InvalidArgumentError("DataContainer: view must have same size as container");
408

409
410
411
412
413
        DataHandlerType newHandlerType = (_dataHandlerType == DataHandlerType::CPU
                                          || _dataHandlerType == DataHandlerType::MAP_CPU)
                                             ? DataHandlerType::MAP_CPU
                                             : DataHandlerType::MAP_GPU;

414
415
        // getBlock() returns a pointer to non-const DH, but that's fine as it gets wrapped in a
        // constant container
Jens Petit's avatar
Jens Petit committed
416
        return DataContainer<data_t>{dataDescriptor, _dataHandler->getBlock(0, getSize()),
417
                                     newHandlerType};
Jens Petit's avatar
Jens Petit committed
418
419
    }

420
421
422
423
424
425
426
427
428
429
430
    template <typename data_t>
    const DataContainer<data_t> DataContainer<data_t>::slice(index_t i) const
    {
        auto& desc = getDataDescriptor();
        auto dim = desc.getNumberOfDimensions();
        auto sizeOfLastDim = desc.getNumberOfCoefficientsPerDimension()[dim - 1];

        if (i >= sizeOfLastDim) {
            throw LogicError("Trying to access out of bound slice");
        }

431
432
433
434
        if (sizeOfLastDim == 1) {
            return *this;
        }

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
        auto sliceDesc = PartitionDescriptor(desc, sizeOfLastDim);

        // Now set the slice
        return viewAs(sliceDesc).getBlock(i);
    }

    template <typename data_t>
    DataContainer<data_t> DataContainer<data_t>::slice(index_t i)
    {
        auto& desc = getDataDescriptor();
        auto dim = desc.getNumberOfDimensions();
        auto sizeOfLastDim = desc.getNumberOfCoefficientsPerDimension()[dim - 1];

        if (i >= sizeOfLastDim) {
            throw LogicError("Trying to access out of bound slice");
        }

452
453
454
455
        if (sizeOfLastDim == 1) {
            return *this;
        }

456
457
458
459
460
461
        auto sliceDesc = PartitionDescriptor(desc, sizeOfLastDim);

        // Now set the slice
        return viewAs(sliceDesc).getBlock(i);
    }

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
    template <typename data_t>
    typename DataContainer<data_t>::iterator DataContainer<data_t>::begin()
    {
        return iterator(&(*this)[0]);
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_iterator DataContainer<data_t>::begin() const
    {
        return cbegin();
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_iterator DataContainer<data_t>::cbegin() const
    {
        return const_iterator(&(*this)[0]);
    }

    template <typename data_t>
    typename DataContainer<data_t>::iterator DataContainer<data_t>::end()
    {
        return iterator(&(*this)[0] + getSize());
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_iterator DataContainer<data_t>::end() const
    {
        return cend();
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_iterator DataContainer<data_t>::cend() const
    {
        return const_iterator(&(*this)[0] + getSize());
    }

    template <typename data_t>
    typename DataContainer<data_t>::reverse_iterator DataContainer<data_t>::rbegin()
    {
        return reverse_iterator(end());
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_reverse_iterator DataContainer<data_t>::rbegin() const
    {
        return crbegin();
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_reverse_iterator DataContainer<data_t>::crbegin() const
    {
        return const_reverse_iterator(cend());
    }

    template <typename data_t>
    typename DataContainer<data_t>::reverse_iterator DataContainer<data_t>::rend()
    {
        return reverse_iterator(begin());
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_reverse_iterator DataContainer<data_t>::rend() const
    {
        return crend();
    }

    template <typename data_t>
    typename DataContainer<data_t>::const_reverse_iterator DataContainer<data_t>::crend() const
    {
        return const_reverse_iterator(cbegin());
    }

Jens Petit's avatar
Jens Petit committed
534
535
536
537
538
539
    template <typename data_t>
    DataHandlerType DataContainer<data_t>::getDataHandlerType() const
    {
        return _dataHandlerType;
    }

540
    template <typename data_t>
541
    void DataContainer<data_t>::format(std::ostream& os, format_config cfg) const
542
    {
543
        DataContainerFormatter<data_t> fmt{cfg};
544
545
546
        fmt.format(os, *this);
    }

547
548
549
550
551
    template <typename data_t>
    DataContainer<data_t> DataContainer<data_t>::loadToCPU()
    {
        if (_dataHandlerType == DataHandlerType::CPU
            || _dataHandlerType == DataHandlerType::MAP_CPU) {
552
            throw LogicError(
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
                "DataContainer: cannot load data to CPU with already CPU based container");
        }

        DataContainer<data_t> dcCPU(*_dataDescriptor, DataHandlerType::CPU);

        for (index_t i = 0; i < getSize(); i++) {
            dcCPU[i] = this->operator[](i);
        }

        return dcCPU;
    }

    template <typename data_t>
    DataContainer<data_t> DataContainer<data_t>::loadToGPU()
    {
        if (_dataHandlerType == DataHandlerType::GPU
            || _dataHandlerType == DataHandlerType::MAP_GPU) {
570
            throw LogicError(
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
                "DataContainer: cannot load data to GPU with already GPU based container");
        }

        DataContainer<data_t> dcGPU(*_dataDescriptor, DataHandlerType::GPU);

        for (index_t i = 0; i < getSize(); i++) {
            dcGPU[i] = this->operator[](i);
        }

        return dcGPU;
    }

    template <typename data_t>
    bool DataContainer<data_t>::canAssign(DataHandlerType handlerType)
    {
        if (_dataHandlerType == DataHandlerType::CPU
            || _dataHandlerType == DataHandlerType::MAP_CPU) {
            switch (handlerType) {
                case DataHandlerType::CPU:
                    return true;
                    break;
                case DataHandlerType::MAP_CPU:
                    return true;
                    break;
                default:
                    return false;
            }
        } else {
            switch (handlerType) {
                case DataHandlerType::GPU:
                    return true;
                    break;
                case DataHandlerType::MAP_GPU:
                    return true;
                    break;
                default:
                    return false;
            }
        }
    }

612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
    template <typename data_t>
    DataContainer<data_t> concatenate(const DataContainer<data_t>& dc1,
                                      const DataContainer<data_t>& dc2)
    {
        auto desc1 = dc1.getDataDescriptor().clone();
        auto desc2 = dc2.getDataDescriptor().clone();

        if (desc1->getNumberOfDimensions() != desc2->getNumberOfDimensions()) {
            throw LogicError("Can't concatenate two DataContainers with different dimension");
        }

        std::vector<std::unique_ptr<DataDescriptor>> descriptors;
        descriptors.reserve(2);
        descriptors.push_back(std::move(desc1));
        descriptors.push_back(std::move(desc2));

        auto blockDesc = RandomBlocksDescriptor(descriptors);
        auto concatenated = DataContainer<data_t>(blockDesc);

        concatenated.getBlock(0) = dc1;
        concatenated.getBlock(1) = dc2;
        return concatenated;
    }

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
    template <typename data_t>
    DataContainer<data_t> fftShift2D(DataContainer<data_t> dc)
    {
        assert(dc.getDataDescriptor().getNumberOfDimensions() == 2
               && "DataContainer::fftShift2D: currently only supporting 2D signals");

        const DataDescriptor& dataDescriptor = dc.getDataDescriptor();
        IndexVector_t numOfCoeffsPerDim = dataDescriptor.getNumberOfCoefficientsPerDimension();
        index_t m = numOfCoeffsPerDim[0];
        index_t n = numOfCoeffsPerDim[1];

        index_t firstShift = m / 2;
        index_t secondShift = n / 2;

        DataContainer<data_t> copyDC(dataDescriptor);

        for (index_t i = 0; i < m; ++i) {
            for (index_t j = 0; j < n; ++j) {
                copyDC((i + firstShift) % m, (j + secondShift) % n) = dc(i, j);
            }
        }

        return copyDC;
    }

    template <typename data_t>
    DataContainer<data_t> ifftShift2D(DataContainer<data_t> dc)
    {
        assert(dc.getDataDescriptor().getNumberOfDimensions() == 2
               && "DataContainer::ifftShift2D: currently only supporting 2D signals");

        const DataDescriptor& dataDescriptor = dc.getDataDescriptor();
        IndexVector_t numOfCoeffsPerDim = dataDescriptor.getNumberOfCoefficientsPerDimension();
        index_t m = numOfCoeffsPerDim[0];
        index_t n = numOfCoeffsPerDim[1];

        index_t firstShift = -m / 2;
        index_t secondShift = -n / 2;

        DataContainer<data_t> copyDC(dataDescriptor);

        for (index_t i = 0; i < m; ++i) {
            for (index_t j = 0; j < n; ++j) {
                index_t leftIndex = (((i + firstShift) % m) + m) % m;
                index_t rightIndex = (((j + secondShift) % n) + n) % n;
                copyDC(leftIndex, rightIndex) = dc(i, j);
            }
        }

        return copyDC;
    }

Tobias Lasser's avatar
Tobias Lasser committed
688
689
690
    // ------------------------------------------
    // explicit template instantiation
    template class DataContainer<float>;
691
    template class DataContainer<complex<float>>;
Tobias Lasser's avatar
Tobias Lasser committed
692
    template class DataContainer<double>;
693
    template class DataContainer<complex<double>>;
Tobias Lasser's avatar
Tobias Lasser committed
694
695
    template class DataContainer<index_t>;

696
697
698
699
    template DataContainer<float> concatenate<float>(const DataContainer<float>&,
                                                     const DataContainer<float>&);
    template DataContainer<double> concatenate<double>(const DataContainer<double>&,
                                                       const DataContainer<double>&);
700
701
702
703
704
705
    template DataContainer<complex<float>>
        concatenate<complex<float>>(const DataContainer<complex<float>>&,
                                    const DataContainer<complex<float>>&);
    template DataContainer<complex<double>>
        concatenate<complex<double>>(const DataContainer<complex<double>>&,
                                     const DataContainer<complex<double>>&);
706

707
    template DataContainer<float> fftShift2D<float>(DataContainer<float>);
708
709
    template DataContainer<complex<float>>
        fftShift2D<complex<float>>(DataContainer<complex<float>>);
710
    template DataContainer<double> fftShift2D<double>(DataContainer<double>);
711
712
    template DataContainer<complex<double>>
        fftShift2D<complex<double>>(DataContainer<complex<double>>);
713
714

    template DataContainer<float> ifftShift2D<float>(DataContainer<float>);
715
716
    template DataContainer<complex<float>>
        ifftShift2D<complex<float>>(DataContainer<complex<float>>);
717
    template DataContainer<double> ifftShift2D<double>(DataContainer<double>);
718
719
    template DataContainer<complex<double>>
        ifftShift2D<complex<double>>(DataContainer<complex<double>>);
720

Tobias Lasser's avatar
Tobias Lasser committed
721
} // namespace elsa