26#ifndef quantlib_matrix_hpp
27#define quantlib_matrix_hpp
31#include <initializer_list>
56 template <
class Iterator>
60 Matrix(std::initializer_list<std::initializer_list<Real>>);
66 bool operator==(const
Matrix&) const;
67 bool operator!=(const
Matrix&) const;
205 template <class Iterator1, class Iterator2>
206 Matrix outerProduct(Iterator1 v1begin, Iterator1 v1end, Iterator2 v2begin, Iterator2 v2end);
229 : data_(rows * columns > 0 ? new
Real[rows * columns] : (
Real*)nullptr), rows_(rows),
234 template <
class Iterator>
236 : data_(rows * columns > 0 ? new
Real[rows * columns] : (
Real*)nullptr), rows_(rows),
242 : data_(!from.empty() ? new
Real[from.rows_ * from.columns_] : (
Real*)nullptr),
243 rows_(from.rows_), columns_(from.columns_) {
244 #if defined(QL_PATCH_MSVC) && defined(QL_DEBUG)
251 : data_((
Real*)
nullptr) {
256 : data_(data.size() == 0 || data.begin()->size() == 0 ?
257 (
Real*)nullptr : new
Real[data.size() * data.begin()->size()]),
258 rows_(data.size()), columns_(data.size() == 0 ? 0 : data.begin()->size()) {
260 for (
const auto& row : data) {
261 #if defined(QL_EXTRA_SAFETY_CHECKS)
263 "a matrix needs the same number of elements for each row");
265 std::copy(row.begin(), row.end(),
row_begin(i));
292 data_.swap(from.data_);
293 std::swap(rows_, from.rows_);
294 std::swap(columns_, from.columns_);
299 "matrices with different sizes (" <<
309 "matrices with different sizes (" <<
361 #if defined(QL_EXTRA_SAFETY_CHECKS)
363 "row index (" << i <<
") must be less than " <<
rows_ <<
364 ": matrix cannot be accessed out of range");
370 #if defined(QL_EXTRA_SAFETY_CHECKS)
372 "row index (" << i <<
") must be less than " <<
rows_ <<
373 ": matrix cannot be accessed out of range");
379 #if defined(QL_EXTRA_SAFETY_CHECKS)
381 "row index (" << i <<
") must be less than " <<
rows_ <<
382 ": matrix cannot be accessed out of range");
388 #if defined(QL_EXTRA_SAFETY_CHECKS)
390 "row index (" << i <<
") must be less than " <<
rows_ <<
391 ": matrix cannot be accessed out of range");
416 #if defined(QL_EXTRA_SAFETY_CHECKS)
418 "column index (" << i <<
") must be less than " <<
columns_ <<
419 ": matrix cannot be accessed out of range");
425 #if defined(QL_EXTRA_SAFETY_CHECKS)
427 "column index (" << i <<
") must be less than " <<
columns_ <<
428 ": matrix cannot be accessed out of range");
435 #if defined(QL_EXTRA_SAFETY_CHECKS)
437 "column index (" << i <<
") must be less than " <<
columns_ <<
438 ": matrix cannot be accessed out of range");
444 #if defined(QL_EXTRA_SAFETY_CHECKS)
446 "column index (" << i <<
") must be less than " <<
columns_ <<
447 ": matrix cannot be accessed out of range");
494 Array tmp(arraySize);
495 for(
Size i = 0; i < arraySize; i++)
496 tmp[i] = (*
this)[i][i];
527 "matrices with different sizes (" <<
539 "matrices with different sizes (" <<
541 m2.rows() <<
"x" << m2.columns() <<
") cannot be "
543 std::transform(m1.
begin(), m1.
end(), m2.begin(), m2.begin(), std::plus<>());
544 return std::move(m2);
550 "matrices with different sizes (" <<
551 m1.rows() <<
"x" << m1.columns() <<
", " <<
554 std::transform(m1.begin(), m1.end(), m2.
begin(), m1.begin(), std::plus<>());
555 return std::move(m1);
560 m1.columns() == m2.columns(),
561 "matrices with different sizes (" <<
562 m1.rows() <<
"x" << m1.columns() <<
", " <<
563 m2.rows() <<
"x" << m2.columns() <<
") cannot be "
565 std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::plus<>());
566 return std::move(m1);
571 std::transform(m1.
begin(), m1.
end(), temp.
begin(), std::negate<>());
576 std::transform(m1.begin(), m1.end(), m1.begin(), std::negate<>());
577 return std::move(m1);
583 "matrices with different sizes (" <<
595 "matrices with different sizes (" <<
597 m2.rows() <<
"x" << m2.columns() <<
") cannot be "
599 std::transform(m1.
begin(), m1.
end(), m2.begin(), m2.begin(), std::minus<>());
600 return std::move(m2);
606 "matrices with different sizes (" <<
607 m1.rows() <<
"x" << m1.columns() <<
", " <<
610 std::transform(m1.begin(), m1.end(), m2.
begin(), m1.begin(), std::minus<>());
611 return std::move(m1);
616 m1.columns() == m2.columns(),
617 "matrices with different sizes (" <<
618 m1.rows() <<
"x" << m1.columns() <<
", " <<
619 m2.rows() <<
"x" << m2.columns() <<
") cannot be "
621 std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::minus<>());
622 return std::move(m1);
632 std::transform(m.begin(), m.end(), m.begin(), [=](
Real y) ->
Real { return y * x; });
643 std::transform(m.begin(), m.end(), m.begin(), [=](
Real y) ->
Real { return x * y; });
654 std::transform(m.begin(), m.end(), m.begin(), [=](
Real y) ->
Real { return y / x; });
660 "vectors and matrices with different sizes ("
661 <<
v.size() <<
", " << m.
rows() <<
"x" << m.
columns() <<
662 ") cannot be multiplied");
664 for (
Size i=0; i<result.
size(); i++)
666 std::inner_product(
v.begin(),
v.end(),
673 "vectors and matrices with different sizes ("
674 <<
v.size() <<
", " << m.
rows() <<
"x" << m.
columns() <<
675 ") cannot be multiplied");
677 for (
Size i=0; i<result.
size(); i++)
685 "matrices with different sizes (" <<
690 for (
Size i=0; i<result.
rows(); ++i) {
693 result[i][j] += m1[i][k]*m2[k][j];
702 #if defined(QL_PATCH_MSVC) && defined(QL_DEBUG)
714 template <
class Iterator1,
class Iterator2>
717 Size size1 = std::distance(v1begin, v1end);
720 Size size2 = std::distance(v2begin, v2end);
723 Matrix result(size1, size2);
725 for (
Size i=0; v1begin!=v1end; i++, v1begin++)
726 std::transform(v2begin, v2end, result.
row_begin(i),
727 [=](
Real y) ->
Real { return y * (*v1begin); });
737 std::streamsize width = out.width();
741 out << std::setw(
int(width)) << m[i][j] <<
" ";
1-D array used in linear algebra.
1-D array used in linear algebra.
const_iterator end() const
Size size() const
dimension of the array
const_iterator begin() const
Matrix used in linear algebra.
const Real * const_iterator
std::unique_ptr< Real[]> data_
const_row_iterator row_begin(Size i) const
const Matrix & operator/=(Real)
std::reverse_iterator< row_iterator > reverse_row_iterator
const_reverse_iterator rend() const
Matrix transpose(const Matrix &)
Matrix()
creates a null matrix
const_reverse_row_iterator row_rbegin(Size i) const
const_iterator begin() const
std::reverse_iterator< const_iterator > const_reverse_iterator
const_reverse_column_iterator column_rend(Size i) const
bool operator!=(const Matrix &) const
const Matrix & operator-=(const Matrix &)
std::reverse_iterator< column_iterator > reverse_column_iterator
std::reverse_iterator< const_row_iterator > const_reverse_row_iterator
const_iterator end() const
const_reverse_row_iterator row_rend(Size i) const
const_column_iterator column_begin(Size i) const
Matrix outerProduct(const Array &v1, const Array &v2)
std::reverse_iterator< iterator > reverse_iterator
const_row_iterator row_end(Size i) const
Real & operator()(Size i, Size j) const
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
const_column_iterator column_end(Size i) const
void swap(Matrix &) noexcept
Matrix & operator=(const Matrix &)
const_row_iterator operator[](Size) const
step_iterator< iterator > column_iterator
const_reverse_column_iterator column_rbegin(Size i) const
const_row_iterator at(Size) const
step_iterator< const_iterator > const_column_iterator
const_reverse_iterator rbegin() const
bool operator==(const Matrix &) const
const Matrix & operator*=(Real)
const Matrix & operator+=(const Matrix &)
Real determinant(const Matrix &m)
Matrix inverse(const Matrix &m)
const Real * const_row_iterator
Iterator advancing in constant steps.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
std::size_t Size
size of a container
Quantity operator-(const Quantity &m1, const Quantity &m2)
Quantity operator*(const Quantity &m, Real x)
std::ostream & operator<<(std::ostream &out, GFunctionFactory::YieldCurveModel type)
Quantity operator+(const Quantity &m1, const Quantity &m2)
void swap(Array &v, Array &w) noexcept
Matrix outerProduct(const Array &v1, const Array &v2)
Matrix transpose(const Matrix &m)
Real operator/(const Quantity &m1, const Quantity &m2)
ext::shared_ptr< BlackVolTermStructure > v
Iterator advancing in constant steps.