Skip to content

Commit 74cb1dd

Browse files
committed
Add operators taking Matrix by rvalue reference
1 parent 617c043 commit 74cb1dd

4 files changed

Lines changed: 177 additions & 2 deletions

File tree

ql/math/matrix.hpp

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ namespace QuantLib {
5757
Matrix(const Matrix&);
5858
Matrix(Matrix&&) noexcept;
5959
Matrix(std::initializer_list<std::initializer_list<Real>>);
60+
~Matrix() = default;
6061

6162
Matrix& operator=(const Matrix&);
6263
Matrix& operator=(Matrix&&) noexcept;
@@ -152,16 +153,35 @@ namespace QuantLib {
152153
/*! \relates Matrix */
153154
Matrix operator+(const Matrix&, const Matrix&);
154155
/*! \relates Matrix */
156+
Matrix operator+(const Matrix&, Matrix&&);
157+
/*! \relates Matrix */
158+
Matrix operator+(Matrix&&, const Matrix&);
159+
/*! \relates Matrix */
160+
Matrix operator+(Matrix&&, Matrix&&);
161+
/*! \relates Matrix */
155162
Matrix operator-(const Matrix&);
156163
/*! \relates Matrix */
164+
Matrix operator-(Matrix&&);
165+
/*! \relates Matrix */
157166
Matrix operator-(const Matrix&, const Matrix&);
158167
/*! \relates Matrix */
168+
Matrix operator-(const Matrix&, Matrix&&);
169+
/*! \relates Matrix */
170+
Matrix operator-(Matrix&&, const Matrix&);
171+
/*! \relates Matrix */
172+
Matrix operator-(Matrix&&, Matrix&&);
173+
/*! \relates Matrix */
159174
Matrix operator*(const Matrix&, Real);
160175
/*! \relates Matrix */
176+
Matrix operator*(Matrix&&, Real);
177+
/*! \relates Matrix */
161178
Matrix operator*(Real, const Matrix&);
162179
/*! \relates Matrix */
180+
Matrix operator*(Real, Matrix&&);
181+
/*! \relates Matrix */
163182
Matrix operator/(const Matrix&, Real);
164-
183+
/*! \relates Matrix */
184+
Matrix operator/(Matrix&&, Real);
165185

166186
// vectorial products
167187

@@ -513,12 +533,50 @@ namespace QuantLib {
513533
return temp;
514534
}
515535

536+
inline Matrix operator+(const Matrix& m1, Matrix&& m2) {
537+
QL_REQUIRE(m1.rows() == m2.rows() &&
538+
m1.columns() == m2.columns(),
539+
"matrices with different sizes (" <<
540+
m1.rows() << "x" << m1.columns() << ", " <<
541+
m2.rows() << "x" << m2.columns() << ") cannot be "
542+
"added");
543+
std::transform(m1.begin(), m1.end(), m2.begin(), m2.begin(), std::plus<>());
544+
return std::move(m2);
545+
}
546+
547+
inline Matrix operator+(Matrix&& m1, const Matrix& m2) {
548+
QL_REQUIRE(m1.rows() == m2.rows() &&
549+
m1.columns() == m2.columns(),
550+
"matrices with different sizes (" <<
551+
m1.rows() << "x" << m1.columns() << ", " <<
552+
m2.rows() << "x" << m2.columns() << ") cannot be "
553+
"added");
554+
std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::plus<>());
555+
return std::move(m1);
556+
}
557+
558+
inline Matrix operator+(Matrix&& m1, Matrix&& m2) {
559+
QL_REQUIRE(m1.rows() == m2.rows() &&
560+
m1.columns() == m2.columns(),
561+
"matrices with different sizes (" <<
562+
m1.rows() << "x" << m1.columns() << ", " <<
563+
m2.rows() << "x" << m2.columns() << ") cannot be "
564+
"added");
565+
std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::plus<>());
566+
return std::move(m1);
567+
}
568+
516569
inline Matrix operator-(const Matrix& m1) {
517570
Matrix temp(m1.rows(), m1.columns());
518571
std::transform(m1.begin(), m1.end(), temp.begin(), std::negate<>());
519572
return temp;
520573
}
521574

