Coverage Report

Created: 2026-08-14 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/math/matrix.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5
 Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl
6
 Copyright (C) 2003, 2004 Ferdinando Ametrano
7
 Copyright (C) 2015 Michael von den Driesch
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <https://www.quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
/*! \file matrix.hpp
23
    \brief matrix used in linear algebra.
24
*/
25
26
#ifndef quantlib_matrix_hpp
27
#define quantlib_matrix_hpp
28
29
#include <ql/math/array.hpp>
30
#include <ql/utilities/steppingiterator.hpp>
31
#include <initializer_list>
32
#include <iterator>
33
34
namespace QuantLib {
35
36
    //! %Matrix used in linear algebra.
37
    /*! This class implements the concept of Matrix as used in linear
38
        algebra. As such, it is <b>not</b> meant to be used as a
39
        container.
40
    */
41
    class Matrix {
42
      public:
43
        //! \name Constructors, destructor, and assignment
44
        //@{
45
        //! creates a null matrix
46
        Matrix();
47
        //! creates a matrix with the given dimensions
48
        Matrix(Size rows, Size columns);
49
        //! creates the matrix and fills it with <tt>value</tt>
50
        Matrix(Size rows, Size columns, Real value);
51
        //! creates the matrix and fills it with data from a range.
52
        /*! \warning if the range defined by [begin, end) is larger
53
            than the size of the matrix, a memory access violation
54
            might occur.  It is up to the user to avoid this.
55
        */
56
        template <class Iterator>
57
        Matrix(Size rows, Size columns, Iterator begin, Iterator end);
58
        Matrix(const Matrix&);
59
        Matrix(Matrix&&) noexcept;
60
        Matrix(std::initializer_list<std::initializer_list<Real>>);
61
6.49k
        ~Matrix() = default;
62
63
        Matrix& operator=(const Matrix&);
64
        Matrix& operator=(Matrix&&) noexcept;
65
66
        bool operator==(const Matrix&) const;
67
        bool operator!=(const Matrix&) const;
68
        //@}
69
70
        //! \name Algebraic operators
71
        /*! \pre all matrices involved in an algebraic expression must have
72
                 the same size.
73
        */
74
        //@{
75
        const Matrix& operator+=(const Matrix&);
76
        const Matrix& operator-=(const Matrix&);
77
        const Matrix& operator*=(Real);
78
        const Matrix& operator/=(Real);
79
        //@}
80
81
        typedef Real* iterator;
82
        typedef const Real* const_iterator;
83
        typedef std::reverse_iterator<iterator> reverse_iterator;
84
        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
85
        typedef Real* row_iterator;
86
        typedef const Real* const_row_iterator;
87
        typedef std::reverse_iterator<row_iterator> reverse_row_iterator;
88
        typedef std::reverse_iterator<const_row_iterator>
89
                                                const_reverse_row_iterator;
90
        typedef step_iterator<iterator> column_iterator;
91
        typedef step_iterator<const_iterator> const_column_iterator;
92
        typedef std::reverse_iterator<column_iterator>
93
                                                   reverse_column_iterator;
94
        typedef std::reverse_iterator<const_column_iterator>
95
                                             const_reverse_column_iterator;
96
        //! \name Iterator access
97
        //@{
98
        const_iterator begin() const;
99
        iterator begin();
100
        const_iterator end() const;
101
        iterator end();
102
        const_reverse_iterator rbegin() const;
103
        reverse_iterator rbegin();
104
        const_reverse_iterator rend() const;
105
        reverse_iterator rend();
106
        const_row_iterator row_begin(Size i) const;
107
        row_iterator row_begin(Size i);
108
        const_row_iterator row_end(Size i) const;
109
        row_iterator row_end(Size i);
110
        const_reverse_row_iterator row_rbegin(Size i) const;
111
        reverse_row_iterator row_rbegin(Size i);
112
        const_reverse_row_iterator row_rend(Size i) const;
113
        reverse_row_iterator row_rend(Size i);
114
        const_column_iterator column_begin(Size i) const;
115
        column_iterator column_begin(Size i);
116
        const_column_iterator column_end(Size i) const;
117
        column_iterator column_end(Size i);
118
        const_reverse_column_iterator column_rbegin(Size i) const;
119
        reverse_column_iterator column_rbegin(Size i);
120
        const_reverse_column_iterator column_rend(Size i) const;
121
        reverse_column_iterator column_rend(Size i);
122
        //@}
123
124
        //! \name Element access
125
        //@{
126
        const_row_iterator operator[](Size) const;
127
        const_row_iterator at(Size) const;
128
        row_iterator operator[](Size);
129
        row_iterator at(Size);
130
        Array diagonal() const;
131
        const Real& operator()(Size i, Size j) const;
132
        Real& operator()(Size i, Size j);
133
        //@}
134
135
        //! \name Inspectors
136
        //@{
137
        Size rows() const;
138
        Size columns() const;
139
        bool empty() const;
140
        Size size1() const;
141
        Size size2() const;
142
        //@}
143
144
        //! \name Utilities
145
        //@{
146
        void swap(Matrix&) noexcept;
147
        //@}
148
      private:
149
        std::unique_ptr<Real[]> data_;
150
        Size rows_ = 0, columns_ = 0;
151
    };
152
153
    // algebraic operators
154
155
    /*! \relates Matrix */
156
    Matrix operator+(const Matrix&, const Matrix&);
157
    /*! \relates Matrix */
158
    Matrix operator+(const Matrix&, Matrix&&);
159
    /*! \relates Matrix */
160
    Matrix operator+(Matrix&&, const Matrix&);
161
    /*! \relates Matrix */
162
    Matrix operator+(Matrix&&, Matrix&&);
163
    /*! \relates Matrix */
164
    Matrix operator-(const Matrix&);
165
    /*! \relates Matrix */
166
    Matrix operator-(Matrix&&);
167
    /*! \relates Matrix */
168
    Matrix operator-(const Matrix&, const Matrix&);
169
    /*! \relates Matrix */
170
    Matrix operator-(const Matrix&, Matrix&&);
171
    /*! \relates Matrix */
172
    Matrix operator-(Matrix&&, const Matrix&);
173
    /*! \relates Matrix */
174
    Matrix operator-(Matrix&&, Matrix&&);
175
    /*! \relates Matrix */
176
    Matrix operator*(const Matrix&, Real);
177
    /*! \relates Matrix */
178
    Matrix operator*(Matrix&&, Real);
179
    /*! \relates Matrix */
180
    Matrix operator*(Real, const Matrix&);
181
    /*! \relates Matrix */
182
    Matrix operator*(Real, Matrix&&);
183
    /*! \relates Matrix */
184
    Matrix operator/(const Matrix&, Real);
185
    /*! \relates Matrix */
186
    Matrix operator/(Matrix&&, Real);
187
188
    // vectorial products
189
190
    /*! \relates Matrix */
191
    Array operator*(const Array&, const Matrix&);
192
    /*! \relates Matrix */
193
    Array operator*(const Matrix&, const Array&);
194
    /*! \relates Matrix */
195
    Matrix operator*(const Matrix&, const Matrix&);
196
197
    // misc. operations
198
199
    /*! \relates Matrix */
200
    Matrix transpose(const Matrix&);
201
202
    /*! \relates Matrix */
203
    Matrix outerProduct(const Array& v1, const Array& v2);
204
205
    /*! \relates Matrix */
206
    template <class Iterator1, class Iterator2>
207
    Matrix outerProduct(Iterator1 v1begin, Iterator1 v1end, Iterator2 v2begin, Iterator2 v2end);
208
209
    /*! \relates Matrix */
210
    void swap(Matrix&, Matrix&) noexcept;
211
212
    /*! \relates Matrix */
213
    std::ostream& operator<<(std::ostream&, const Matrix&);
214
215
    /*! \relates Matrix */
216
    Matrix inverse(const Matrix& m);
217
218
    /*! \relates Matrix */
219
    Real determinant(const Matrix& m);
220
221
    // inline definitions
222
223
0
    inline Matrix::Matrix() : data_((Real*)nullptr) {}
224
225
    inline Matrix::Matrix(Size rows, Size columns)
226
1.08k
    : data_(rows * columns > 0 ? new Real[rows * columns] : (Real*)nullptr), rows_(rows),
227
1.08k
      columns_(columns) {}
228
229
    inline Matrix::Matrix(Size rows, Size columns, Real value)
230
4.32k
    : data_(rows * columns > 0 ? new Real[rows * columns] : (Real*)nullptr), rows_(rows),
231
4.32k
      columns_(columns) {
232
4.32k
        std::fill(begin(),end(),value);
233
4.32k
    }
234
235
    template <class Iterator>
236
    inline Matrix::Matrix(Size rows, Size columns, Iterator begin, Iterator end)
237
    : data_(rows * columns > 0 ? new Real[rows * columns] : (Real*)nullptr), rows_(rows),
238
      columns_(columns) {
239
        std::copy(begin, end, this->begin());
240
    }
241
242
    inline Matrix::Matrix(const Matrix& from)
243
1.08k
    : data_(!from.empty() ? new Real[from.rows_ * from.columns_] : (Real*)nullptr),
244
1.08k
      rows_(from.rows_), columns_(from.columns_) {
245
        #if defined(QL_PATCH_MSVC) && defined(QL_DEBUG)
246
        if (!from.empty())
247
        #endif
248
1.08k
        std::copy(from.begin(),from.end(),begin());
249
1.08k
    }
250
251
    inline Matrix::Matrix(Matrix&& from) noexcept
252
0
    : data_((Real*)nullptr) {
253
0
        swap(from);
254
0
    }
255
256
    inline Matrix::Matrix(std::initializer_list<std::initializer_list<Real>> data)
257
    : data_(data.size() == 0 || data.begin()->size() == 0 ?
258
            (Real*)nullptr : new Real[data.size() * data.begin()->size()]),
259
      rows_(data.size()), columns_(data.size() == 0 ? 0 : data.begin()->size()) {
260
        Size i=0;
261
        for (const auto& row : data) {
262
            #if defined(QL_EXTRA_SAFETY_CHECKS)
263
            QL_REQUIRE(row.size() == columns_,
264
                       "a matrix needs the same number of elements for each row");
265
            #endif
266
            std::copy(row.begin(), row.end(), row_begin(i));
267
            ++i;
268
        }
269
    }
270
271
0
    inline Matrix& Matrix::operator=(const Matrix& from) {
272
0
        // strong guarantee
273
0
        Matrix temp(from);
274
0
        swap(temp);
275
0
        return *this;
276
0
    }
277
278
1.08k
    inline Matrix& Matrix::operator=(Matrix&& from) noexcept {
279
1.08k
        swap(from);
280
1.08k
        return *this;
281
1.08k
    }
282
283
0
    inline bool Matrix::operator==(const Matrix& to) const {
284
0
        return rows_ == to.rows_ && columns_ == to.columns_ &&
285
0
               std::equal(begin(), end(), to.begin());
286
0
    }
287
288
0
    inline bool Matrix::operator!=(const Matrix& to) const { 
289
0
        return !this->operator==(to); 
290
0
    }
291
292
1.08k
    inline void Matrix::swap(Matrix& from) noexcept {
293
1.08k
        data_.swap(from.data_);
294
1.08k
        std::swap(rows_, from.rows_);
295
1.08k
        std::swap(columns_, from.columns_);
296
1.08k
    }
297
298
0
    inline const Matrix& Matrix::operator+=(const Matrix& m) {
299
0
        QL_REQUIRE(rows_ == m.rows_ && columns_ == m.columns_,
300
0
                   "matrices with different sizes (" <<
301
0
                   m.rows_ << "x" << m.columns_ << ", " <<
302
0
                   rows_ << "x" << columns_ << ") cannot be "
303
0
                   "added");
304
0
        std::transform(begin(), end(), m.begin(), begin(), std::plus<>());
305
0
        return *this;
306
0
    }
Unexecuted instantiation: QuantLib::Matrix::operator+=(QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::Matrix::operator+=(QuantLib::Matrix const&)
307
308
0
    inline const Matrix& Matrix::operator-=(const Matrix& m) {
309
0
        QL_REQUIRE(rows_ == m.rows_ && columns_ == m.columns_,
310
0
                   "matrices with different sizes (" <<
311
0
                   m.rows_ << "x" << m.columns_ << ", " <<
312
0
                   rows_ << "x" << columns_ << ") cannot be "
313
0
                   "subtracted");
314
0
        std::transform(begin(), end(), m.begin(), begin(), std::minus<>());
315
0
        return *this;
316
0
    }
Unexecuted instantiation: QuantLib::Matrix::operator-=(QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::Matrix::operator-=(QuantLib::Matrix const&)
317
318
0
    inline const Matrix& Matrix::operator*=(Real x) {
319
0
        std::transform(begin(), end(), begin(), [=](Real y) -> Real { return y * x; });
320
0
        return *this;
321
0
    }
322
323
0
    inline const Matrix& Matrix::operator/=(Real x) {
324
0
        std::transform(begin(),end(),begin(), [=](Real y) -> Real { return y / x; });
325
0
        return *this;
326
0
    }
327
328
1.08k
    inline Matrix::const_iterator Matrix::begin() const {
329
1.08k
        return data_.get();
330
1.08k
    }
331
332
5.41k
    inline Matrix::iterator Matrix::begin() {
333
5.41k
        return data_.get();
334
5.41k
    }
335
336
1.08k
    inline Matrix::const_iterator Matrix::end() const {
337
1.08k
        return data_.get()+rows_*columns_;
338
1.08k
    }
339
340
4.32k
    inline Matrix::iterator Matrix::end() {
341
4.32k
        return data_.get()+rows_*columns_;
342
4.32k
    }
343
344
0
    inline Matrix::const_reverse_iterator Matrix::rbegin() const {
345
0
        return const_reverse_iterator(end());
346
0
    }
347
348
0
    inline Matrix::reverse_iterator Matrix::rbegin() {
349
0
        return reverse_iterator(end());
350
0
    }
351
352
0
    inline Matrix::const_reverse_iterator Matrix::rend() const {
353
0
        return const_reverse_iterator(begin());
354
0
    }
355
356
0
    inline Matrix::reverse_iterator Matrix::rend() {
357
0
        return reverse_iterator(begin());
358
0
    }
359
360
    inline Matrix::const_row_iterator
361
2.32M
    Matrix::row_begin(Size i) const {
362
        #if defined(QL_EXTRA_SAFETY_CHECKS)
363
        QL_REQUIRE(i<rows_,
364
                   "row index (" << i << ") must be less than " << rows_ <<
365
                   ": matrix cannot be accessed out of range");
366
        #endif
367
2.32M
        return data_.get()+columns_*i;
368
2.32M
    }
369
370
335k
    inline Matrix::row_iterator Matrix::row_begin(Size i) {
371
        #if defined(QL_EXTRA_SAFETY_CHECKS)
372
        QL_REQUIRE(i<rows_,
373
                   "row index (" << i << ") must be less than " << rows_ <<
374
                   ": matrix cannot be accessed out of range");
375
        #endif
376
335k
        return data_.get()+columns_*i;
377
335k
    }
378
379
0
    inline Matrix::const_row_iterator Matrix::row_end(Size i) const{
380
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
381
0
        QL_REQUIRE(i<rows_,
382
0
                   "row index (" << i << ") must be less than " << rows_ <<
383
0
                   ": matrix cannot be accessed out of range");
384
0
        #endif
385
0
        return data_.get()+columns_*(i+1);
386
0
    }
387
388
0
    inline Matrix::row_iterator Matrix::row_end(Size i) {
389
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
390
0
        QL_REQUIRE(i<rows_,
391
0
                   "row index (" << i << ") must be less than " << rows_ <<
392
0
                   ": matrix cannot be accessed out of range");
393
0
        #endif
394
0
        return data_.get()+columns_*(i+1);
395
0
    }
396
397
    inline Matrix::const_reverse_row_iterator
398
0
    Matrix::row_rbegin(Size i) const {
399
0
        return const_reverse_row_iterator(row_end(i));
400
0
    }
401
402
0
    inline Matrix::reverse_row_iterator Matrix::row_rbegin(Size i) {
403
0
        return reverse_row_iterator(row_end(i));
404
0
    }
405
406
    inline Matrix::const_reverse_row_iterator
407
0
    Matrix::row_rend(Size i) const {
408
0
        return const_reverse_row_iterator(row_begin(i));
409
0
    }
410
411
0
    inline Matrix::reverse_row_iterator Matrix::row_rend(Size i) {
412
0
        return reverse_row_iterator(row_begin(i));
413
0
    }
414
415
    inline Matrix::const_column_iterator
416
0
    Matrix::column_begin(Size i) const {
417
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
418
0
        QL_REQUIRE(i<columns_,
419
0
                   "column index (" << i << ") must be less than " << columns_ <<
420
0
                   ": matrix cannot be accessed out of range");
421
0
        #endif
422
0
        return const_column_iterator(data_.get()+i,columns_);
423
0
    }
424
425
3.07k
    inline Matrix::column_iterator Matrix::column_begin(Size i) {
426
        #if defined(QL_EXTRA_SAFETY_CHECKS)
427
        QL_REQUIRE(i<columns_,
428
                   "column index (" << i << ") must be less than " << columns_ <<
429
                   ": matrix cannot be accessed out of range");
430
        #endif
431
3.07k
        return column_iterator(data_.get()+i,columns_);
432
3.07k
    }
433
434
    inline Matrix::const_column_iterator
435
0
    Matrix::column_end(Size i) const {
436
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
437
0
        QL_REQUIRE(i<columns_,
438
0
                   "column index (" << i << ") must be less than " << columns_ <<
439
0
                   ": matrix cannot be accessed out of range");
440
0
        #endif
441
0
        return const_column_iterator(data_.get()+i+rows_*columns_,columns_);
442
0
    }
443
444
3.07k
    inline Matrix::column_iterator Matrix::column_end(Size i) {
445
        #if defined(QL_EXTRA_SAFETY_CHECKS)
446
        QL_REQUIRE(i<columns_,
447
                   "column index (" << i << ") must be less than " << columns_ <<
448
                   ": matrix cannot be accessed out of range");
449
        #endif
450
3.07k
        return column_iterator(data_.get()+i+rows_*columns_,columns_);
451
3.07k
    }
452
453
    inline Matrix::const_reverse_column_iterator
454
0
    Matrix::column_rbegin(Size i) const {
455
0
        return const_reverse_column_iterator(column_end(i));
456
0
    }
457
458
    inline Matrix::reverse_column_iterator
459
0
    Matrix::column_rbegin(Size i) {
460
0
        return reverse_column_iterator(column_end(i));
461
0
    }
462
463
    inline Matrix::const_reverse_column_iterator
464
0
    Matrix::column_rend(Size i) const {
465
0
        return const_reverse_column_iterator(column_begin(i));
466
0
    }
467
468
    inline Matrix::reverse_column_iterator
469
0
    Matrix::column_rend(Size i) {
470
0
        return reverse_column_iterator(column_begin(i));
471
0
    }
472
473
    inline Matrix::const_row_iterator
474
70.9k
    Matrix::operator[](Size i) const {
475
70.9k
        return row_begin(i);
476
70.9k
    }
477
478
    inline Matrix::const_row_iterator
479
0
    Matrix::at(Size i) const {
480
0
        QL_REQUIRE(i < rows_, "matrix access out of range");
481
0
        return row_begin(i);
482
0
    }
483
484
335k
    inline Matrix::row_iterator Matrix::operator[](Size i) {
485
335k
        return row_begin(i);
486
335k
    }
487
488
0
    inline Matrix::row_iterator Matrix::at(Size i) {
489
0
        QL_REQUIRE(i < rows_, "matrix access out of range");
490
0
        return row_begin(i);
491
0
    }
492
493
0
    inline Array Matrix::diagonal() const {
494
0
        Size arraySize = std::min<Size>(rows(), columns());
495
0
        Array tmp(arraySize);
496
0
        for(Size i = 0; i < arraySize; i++)
497
0
            tmp[i] = (*this)[i][i];
498
0
        return tmp;
499
0
    }
500
501
0
    inline const Real& Matrix::operator()(Size i, Size j) const {
502
0
        return data_[i*columns()+j];
503
0
    }
504
505
0
    inline Real& Matrix::operator()(Size i, Size j) {
506
0
        return data_[i*columns()+j];
507
0
    }
508
509
690k
    inline Size Matrix::rows() const {
510
690k
        return rows_;
511
690k
    }
512
513
736k
    inline Size Matrix::columns() const {
514
736k
        return columns_;
515
736k
    }
516
517
0
    inline Size Matrix::size1() const {
518
0
        return rows();
519
0
    }
520
521
0
    inline Size Matrix::size2() const {
522
0
        return columns();
523
0
    }
524
525
1.08k
    inline bool Matrix::empty() const {
526
1.08k
        return rows_ == 0 || columns_ == 0;
527
1.08k
    }
528
529
0
    inline Matrix operator+(const Matrix& m1, const Matrix& m2) {
530
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
531
0
                   m1.columns() == m2.columns(),
532
0
                   "matrices with different sizes (" <<
533
0
                   m1.rows() << "x" << m1.columns() << ", " <<
534
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
535
0
                   "added");
536
0
        Matrix temp(m1.rows(),m1.columns());
537
0
        std::transform(m1.begin(), m1.end(), m2.begin(), temp.begin(), std::plus<>());
538
0
        return temp;
539
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix const&, QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix const&, QuantLib::Matrix const&)
540
541
0
    inline Matrix operator+(const Matrix& m1, Matrix&& m2) {
542
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
543
0
                   m1.columns() == m2.columns(),
544
0
                   "matrices with different sizes (" <<
545
0
                   m1.rows() << "x" << m1.columns() << ", " <<
546
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
547
0
                   "added");
548
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m2.begin(), std::plus<>());
549
0
        return std::move(m2);
550
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix const&, QuantLib::Matrix&&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix const&, QuantLib::Matrix&&)
551
552
0
    inline Matrix operator+(Matrix&& m1, const Matrix& m2) {
553
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
554
0
                   m1.columns() == m2.columns(),
555
0
                   "matrices with different sizes (" <<
556
0
                   m1.rows() << "x" << m1.columns() << ", " <<
557
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
558
0
                   "added");
