test_LinearOperator.cpp 16.8 KB
Newer Older
Tobias Lasser's avatar
Tobias Lasser committed
1
/**
2
 * @file test_LinearOperator.cpp
Tobias Lasser's avatar
Tobias Lasser committed
3
 *
4
 * @brief Tests for LinearOperator class
Tobias Lasser's avatar
Tobias Lasser committed
5
 *
6
7
8
 * @author Tobias Lasser - main code
 * @author David Frank - composite tests
 * @author Nikola Dinev - fixes
Tobias Lasser's avatar
Tobias Lasser committed
9
10
 */

11
#include "doctest/doctest.h"
Tobias Lasser's avatar
Tobias Lasser committed
12
#include "LinearOperator.h"
13
#include "VolumeDescriptor.h"
Tobias Lasser's avatar
Tobias Lasser committed
14
15

using namespace elsa;
16
using namespace doctest;
Tobias Lasser's avatar
Tobias Lasser committed
17
18
19

// mock operator, which outputs 1 for apply and 2 for applyAdjoint
template <typename data_t = real_t>
Jens Petit's avatar
Jens Petit committed
20
21
class MockOperator : public LinearOperator<data_t>
{
Tobias Lasser's avatar
Tobias Lasser committed
22
23
public:
    MockOperator(const DataDescriptor& domain, const DataDescriptor& range)
Jens Petit's avatar
Jens Petit committed
24
25
26
        : LinearOperator<data_t>(domain, range)
    {
    }
Tobias Lasser's avatar
Tobias Lasser committed
27
28

protected:
29
30
    void applyImpl([[maybe_unused]] const DataContainer<data_t>& x,
                   DataContainer<data_t>& Ax) const override
Jens Petit's avatar
Jens Petit committed
31
    {
Tobias Lasser's avatar
Tobias Lasser committed
32
33
34
        Ax = 1;
    }

35
36
    void applyAdjointImpl([[maybe_unused]] const DataContainer<data_t>& y,
                          DataContainer<data_t>& Aty) const override
Jens Petit's avatar
Jens Petit committed
37
    {
Tobias Lasser's avatar
Tobias Lasser committed
38
39
40
41
        Aty = 3;
    }

protected:
Jens Petit's avatar
Jens Petit committed
42
43
    MockOperator<data_t>* cloneImpl() const override
    {
Tobias Lasser's avatar
Tobias Lasser committed
44
45
46
47
        return new MockOperator<data_t>(this->getDomainDescriptor(), this->getRangeDescriptor());
    }
};

48
49
50
TYPE_TO_STRING(complex<float>);
TYPE_TO_STRING(complex<double>);

51
52
TEST_SUITE_BEGIN("core");

53
54
TEST_CASE_TEMPLATE("LinearOperator: Testing construction", TestType, float, double, complex<float>,
                   complex<double>)