575+
inline Matrix operator-(Matrix&& m1) {
576+
std::transform(m1.begin(), m1.end(), m1.begin(), std::negate<>());
577+
return std::move(m1);
578+
}
579+
522580
inline Matrix operator-(const Matrix& m1, const Matrix& m2) {
523581
QL_REQUIRE(m1.rows() == m2.rows() &&
524582
m1.columns() == m2.columns(),
@@ -531,24 +589,72 @@ namespace QuantLib {
531589
return temp;
532590
}
533591

592+
inline Matrix operator-(const Matrix& m1, Matrix&& m2) {
593+
QL_REQUIRE(m1.rows() == m2.rows() &&
594+
m1.columns() == m2.columns(),
595+
"matrices with different sizes (" <<
596+
m1.rows() << "x" << m1.columns() << ", " <<
597+
m2.rows() << "x" << m2.columns() << ") cannot be "
598+
"subtracted");
599+
std::transform(m1.begin(), m1.end(), m2.begin(), m2.begin(), std::minus<>());
600+
return std::move(m2);
601+
}
602+
603+
inline Matrix operator-(Matrix&& m1, const Matrix& m2) {
604+
QL_REQUIRE(m1.rows() == m2.rows() &&
605+
m1.columns() == m2.columns(),
606+
"matrices with different sizes (" <<
607+
m1.rows() << "x" << m1.columns() << ", " <<
608+
m2.rows() << "x" << m2.columns() << ") cannot be "
609+
"subtracted");
610+
std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::minus<>());
611+
return std::move(m1);
612+
}
613+
614+
inline Matrix operator-(Matrix&& m1, Matrix&& m2) {
615+
QL_REQUIRE(m1.rows() == m2.rows() &&
616+
m1.columns() == m2.columns(),
617+
"matrices with different sizes (" <<
618+
m1.rows() << "x" << m1.columns() << ", " <<
619+
m2.rows() << "x" << m2.columns() << ") cannot be "
620+
"subtracted");
621+
std::transform(m1.begin(), m1.end(), m2.begin(), m1.begin(), std::minus<>());
622+
return std::move(m1);
623+
}
624+
534625
inline Matrix operator*(const Matrix& m, Real x) {
535626
Matrix temp(m.rows(),m.columns());
536627
std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return y * x; });
537628
return temp;
538629
}
539630

631+
inline Matrix operator*(Matrix&& m, Real x) {
632+
std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return y * x; });
633+
return std::move(m);
634+
}
635+
540636
inline Matrix operator*(Real x, const Matrix& m) {
541637
Matrix temp(m.rows(),m.columns());
542638
std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return x * y; });
543639
return temp;
544640
}
545641

642+
inline Matrix operator*(Real x, Matrix&& m) {
643+
std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return x * y; });
644+
return std::move(m);
645+
}
646+
546647
inline Matrix operator/(const Matrix& m, Real x) {
547648
Matrix temp(m.rows(),m.columns());
548649
std::transform(m.begin(), m.end(), temp.begin(), [=](Real y) -> Real { return y / x; });
549650
return temp;
550651
}
551652