559
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::plus<>());
560
0
        return std::move(m1);
561
0
    }
562
563
0
    inline Matrix operator+(Matrix&& m1, Matrix&& m2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
564
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
565
0
                   m1.columns() == m2.columns(),
566
0
                   "matrices with different sizes (" <<
567
0
                   m1.rows() << "x" << m1.columns() << ", " <<
568
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
569
0
                   "added");
570
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::plus<>());
571
0
        return std::move(m1);
572
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix&&, QuantLib::Matrix&&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Matrix&&, QuantLib::Matrix&&)
573
574
0
    inline Matrix operator-(const Matrix& m1) {
575
0
        Matrix temp(m1.rows(), m1.columns());
576
0
        std::transform(m1.begin(), m1.end(), temp.begin(), std::negate<>());
577
0
        return temp;
578
0
    }
579
580
0
    inline Matrix operator-(Matrix&& m1) {
581
0
        std::transform(m1.begin(), m1.end(), m1.begin(), std::negate<>());
582
0
        return std::move(m1);
583
0
    }
584
585
0
    inline Matrix operator-(const Matrix& m1, const Matrix& m2) {
586
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
587
0
                   m1.columns() == m2.columns(),
588
0
                   "matrices with different sizes (" <<
589
0
                   m1.rows() << "x" << m1.columns() << ", " <<
590
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
591
0
                   "subtracted");