Jens Petit's avatar
Jens Petit committed
55
56
57
58
59
60
61
{
    GIVEN("DataDescriptors")
    {
        IndexVector_t numCoeff(2);
        numCoeff << 47, 11;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 31, 23;
62
63
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
Tobias Lasser's avatar
Tobias Lasser committed
64

Jens Petit's avatar
Jens Petit committed
65
66
        WHEN("instantiating a LinearOperator")
        {
67
            LinearOperator<TestType> linOp(ddDomain, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
68

Jens Petit's avatar
Jens Petit committed
69
70
            THEN("the DataDescriptors are as expected")
            {
71
72
                REQUIRE_EQ(linOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(linOp.getRangeDescriptor(), ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
73
74
            }

Jens Petit's avatar
Jens Petit committed
75
76
            THEN("the apply* operations throw")
            {
77
                DataContainer<TestType> dc(ddDomain);
78
79
                REQUIRE_THROWS_AS(linOp.apply(dc), LogicError);
                REQUIRE_THROWS_AS(linOp.applyAdjoint(dc), LogicError);
Tobias Lasser's avatar
Tobias Lasser committed
80
81
            }

Jens Petit's avatar
Jens Petit committed
82
83
            THEN("copies are good")
            {
Tobias Lasser's avatar
Tobias Lasser committed
84
                auto newOp = linOp;
85
                REQUIRE_EQ(newOp, linOp);
Tobias Lasser's avatar
Tobias Lasser committed
86
            }
Tobias Lasser's avatar
Tobias Lasser committed
87
88
89
90
        }
    }
}

91
92
TEST_CASE_TEMPLATE("LinearOperator: Testing clone()", TestType, float, double, complex<float>,
                   complex<double>)
Jens Petit's avatar
Jens Petit committed
93
94
95
96
97
98
99
{
    GIVEN("a LinearOperator")
    {
        IndexVector_t numCoeff(3);
        numCoeff << 23, 45, 67;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 78, 90;
100
101
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
102
        LinearOperator<TestType> linOp(ddDomain, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
103

Jens Petit's avatar
Jens Petit committed
104
105
        WHEN("cloning the LinearOperator")
        {
Tobias Lasser's avatar
Tobias Lasser committed
106
107
            auto linOpClone = linOp.clone();

Jens Petit's avatar
Jens Petit committed
108
109
            THEN("everything matches")
            {
110
111
                REQUIRE_NE(linOpClone.get(), &linOp);
                REQUIRE_EQ(*linOpClone, linOp);
Tobias Lasser's avatar
Tobias Lasser committed
112
            }
Tobias Lasser's avatar
Tobias Lasser committed
113

Jens Petit's avatar
Jens Petit committed
114
115
            THEN("copies are also identical")
            {
Tobias Lasser's avatar
Tobias Lasser committed
116
                auto newOp = *linOpClone;
117
                REQUIRE_EQ(newOp, linOp);
Tobias Lasser's avatar
Tobias Lasser committed
118
            }
Tobias Lasser's avatar
Tobias Lasser committed
119
120
        }
    }
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

    GIVEN("a scalar multiplicative composite LinearOperator")
    {
        IndexVector_t numCoeff(3);
        numCoeff << 50, 41, 22;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 4, 88;
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
        LinearOperator<TestType> linOp(ddDomain, ddRange);
        TestType scalar = 42;

        LinearOperator<TestType> scalarMultLinOp = scalar * linOp;

        WHEN("cloning the LinearOperator")
        {
            auto linOpClone = scalarMultLinOp.clone();

            THEN("everything matches")
            {
                REQUIRE_NE(linOpClone.get(), &scalarMultLinOp);
                REQUIRE_EQ(*linOpClone, scalarMultLinOp);
            }

            THEN("copies are also identical")
            {
                auto newOp = *linOpClone;
                REQUIRE_EQ(newOp, scalarMultLinOp);
            }
        }
    }
Tobias Lasser's avatar
Tobias Lasser committed
152
153
}

154
155
TEST_CASE_TEMPLATE("LinearOperator: Testing a leaf LinearOperator", TestType, float, double,
                   complex<float>, complex<double>)
Jens Petit's avatar
Jens Petit committed
156
157
158
159
160
161
162
{
    GIVEN("a non-adjoint leaf linear operator")
    {
        IndexVector_t numCoeff(2);
        numCoeff << 12, 23;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 34, 45;
163
164
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
165
        MockOperator<TestType> mockOp(ddDomain, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
166
167
168

        auto leafOp = leaf(mockOp);

Jens Petit's avatar
Jens Petit committed
169
170
171
172
        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
173
174
                REQUIRE_EQ(leafOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(leafOp.getRangeDescriptor(), ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
175
176
177
            }
        }

Jens Petit's avatar
Jens Petit committed
178
179
        WHEN("given data")
        {
180
181
            DataContainer<TestType> dcDomain(ddDomain);
            DataContainer<TestType> dcRange(ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
182

Jens Petit's avatar
Jens Petit committed
183
184
            THEN("the apply operations return the correct result")
            {
Tobias Lasser's avatar
Tobias Lasser committed
185
186
                auto resultApply = leafOp.apply(dcDomain);
                for (int i = 0; i < resultApply.getSize(); ++i)
187
                    REQUIRE_EQ(resultApply[i], static_cast<TestType>(1));
Tobias Lasser's avatar
Tobias Lasser committed
188
189
190

                auto resultApplyAdjoint = leafOp.applyAdjoint(dcRange);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
191
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<TestType>(3));
Tobias Lasser's avatar
Tobias Lasser committed
192
193
            }

Jens Petit's avatar
Jens Petit committed
194
195
            THEN("the apply operations care for appropriately sized containers")
            {
196
197
                REQUIRE_THROWS_AS(leafOp.apply(dcRange), InvalidArgumentError);
                REQUIRE_THROWS_AS(leafOp.applyAdjoint(dcDomain), InvalidArgumentError);
Tobias Lasser's avatar
Tobias Lasser committed
198
199
200
            }
        }

Jens Petit's avatar
Jens Petit committed
201
202
        WHEN("copying/assigning")
        {
Tobias Lasser's avatar
Tobias Lasser committed
203
204
205
            auto newOp = leafOp;
            auto assignedOp = leaf(newOp);

Jens Petit's avatar
Jens Petit committed
206
207
            THEN("it should be identical")
            {
208
209
                REQUIRE_EQ(newOp, leafOp);
                REQUIRE_EQ(assignedOp, leaf(newOp));
Tobias Lasser's avatar
Tobias Lasser committed
210
211

                assignedOp = newOp;
212
                REQUIRE_EQ(assignedOp, newOp);
Tobias Lasser's avatar
Tobias Lasser committed
213
214
215
216
            }
        }
    }

Jens Petit's avatar
Jens Petit committed
217
218
219
220
221
222
    GIVEN("an adjoint linear operator")
    {
        IndexVector_t numCoeff(2);
        numCoeff << 12, 23;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 34, 45;
223
224
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
225
        MockOperator<TestType> mockOp(ddDomain, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
226
227
228

        auto adjointOp = adjoint(mockOp);

Jens Petit's avatar
Jens Petit committed
229
230
231
232
        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
233
234
                REQUIRE_EQ(adjointOp.getDomainDescriptor(), ddRange);
                REQUIRE_EQ(adjointOp.getRangeDescriptor(), ddDomain);
Tobias Lasser's avatar
Tobias Lasser committed
235
236
237
            }
        }

Jens Petit's avatar
Jens Petit committed
238
239
        WHEN("given data")
        {
240
241
            DataContainer<TestType> dcDomain(ddDomain);
            DataContainer<TestType> dcRange(ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
242

Jens Petit's avatar
Jens Petit committed
243
244
            THEN("the apply operations return the correct result")
            {
Tobias Lasser's avatar
Tobias Lasser committed
245
246
                auto resultApply = adjointOp.apply(dcRange);
                for (int i = 0; i < resultApply.getSize(); ++i)
247
                    REQUIRE_EQ(resultApply[i], static_cast<TestType>(3));
Tobias Lasser's avatar
Tobias Lasser committed
248
249
250

                auto resultApplyAdjoint = adjointOp.applyAdjoint(dcDomain);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
251
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<TestType>(1));
Tobias Lasser's avatar
Tobias Lasser committed
252
253
            }

Jens Petit's avatar
Jens Petit committed
254
255
            THEN("the apply operations care for appropriately sized containers")
            {
256
257
                REQUIRE_THROWS_AS(adjointOp.apply(dcDomain), InvalidArgumentError);
                REQUIRE_THROWS_AS(adjointOp.applyAdjoint(dcRange), InvalidArgumentError);
Tobias Lasser's avatar
Tobias Lasser committed
258
259
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
260

Jens Petit's avatar
Jens Petit committed
261
262
        WHEN("copying/assigning")
        {
Tobias Lasser's avatar
Tobias Lasser committed
263
264
265
            auto newOp = adjointOp;
            auto assignedOp = adjoint(newOp);

Jens Petit's avatar
Jens Petit committed
266
267
            THEN("it should be identical")
            {
268
269
                REQUIRE_EQ(newOp, adjointOp);
                REQUIRE_EQ(assignedOp, adjoint(newOp));
Tobias Lasser's avatar
Tobias Lasser committed
270
271

                assignedOp = newOp;
272
                REQUIRE_EQ(assignedOp, newOp);
Tobias Lasser's avatar
Tobias Lasser committed
273
274
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
275
276
277
    }
}

278
279
TEST_CASE_TEMPLATE("LinearOperator: Testing composite LinearOperator", TestType, float, double,
                   complex<float>, complex<double>)
Jens Petit's avatar
Jens Petit committed
280
281
282
283
284
285
286
{
    GIVEN("an additive composite linear operator")
    {
        IndexVector_t numCoeff(2);
        numCoeff << 45, 67;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 13, 48;
287
288
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
Tobias Lasser's avatar
Tobias Lasser committed
289

290
291
        MockOperator<TestType> op1(ddDomain, ddRange);
        MockOperator<TestType> op2(ddDomain, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
292
293
294

        auto addOp = op1 + op2;

Jens Petit's avatar
Jens Petit committed
295
296
297
298
        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
299
300
                REQUIRE_EQ(addOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(addOp.getRangeDescriptor(), ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
301
302
303
            }
        }

Jens Petit's avatar
Jens Petit committed
304
305
        WHEN("given data")
        {
306
307
            DataContainer<TestType> dcDomain(ddDomain);
            DataContainer<TestType> dcRange(ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
308

Jens Petit's avatar
Jens Petit committed
309
310
            THEN("the apply operations return the correct result")
            {
Tobias Lasser's avatar
Tobias Lasser committed
311
312
                auto resultApply = addOp.apply(dcDomain);
                for (int i = 0; i < resultApply.getSize(); ++i)
313
                    REQUIRE_EQ(resultApply[i], static_cast<TestType>(2));
Tobias Lasser's avatar
Tobias Lasser committed
314
315
316

                auto resultApplyAdjoint = addOp.applyAdjoint(dcRange);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
317
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<TestType>(6));
Tobias Lasser's avatar
Tobias Lasser committed
318
319
            }

Jens Petit's avatar
Jens Petit committed
320
321
            THEN("the apply operations care for appropriately sized containers")
            {
322
323
                REQUIRE_THROWS_AS(addOp.apply(dcRange), InvalidArgumentError);
                REQUIRE_THROWS_AS(addOp.applyAdjoint(dcDomain), InvalidArgumentError);
Tobias Lasser's avatar
Tobias Lasser committed
324
325
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
326

Jens Petit's avatar
Jens Petit committed
327
328
        WHEN("copying/assigning")
        {
Tobias Lasser's avatar
Tobias Lasser committed
329
330
331
            auto newOp = addOp;
            auto assignedOp = adjoint(newOp);

Jens Petit's avatar
Jens Petit committed
332
333
            THEN("it should be identical")
            {
334
335
                REQUIRE_EQ(newOp, addOp);
                REQUIRE_EQ(assignedOp, adjoint(newOp));
Tobias Lasser's avatar
Tobias Lasser committed
336
337

                assignedOp = newOp;
338
                REQUIRE_EQ(assignedOp, newOp);
Tobias Lasser's avatar
Tobias Lasser committed
339
340
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
341
342
    }

Jens Petit's avatar
Jens Petit committed
343
344
345
346
347
348
349
350
    GIVEN("a multiplicative composite linear operator")
    {
        IndexVector_t numCoeff(3);
        numCoeff << 13, 47, 69;
        IndexVector_t numCoeff2(2);
        numCoeff2 << 15, 28;
        IndexVector_t numCoeff3(4);
        numCoeff3 << 7, 30, 83, 13;
351
352
353
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddMiddle(numCoeff2);
        VolumeDescriptor ddRange(numCoeff3);
Tobias Lasser's avatar
Tobias Lasser committed
354

355
356
        MockOperator<TestType> op1(ddDomain, ddMiddle);
        MockOperator<TestType> op2(ddMiddle, ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
357
358
359

        auto multOp = op2 * op1;

Jens Petit's avatar
Jens Petit committed
360
361
362
363
        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
364
365
                REQUIRE_EQ(multOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(multOp.getRangeDescriptor(), ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
366
367
368
            }
        }

Jens Petit's avatar
Jens Petit committed
369
370
        WHEN("given data")
        {
371
372
            DataContainer<TestType> dcDomain(ddDomain);
            DataContainer<TestType> dcRange(ddRange);
Tobias Lasser's avatar
Tobias Lasser committed
373

Jens Petit's avatar
Jens Petit committed
374
375
            THEN("the apply operations return the correct result")
            {
Tobias Lasser's avatar
Tobias Lasser committed
376
377
                auto resultApply = multOp.apply(dcDomain);
                for (int i = 0; i < resultApply.getSize(); ++i)
378
                    REQUIRE_EQ(resultApply[i], static_cast<TestType>(1));
Tobias Lasser's avatar
Tobias Lasser committed
379
380
381

                auto resultApplyAdjoint = multOp.applyAdjoint(dcRange);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
382
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<TestType>(3));
Tobias Lasser's avatar
Tobias Lasser committed
383
384
            }

Jens Petit's avatar
Jens Petit committed
385
386
            THEN("the apply operations care for appropriately sized containers")
            {
387
388
                REQUIRE_THROWS_AS(multOp.apply(dcRange), InvalidArgumentError);
                REQUIRE_THROWS_AS(multOp.applyAdjoint(dcDomain), InvalidArgumentError);
Tobias Lasser's avatar
Tobias Lasser committed
389
390
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
391

Jens Petit's avatar
Jens Petit committed
392
393
        WHEN("copying/assigning")
        {
Tobias Lasser's avatar
Tobias Lasser committed
394
395
396
            auto newOp = multOp;
            auto assignedOp = adjoint(newOp);

Jens Petit's avatar
Jens Petit committed
397
398
            THEN("it should be identical")
            {
399
400
                REQUIRE_EQ(newOp, multOp);
                REQUIRE_EQ(assignedOp, adjoint(newOp));
Tobias Lasser's avatar
Tobias Lasser committed
401
402

                assignedOp = newOp;
403
                REQUIRE_EQ(assignedOp, newOp);
Tobias Lasser's avatar
Tobias Lasser committed
404
405
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
406
407
    }

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
    GIVEN("a scalar multiplicative composite linear operator")
    {
        IndexVector_t numCoeff(3);
        numCoeff << 13, 47, 69;
        IndexVector_t otherNumCoeff(2);
        otherNumCoeff << 15, 28;
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(otherNumCoeff);

        MockOperator op(ddDomain, ddRange);
        real_t scalar = 8;

        auto scalarMultOp = scalar * op;

        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
                REQUIRE_EQ(scalarMultOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(scalarMultOp.getRangeDescriptor(), ddRange);
            }
        }

        WHEN("given data")
        {
            DataContainer dcDomain(ddDomain);
            DataContainer dcRange(ddRange);

            THEN("the apply operations return the correct result")
            {
                auto resultApply = scalarMultOp.apply(dcDomain);
                for (int i = 0; i < resultApply.getSize(); ++i)
                    REQUIRE_EQ(resultApply[i], static_cast<real_t>(8));

                auto resultApplyAdjoint = scalarMultOp.applyAdjoint(dcRange);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<real_t>(24));
            }

            THEN("the apply operations account for appropriately sized containers")
            {
                REQUIRE_THROWS_AS(scalarMultOp.apply(dcRange), InvalidArgumentError);
                REQUIRE_THROWS_AS(scalarMultOp.applyAdjoint(dcDomain), InvalidArgumentError);
            }
        }

        WHEN("copying/assigning")
        {
            const auto& newOp = scalarMultOp;
            auto assignedOp = adjoint(newOp);

            THEN("it should be identical")
            {
                REQUIRE_EQ(newOp, scalarMultOp);
                REQUIRE_EQ(assignedOp, adjoint(newOp));

                assignedOp = newOp;
                REQUIRE_EQ(assignedOp, newOp);
            }
        }
    }

Jens Petit's avatar
Jens Petit committed
470
471
472
473
474
475
476
477
    GIVEN("a complex composite with multiple leafs and levels")
    {
        IndexVector_t numCoeff(2);
        numCoeff << 13, 38;
        IndexVector_t numCoeff2(1);
        numCoeff2 << 16;
        IndexVector_t numCoeff3(3);
        numCoeff3 << 17, 38, 15;
478
479
480
        VolumeDescriptor ddDomain(numCoeff);
        VolumeDescriptor ddRange(numCoeff2);
        VolumeDescriptor ddFinalRange(numCoeff3);
Tobias Lasser's avatar
Tobias Lasser committed
481

482
483
484
        MockOperator<TestType> op1(ddDomain, ddRange);
        MockOperator<TestType> op2(ddFinalRange, ddRange);
        MockOperator<TestType> op3(ddRange, ddFinalRange);
Tobias Lasser's avatar
Tobias Lasser committed
485
486
487

        auto compositeOp = (op3 + adjoint(op2)) * op1;

Jens Petit's avatar
Jens Petit committed
488
489
490
491
        WHEN("the operator is there")
        {
            THEN("the descriptors are set correctly")
            {
492
493
                REQUIRE_EQ(compositeOp.getDomainDescriptor(), ddDomain);
                REQUIRE_EQ(compositeOp.getRangeDescriptor(), ddFinalRange);
Tobias Lasser's avatar
Tobias Lasser committed
494
495
496
            }
        }

Jens Petit's avatar
Jens Petit committed
497
498
        WHEN("given data")
        {
499
500
            DataContainer<TestType> dcDomain(ddDomain);
            DataContainer<TestType> dcFinalRange(ddFinalRange);
Tobias Lasser's avatar
Tobias Lasser committed
501

Jens Petit's avatar
Jens Petit committed
502
503
504
505
            THEN("the apply operations return the correct result")
            {
                auto resultApply = compositeOp.apply(dcDomain);
                for (int i = 0; i < resultApply.getSize(); ++i)
506
                    REQUIRE_EQ(resultApply[i], static_cast<TestType>(4));
Tobias Lasser's avatar
Tobias Lasser committed
507

Jens Petit's avatar
Jens Petit committed
508
509
                auto resultApplyAdjoint = compositeOp.applyAdjoint(dcFinalRange);
                for (int i = 0; i < resultApplyAdjoint.getSize(); ++i)
510
                    REQUIRE_EQ(resultApplyAdjoint[i], static_cast<TestType>(3));
Jens Petit's avatar
Jens Petit committed
511
            }
Tobias Lasser's avatar
Tobias Lasser committed
512

Jens Petit's avatar
Jens Petit committed
513
514
            THEN("the apply operations expect appropriately sized containers")
            {
515
516
                REQUIRE_THROWS_AS(compositeOp.apply(dcFinalRange), InvalidArgumentError);
                REQUIRE_THROWS_AS(compositeOp.applyAdjoint(dcDomain), InvalidArgumentError);
Jens Petit's avatar
Jens Petit committed
517
            }
Tobias Lasser's avatar
Tobias Lasser committed
518
        }
Tobias Lasser's avatar
Tobias Lasser committed
519

Jens Petit's avatar
Jens Petit committed
520
521
        WHEN("copying/assigning")
        {
Tobias Lasser's avatar
Tobias Lasser committed
522
523
524
            auto newOp = compositeOp;
            auto assignedOp = adjoint(newOp);

Jens Petit's avatar
Jens Petit committed
525
526
            THEN("it should be identical")
            {
527
528
                REQUIRE_EQ(newOp, compositeOp);
                REQUIRE_EQ(assignedOp, adjoint(newOp));
Tobias Lasser's avatar
Tobias Lasser committed
529
530

                assignedOp = newOp;
531
                REQUIRE_EQ(assignedOp, newOp);
Tobias Lasser's avatar
Tobias Lasser committed
532
533
            }
        }
Tobias Lasser's avatar
Tobias Lasser committed
534
    }
535
}
536
537

TEST_SUITE_END();