653+
inline Matrix operator/(Matrix&& m, Real x) {
654+
std::transform(m.begin(), m.end(), m.begin(), [=](Real y) -> Real { return y / x; });
655+
return std::move(m);
656+
}
657+
552658
inline Array operator*(const Array& v, const Matrix& m) {
553659
QL_REQUIRE(v.size() == m.rows(),
554660
"vectors and matrices with different sizes ("

test-suite/array.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ void ArrayTest::testArrayOperators() {
322322
const auto real_rvalue_quotient = 1.1 / get_array();
323323

324324
QL_CHECK_CLOSE_ARRAY(lvalue_real_quotient, scalar_quotient_1);
325-
QL_CHECK_CLOSE_ARRAY(lvalue_real_quotient, scalar_quotient_1);
325+
QL_CHECK_CLOSE_ARRAY(rvalue_real_quotient, scalar_quotient_1);
326326
QL_CHECK_CLOSE_ARRAY(real_lvalue_quotient, scalar_quotient_2);
327327
QL_CHECK_CLOSE_ARRAY(real_rvalue_quotient, scalar_quotient_2);
328328
}

test-suite/matrices.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,73 @@ void MatricesTest::testSparseMatrixMemory() {
791791

792792
}
793793

794+
#define QL_CHECK_CLOSE_MATRIX(actual, expected) \
795+
BOOST_REQUIRE(actual.rows() == expected.rows() && \
796+
actual.columns() == expected.columns()); \
797+
for (auto i = 0u; i < actual.rows(); i++) { \
798+
for (auto j = 0u; j < actual.columns(); j++) { \
799+
QL_CHECK_CLOSE(actual(i, j), expected(i, j), 100 * QL_EPSILON); \
800+
} \
801+
} \
802+
803+
void MatricesTest::testOperators() {
804+
805+
BOOST_TEST_MESSAGE("Testing matrix operators...");
806+
807+
auto get_matrix = []() {
808+
return Matrix(2, 3, 4.0);
809+
};
810+
811+
const auto m = get_matrix();
812+
813+
const auto negative = Matrix(2, 3, -4.0);
814+
const auto lvalue_negative = -m;
815+
const auto rvalue_negative = -get_matrix();
816+
817+
QL_CHECK_CLOSE_MATRIX(lvalue_negative, negative);
818+
QL_CHECK_CLOSE_MATRIX(rvalue_negative, negative);
819+
820+
const auto matrix_sum = Matrix(2, 3, 8.0);
821+
const auto lvalue_lvalue_sum = m + m;
822+
const auto lvalue_rvalue_sum = m + get_matrix();
823+
const auto rvalue_lvalue_sum = get_matrix() + m;
824+
const auto rvalue_rvalue_sum = get_matrix() + get_matrix();
825+
826+
QL_CHECK_CLOSE_MATRIX(lvalue_lvalue_sum, matrix_sum);
827+
QL_CHECK_CLOSE_MATRIX(lvalue_rvalue_sum, matrix_sum);
828+
QL_CHECK_CLOSE_MATRIX(rvalue_lvalue_sum, matrix_sum);
829+
QL_CHECK_CLOSE_MATRIX(rvalue_rvalue_sum, matrix_sum);
830+
831+
const auto matrix_difference = Matrix(2, 3, 0.0);
832+
const auto lvalue_lvalue_difference = m - m;
833+
const auto lvalue_rvalue_difference = m - get_matrix();
834+
const auto rvalue_lvalue_difference = get_matrix() - m;
835+
const auto rvalue_rvalue_difference = get_matrix() - get_matrix();
836+
837+
QL_CHECK_CLOSE_MATRIX(lvalue_lvalue_difference, matrix_difference);
838+
QL_CHECK_CLOSE_MATRIX(lvalue_rvalue_difference, matrix_difference);
839+
QL_CHECK_CLOSE_MATRIX(rvalue_lvalue_difference, matrix_difference);
840+
QL_CHECK_CLOSE_MATRIX(rvalue_rvalue_difference, matrix_difference);
841+
842+
const auto scalar_product = Matrix(2, 3, 6.0);
843+
const auto lvalue_real_product = m * 1.5;
844+
const auto rvalue_real_product = get_matrix() * 1.5;
845+
const auto real_lvalue_product = 1.5 * m;
846+
const auto real_rvalue_product = 1.5 * get_matrix();
847+
848+
QL_CHECK_CLOSE_MATRIX(lvalue_real_product, scalar_product);
849+
QL_CHECK_CLOSE_MATRIX(rvalue_real_product, scalar_product);
850+
QL_CHECK_CLOSE_MATRIX(real_lvalue_product, scalar_product);
851+
QL_CHECK_CLOSE_MATRIX(real_rvalue_product, scalar_product);
852+
853+
const auto scalar_quotient = Matrix(2, 3, 2.0);
854+
const auto lvalue_real_quotient = m / 2.0;
855+
const auto rvalue_real_quotient = get_matrix() / 2.0;
856+
857+
QL_CHECK_CLOSE_MATRIX(lvalue_real_quotient, scalar_quotient);
858+
QL_CHECK_CLOSE_MATRIX(rvalue_real_quotient, scalar_quotient);
859+
}
860+
794861
test_suite* MatricesTest::suite() {
795862
auto* suite = BOOST_TEST_SUITE("Matrix tests");
796863

@@ -808,6 +875,7 @@ test_suite* MatricesTest::suite() {
808875
suite->add(QUANTLIB_TEST_CASE(&MatricesTest::testMoorePenroseInverse));
809876
suite->add(QUANTLIB_TEST_CASE(&MatricesTest::testIterativeSolvers));
810877
suite->add(QUANTLIB_TEST_CASE(&MatricesTest::testInitializers));
878+
suite->add(QUANTLIB_TEST_CASE(&MatricesTest::testOperators));
811879
return suite;
812880
}
813881

test-suite/matrices.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class MatricesTest {
4343
static void testIterativeSolvers();
4444
static void testInitializers();
4545
static void testSparseMatrixMemory();
46+
static void testOperators();
4647

4748
static boost::unit_test_framework::test_suite* suite();
4849
};

0 commit comments

Comments
 (0)