592
0
        Matrix temp(m1.rows(),m1.columns());
593
0
        std::transform(m1.begin(), m1.end(), m2.begin(), temp.begin(), std::minus<>());
594
0
        return temp;
595
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix const&, QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix const&, QuantLib::Matrix const&)
596
597
0
    inline Matrix operator-(const Matrix& m1, Matrix&& m2) {
598
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
599
0
                   m1.columns() == m2.columns(),
600
0
                   "matrices with different sizes (" <<
601
0
                   m1.rows() << "x" << m1.columns() << ", " <<
602
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
603
0
                   "subtracted");
604
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m2.begin(), std::minus<>());
605
0
        return std::move(m2);
606
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix const&, QuantLib::Matrix&&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix const&, QuantLib::Matrix&&)
607
608
0
    inline Matrix operator-(Matrix&& m1, const Matrix& m2) {
609
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
610
0
                   m1.columns() == m2.columns(),
611
0
                   "matrices with different sizes (" <<
612
0
                   m1.rows() << "x" << m1.columns() << ", " <<
613
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
614
0
                   "subtracted");
615
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::minus<>());
616
0
        return std::move(m1);
617
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix&&, QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Matrix&&, QuantLib::Matrix const&)
618
619
0
    inline Matrix operator-(Matrix&& m1, Matrix&& m2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
620
0
        QL_REQUIRE(m1.rows() == m2.rows() &&
621
0
                   m1.columns() == m2.columns(),
622
0
                   "matrices with different sizes (" <<
623
0
                   m1.rows() << "x" << m1.columns() << ", " <<
624
0
                   m2.rows() << "x" << m2.columns() << ") cannot be "
625
0
                   "subtracted");
626
0
        std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::minus<>());
627
0
        return std::move(m1);
628
0
    }
629
630
0
    inline Matrix operator*(const Matrix& m, Real x) {
631
0
        Matrix temp(m.rows(),m.columns());
632
0
        std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return y * x; });
633
0
        return temp;
634
0
    }
635
636
0
    inline Matrix operator*(Matrix&& m, Real x) {
637
0
        std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return y * x; });
638
0
        return std::move(m);
639
0
    }
640
641
0
    inline Matrix operator*(Real x, const Matrix& m) {
642
0
        Matrix temp(m.rows(),m.columns());
643
0
        std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return x * y; });
644
0
        return temp;
645
0
    }
646
647
0
    inline Matrix operator*(Real x, Matrix&& m) {
648
0
        std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return x * y; });
649
0
        return std::move(m);
650
0
    }
651
652
0
    inline Matrix operator/(const Matrix& m, Real x) {
653
0
        Matrix temp(m.rows(),m.columns());
654
0
        std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return y / x; });
655
0
        return temp;
656
0
    }
657
658
0
    inline Matrix operator/(Matrix&& m, Real x) {
659
0
        std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return y / x; });
660
0
        return std::move(m);
661
0
    }
662
663
0
    inline Array operator*(const Array& v, const Matrix& m) {
664
0
        QL_REQUIRE(v.size() == m.rows(),
665
0
                   "vectors and matrices with different sizes ("
666
0
                   << v.size() << ", " << m.rows() << "x" << m.columns() <<
667
0
                   ") cannot be multiplied");
668
0
        Array result(m.columns());
669
0
        for (Size i=0; i<result.size(); i++)
670
0
            result[i] =
671
0
                std::inner_product(v.begin(),v.end(),
672
0
                                   m.column_begin(i),Real(0.0));
673
0
        return result;
674
0
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Matrix const&)
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Matrix const&)
675
676
674k
    inline Array operator*(const Matrix& m, const Array& v) {
677
674k
        QL_REQUIRE(v.size() == m.columns(),
678
674k
                   "vectors and matrices with different sizes ("
679
674k
                   << v.size() << ", " << m.rows() << "x" << m.columns() <<
680
674k
                   ") cannot be multiplied");
681
674k
        Array result(m.rows());
682
2.92M
        for (Size i=0; i<result.size(); i++)
683
2.25M
            result[i] =
684
2.25M
                std::inner_product(v.begin(),v.end(),m.row_begin(i),Real(0.0));
685
674k
        return result;
686
674k
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Matrix const&, QuantLib::Array const&)
QuantLib::operator*(QuantLib::Matrix const&, QuantLib::Array const&)
Line
Count
Source
676
674k
    inline Array operator*(const Matrix& m, const Array& v) {
677
674k
        QL_REQUIRE(v.size() == m.columns(),
678
674k
                   "vectors and matrices with different sizes ("
679
674k
                   << v.size() << ", " << m.rows() << "x" << m.columns() <<
680
674k
                   ") cannot be multiplied");
681
674k
        Array result(m.rows());
682
2.92M
        for (Size i=0; i<result.size(); i++)
683
2.25M
            result[i] =
684
2.25M
                std::inner_product(v.begin(),v.end(),m.row_begin(i),Real(0.0));
685
674k
        return result;
686
674k
    }
687
688
1.08k
    inline Matrix operator*(const Matrix& m1, const Matrix& m2) {
689
1.08k
        QL_REQUIRE(m1.columns() == m2.rows(),
690
1.08k
                   "matrices with different sizes (" <<
691
1.08k
                   m1.rows() << "x" << m1.columns() << ", " <<
692
1.08k
                   m2.rows() << "x" << m2.columns() << ") cannot be "
693
1.08k
                   "multiplied");
694
1.08k
        Matrix result(m1.rows(),m2.columns(),0.0);
695
4.15k
        for (Size i=0; i<result.rows(); ++i) {
696
12.6k
            for (Size k=0; k<m1.columns(); ++k) {
697
41.9k
                for (Size j=0; j<result.columns(); ++j) {
698
32.4k
                    result[i][j] += m1[i][k]*m2[k][j];
699
32.4k
                }
700
9.58k
            }
701
3.07k
        }
702
1.08k
        return result;
703
1.08k
    }
704
705
0
    inline Matrix transpose(const Matrix& m) {
706
0
        Matrix result(m.columns(),m.rows());
707
0
        #if defined(QL_PATCH_MSVC) && defined(QL_DEBUG)
708
0
        if (!m.empty())
709
0
        #endif
710
0
        for (Size i=0; i<m.rows(); i++)
711
0
            std::copy(m.row_begin(i),m.row_end(i),result.column_begin(i));
712
0
        return result;
713
0
    }
714
715
0
    inline Matrix outerProduct(const Array& v1, const Array& v2) {
716
0
        return outerProduct(v1.begin(), v1.end(), v2.begin(), v2.end());
717
0
    }
718
719
    template <class Iterator1, class Iterator2>
720
0
    inline Matrix outerProduct(Iterator1 v1begin, Iterator1 v1end, Iterator2 v2begin, Iterator2 v2end) {
721
722
0
        Size size1 = std::distance(v1begin, v1end);
723
0
        QL_REQUIRE(size1>0, "null first vector");
724
725
0
        Size size2 = std::distance(v2begin, v2end);
726
0
        QL_REQUIRE(size2>0, "null second vector");
727
728
0
        Matrix result(size1, size2);
729
730
0
        for (Size i=0; v1begin!=v1end; i++, v1begin++)
731
0
            std::transform(v2begin, v2end, result.row_begin(i),
732
0
                           [=](Real y) -> Real { return y * (*v1begin); });
Unexecuted instantiation: QuantLib::outerProduct<double const*, double const*>(double const*, double const*, double const*, double const*)::{lambda(double)#1}::operator()(double) const
Unexecuted instantiation: QuantLib::outerProduct<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >(std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>)::{lambda(double)#1}::operator()(double) const
Unexecuted instantiation: QuantLib::outerProduct<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >(std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>)::{lambda(double)#1}::operator()(double) const
733
734
0
        return result;
735
0
    }
Unexecuted instantiation: QuantLib::Matrix QuantLib::outerProduct<double const*, double const*>(double const*, double const*, double const*, double const*)
Unexecuted instantiation: QuantLib::Matrix QuantLib::outerProduct<double const*, double const*>(double const*, double const*, double const*, double const*)
Unexecuted instantiation: QuantLib::Matrix QuantLib::outerProduct<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >(std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>)
Unexecuted instantiation: QuantLib::Matrix QuantLib::outerProduct<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >(std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>)
736
737
0
    inline void swap(Matrix& m1, Matrix& m2) noexcept {
738
0
        m1.swap(m2);
739
0
    }
740
741
0
    inline std::ostream& operator<<(std::ostream& out, const Matrix& m) {
742
0
        std::streamsize width = out.width();
743
0
        for (Size i=0; i<m.rows(); i++) {
744
0
            out << "| ";
745
0
            for (Size j=0; j<m.columns(); j++)
746
0
                out << std::setw(int(width)) << m[i][j] << " ";
747
0
            out << "|\n";
748
0
        }
749
0
        return out;
750
0
    }
751
752
}
753
754
755
#endif