From ec401efb84a8d1379a1455858fa092406c98375d Mon Sep 17 00:00:00 2001 From: Houndie Date: Thu, 29 Jan 2015 11:04:42 -0500 Subject: [PATCH 01/73] Fix typo in fixed_matrix move-assignment The move assignment operator= had an operand of "matrix", which is an undefined type, causing a compile error. Changing the type to "fixed_matrix" solves the problem. Since this is supposed to be a move-assignment operator, I made it take an r-value reference as well, which seems to be the general agreed-upon way to define this operator. This is related to trac bug #10762 --- include/boost/numeric/ublas/matrix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp index d06391077..50bd74b0d 100644 --- a/include/boost/numeric/ublas/matrix.hpp +++ b/include/boost/numeric/ublas/matrix.hpp @@ -1384,7 +1384,7 @@ namespace boost { namespace numeric { /*! @note "pass by value" the key idea to enable move semantics */ BOOST_UBLAS_INLINE - fixed_matrix &operator = (matrix m) { + fixed_matrix &operator = (fixed_matrix && m) { assign_temporary(m); return *this; } From c06ebdb1acca8c8f7245bc97bb84134ddfed9221 Mon Sep 17 00:00:00 2001 From: akumta Date: Tue, 3 Mar 2015 14:28:04 -0800 Subject: [PATCH 02/73] Update test_triangular.cpp Update for ticket#10986 --- test/test_triangular.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/test_triangular.cpp b/test/test_triangular.cpp index 9a9bf48a1..c6cba9134 100644 --- a/test/test_triangular.cpp +++ b/test/test_triangular.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include @@ -17,7 +19,7 @@ double diff(const mat& A, const vec& x, const vec& b) { for (typename vec::size_type i=0; i @@ -45,10 +47,10 @@ int main() { std::cerr << "Constructing..." << std::endl; for (int i=0; i=0) { mat_row_low(i, i-1) = side; } From cd68a7c7e8235c46f64e9ed9de9b7cf0904d2ac4 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 12 Apr 2015 02:03:42 +0200 Subject: [PATCH 03/73] Fixed path name in benchmarks/configuration.pri file (using qmake 5.4). Removed '!' (test for command failure) before 'include' commands. --- IDEs/qtcreator/benchmarks/bench1/bench1.pro | 2 +- IDEs/qtcreator/benchmarks/bench2/bench2.pro | 2 +- IDEs/qtcreator/benchmarks/bench3/bench3.pro | 2 +- IDEs/qtcreator/benchmarks/bench4/bench4.pro | 2 +- IDEs/qtcreator/benchmarks/bench5/bench5.pro | 2 +- IDEs/qtcreator/benchmarks/configuration.pri | 2 +- IDEs/qtcreator/test/begin_end.pro | 2 +- IDEs/qtcreator/test/comp_mat_erase.pro | 2 +- IDEs/qtcreator/test/concepts.pro | 2 +- IDEs/qtcreator/test/num_columns.pro | 2 +- IDEs/qtcreator/test/num_rows.pro | 2 +- IDEs/qtcreator/test/placement_new.pro | 2 +- IDEs/qtcreator/test/size.pro | 2 +- IDEs/qtcreator/test/sparse_view_test.pro | 2 +- IDEs/qtcreator/test/test1.pro | 2 +- IDEs/qtcreator/test/test2.pro | 2 +- IDEs/qtcreator/test/test3.pro | 2 +- IDEs/qtcreator/test/test3_coo.pro | 2 +- IDEs/qtcreator/test/test3_mvov.pro | 2 +- IDEs/qtcreator/test/test4.pro | 2 +- IDEs/qtcreator/test/test5.pro | 2 +- IDEs/qtcreator/test/test6.pro | 2 +- IDEs/qtcreator/test/test7.pro | 2 +- IDEs/qtcreator/test/test_assignment.pro | 2 +- IDEs/qtcreator/test/test_banded_storage_layout.pro | 2 +- IDEs/qtcreator/test/test_complex_norms.pro | 2 +- .../test/test_coordinate_matrix_always_do_full_sort.pro | 2 +- IDEs/qtcreator/test/test_coordinate_matrix_inplace_merge.pro | 2 +- IDEs/qtcreator/test/test_coordinate_matrix_sort.pro | 2 +- IDEs/qtcreator/test/test_coordinate_vector_inplace_merge.pro | 2 +- IDEs/qtcreator/test/test_fixed_containers.pro | 2 +- IDEs/qtcreator/test/test_inplace_solve_basic.pro | 2 +- IDEs/qtcreator/test/test_inplace_solve_mvov.pro | 2 +- IDEs/qtcreator/test/test_inplace_solve_sparse.pro | 2 +- IDEs/qtcreator/test/test_lu.pro | 2 +- IDEs/qtcreator/test/test_matrix_vector.pro | 2 +- IDEs/qtcreator/test/test_ticket7296.pro | 2 +- IDEs/qtcreator/test/test_triangular.pro | 2 +- IDEs/qtcreator/test/triangular_access.pro | 2 +- IDEs/qtcreator/test/triangular_layout.pro | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) diff --git a/IDEs/qtcreator/benchmarks/bench1/bench1.pro b/IDEs/qtcreator/benchmarks/bench1/bench1.pro index 685802b31..c580b766c 100644 --- a/IDEs/qtcreator/benchmarks/bench1/bench1.pro +++ b/IDEs/qtcreator/benchmarks/bench1/bench1.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = bench1 -!include (../configuration.pri) +include (../configuration.pri) OTHER_FILES += \ ../../../../benchmarks/bench1/Jamfile.v2 diff --git a/IDEs/qtcreator/benchmarks/bench2/bench2.pro b/IDEs/qtcreator/benchmarks/bench2/bench2.pro index b667a3fd4..80132f6eb 100644 --- a/IDEs/qtcreator/benchmarks/bench2/bench2.pro +++ b/IDEs/qtcreator/benchmarks/bench2/bench2.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = bench2 -!include (../configuration.pri) +include (../configuration.pri) OTHER_FILES += \ ../../../../benchmarks/bench2/Jamfile.v2 diff --git a/IDEs/qtcreator/benchmarks/bench3/bench3.pro b/IDEs/qtcreator/benchmarks/bench3/bench3.pro index 21f561fc6..256b22056 100644 --- a/IDEs/qtcreator/benchmarks/bench3/bench3.pro +++ b/IDEs/qtcreator/benchmarks/bench3/bench3.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = bench3 -!include (../configuration.pri) +include (../configuration.pri) OTHER_FILES += \ ../../../../benchmarks/bench3/Jamfile.v2 diff --git a/IDEs/qtcreator/benchmarks/bench4/bench4.pro b/IDEs/qtcreator/benchmarks/bench4/bench4.pro index 354bb478b..d1b6f30bf 100644 --- a/IDEs/qtcreator/benchmarks/bench4/bench4.pro +++ b/IDEs/qtcreator/benchmarks/bench4/bench4.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = bench4 -!include (../configuration.pri) +include (../configuration.pri) DEFINES += BOOST_UBLAS_USE_INTERVAL diff --git a/IDEs/qtcreator/benchmarks/bench5/bench5.pro b/IDEs/qtcreator/benchmarks/bench5/bench5.pro index e450911f0..b561cdc6f 100644 --- a/IDEs/qtcreator/benchmarks/bench5/bench5.pro +++ b/IDEs/qtcreator/benchmarks/bench5/bench5.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = bench5 -!include (../configuration.pri) +include (../configuration.pri) DEFINES += BOOST_UBLAS_USE_INTERVAL diff --git a/IDEs/qtcreator/benchmarks/configuration.pri b/IDEs/qtcreator/benchmarks/configuration.pri index 07ffcae1c..d25d7e40a 100644 --- a/IDEs/qtcreator/benchmarks/configuration.pri +++ b/IDEs/qtcreator/benchmarks/configuration.pri @@ -7,7 +7,7 @@ INCLUDEPATH += \ # If ublas tests are build with boost source code then, # then boost headers and boost libraries should be used. -exists(../../../../../../../boost-build.jam) { +exists(../../../../../../boost-build.jam) { INCLUDEPATH += ../../../../../../.. #LIBS += -L../../../../../../../stage/lib } diff --git a/IDEs/qtcreator/test/begin_end.pro b/IDEs/qtcreator/test/begin_end.pro index 03c4c6276..56fc9fbd4 100644 --- a/IDEs/qtcreator/test/begin_end.pro +++ b/IDEs/qtcreator/test/begin_end.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = begin_end -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/comp_mat_erase.pro b/IDEs/qtcreator/test/comp_mat_erase.pro index 63960aefe..d5b766757 100644 --- a/IDEs/qtcreator/test/comp_mat_erase.pro +++ b/IDEs/qtcreator/test/comp_mat_erase.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = comp_mat_erase -!include (configuration.pri) +include (configuration.pri) SOURCES += \ ../../../test/comp_mat_erase.cpp diff --git a/IDEs/qtcreator/test/concepts.pro b/IDEs/qtcreator/test/concepts.pro index c4c0bca9f..b35d7cb75 100644 --- a/IDEs/qtcreator/test/concepts.pro +++ b/IDEs/qtcreator/test/concepts.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = concepts -!include (configuration.pri) +include (configuration.pri) DEFINES += \ EXTERNAL diff --git a/IDEs/qtcreator/test/num_columns.pro b/IDEs/qtcreator/test/num_columns.pro index 8a28199c6..ee1d890dd 100644 --- a/IDEs/qtcreator/test/num_columns.pro +++ b/IDEs/qtcreator/test/num_columns.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = num_columns -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/num_rows.pro b/IDEs/qtcreator/test/num_rows.pro index dc0a22904..9de32bf95 100644 --- a/IDEs/qtcreator/test/num_rows.pro +++ b/IDEs/qtcreator/test/num_rows.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = num_rows -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/placement_new.pro b/IDEs/qtcreator/test/placement_new.pro index d19a74743..11a05cec0 100644 --- a/IDEs/qtcreator/test/placement_new.pro +++ b/IDEs/qtcreator/test/placement_new.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = placement_new -!include (configuration.pri) +include (configuration.pri) SOURCES += \ ../../../test/placement_new.cpp diff --git a/IDEs/qtcreator/test/size.pro b/IDEs/qtcreator/test/size.pro index 59a040334..69aee624e 100644 --- a/IDEs/qtcreator/test/size.pro +++ b/IDEs/qtcreator/test/size.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = size -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/sparse_view_test.pro b/IDEs/qtcreator/test/sparse_view_test.pro index 02b3eb089..0a84afa70 100644 --- a/IDEs/qtcreator/test/sparse_view_test.pro +++ b/IDEs/qtcreator/test/sparse_view_test.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = sparse_view_test -!include (configuration.pri) +include (configuration.pri) SOURCES += \ ../../../test/sparse_view_test.cpp diff --git a/IDEs/qtcreator/test/test1.pro b/IDEs/qtcreator/test/test1.pro index d1123c44e..dae81d57c 100644 --- a/IDEs/qtcreator/test/test1.pro +++ b/IDEs/qtcreator/test/test1.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test1 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test2.pro b/IDEs/qtcreator/test/test2.pro index 00fb53f54..e967a474a 100644 --- a/IDEs/qtcreator/test/test2.pro +++ b/IDEs/qtcreator/test/test2.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test2 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test3.pro b/IDEs/qtcreator/test/test3.pro index f4fd021fa..69d0f4530 100644 --- a/IDEs/qtcreator/test/test3.pro +++ b/IDEs/qtcreator/test/test3.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test3 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET_SPARSE diff --git a/IDEs/qtcreator/test/test3_coo.pro b/IDEs/qtcreator/test/test3_coo.pro index 27e3ca384..4af41c9d1 100644 --- a/IDEs/qtcreator/test/test3_coo.pro +++ b/IDEs/qtcreator/test/test3_coo.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test3_coo -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET_SPARSE_COO diff --git a/IDEs/qtcreator/test/test3_mvov.pro b/IDEs/qtcreator/test/test3_mvov.pro index f0a46dcd2..7009bdb17 100644 --- a/IDEs/qtcreator/test/test3_mvov.pro +++ b/IDEs/qtcreator/test/test3_mvov.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test3_mvov -!include (configuration.pri) +include (configuration.pri) DEFINES += \ USE_FLOAT \ diff --git a/IDEs/qtcreator/test/test4.pro b/IDEs/qtcreator/test/test4.pro index 19da3f872..0072a06a0 100644 --- a/IDEs/qtcreator/test/test4.pro +++ b/IDEs/qtcreator/test/test4.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test4 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test5.pro b/IDEs/qtcreator/test/test5.pro index 3f27384ec..7dfcb5c0b 100644 --- a/IDEs/qtcreator/test/test5.pro +++ b/IDEs/qtcreator/test/test5.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test5 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test6.pro b/IDEs/qtcreator/test/test6.pro index 0664ce454..5721c8a83 100644 --- a/IDEs/qtcreator/test/test6.pro +++ b/IDEs/qtcreator/test/test6.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test6 -!include (configuration.pri) +include (configuration.pri) DEFINES += $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test7.pro b/IDEs/qtcreator/test/test7.pro index 541018492..c34e201c8 100644 --- a/IDEs/qtcreator/test/test7.pro +++ b/IDEs/qtcreator/test/test7.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test7 -!include (configuration.pri) +include (configuration.pri) DEFINES += \ BOOST_UBLAS_USE_INTERVAL \ diff --git a/IDEs/qtcreator/test/test_assignment.pro b/IDEs/qtcreator/test/test_assignment.pro index 1ad6ca391..1956d82fc 100644 --- a/IDEs/qtcreator/test/test_assignment.pro +++ b/IDEs/qtcreator/test/test_assignment.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_assignment -!include (configuration.pri) +include (configuration.pri) DEFINES += \ BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT diff --git a/IDEs/qtcreator/test/test_banded_storage_layout.pro b/IDEs/qtcreator/test/test_banded_storage_layout.pro index 78a96dc42..3cd992cf8 100644 --- a/IDEs/qtcreator/test/test_banded_storage_layout.pro +++ b/IDEs/qtcreator/test/test_banded_storage_layout.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_banded_storage_layout -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_complex_norms.pro b/IDEs/qtcreator/test/test_complex_norms.pro index e7c431e4a..3bc6ae59b 100644 --- a/IDEs/qtcreator/test/test_complex_norms.pro +++ b/IDEs/qtcreator/test/test_complex_norms.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_complex_norms -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_coordinate_matrix_always_do_full_sort.pro b/IDEs/qtcreator/test/test_coordinate_matrix_always_do_full_sort.pro index 0c93dd04b..ef1ece33a 100644 --- a/IDEs/qtcreator/test/test_coordinate_matrix_always_do_full_sort.pro +++ b/IDEs/qtcreator/test/test_coordinate_matrix_always_do_full_sort.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_coordinate_matrix_always_do_full_sort -!include (configuration.pri) +include (configuration.pri) DEFINES += \ BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT diff --git a/IDEs/qtcreator/test/test_coordinate_matrix_inplace_merge.pro b/IDEs/qtcreator/test/test_coordinate_matrix_inplace_merge.pro index 0dee5eb39..c1b790116 100644 --- a/IDEs/qtcreator/test/test_coordinate_matrix_inplace_merge.pro +++ b/IDEs/qtcreator/test/test_coordinate_matrix_inplace_merge.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_coordinate_matrix_inplace_merge -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_coordinate_matrix_sort.pro b/IDEs/qtcreator/test/test_coordinate_matrix_sort.pro index ea94561d1..ba109cf1e 100644 --- a/IDEs/qtcreator/test/test_coordinate_matrix_sort.pro +++ b/IDEs/qtcreator/test/test_coordinate_matrix_sort.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_coordinate_matrix_sort -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_coordinate_vector_inplace_merge.pro b/IDEs/qtcreator/test/test_coordinate_vector_inplace_merge.pro index a86ce2aeb..c1b4e9a7d 100644 --- a/IDEs/qtcreator/test/test_coordinate_vector_inplace_merge.pro +++ b/IDEs/qtcreator/test/test_coordinate_vector_inplace_merge.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_coordinate_vector_inplace_merge -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_fixed_containers.pro b/IDEs/qtcreator/test/test_fixed_containers.pro index 60127482f..bb7910546 100644 --- a/IDEs/qtcreator/test/test_fixed_containers.pro +++ b/IDEs/qtcreator/test/test_fixed_containers.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_fixed_containers -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_inplace_solve_basic.pro b/IDEs/qtcreator/test/test_inplace_solve_basic.pro index 42bc3db6f..c13f6af1d 100644 --- a/IDEs/qtcreator/test/test_inplace_solve_basic.pro +++ b/IDEs/qtcreator/test/test_inplace_solve_basic.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_inplace_solve_basic -!include (configuration.pri) +include (configuration.pri) DEFINES += \ $$UBLAS_TESTSET diff --git a/IDEs/qtcreator/test/test_inplace_solve_mvov.pro b/IDEs/qtcreator/test/test_inplace_solve_mvov.pro index a1d1316d6..3f3870e5d 100644 --- a/IDEs/qtcreator/test/test_inplace_solve_mvov.pro +++ b/IDEs/qtcreator/test/test_inplace_solve_mvov.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_inplace_solve_mvov -!include (configuration.pri) +include (configuration.pri) DEFINES += \ USE_MAPPED_VECTOR_OF_MAPPED_VECTOR diff --git a/IDEs/qtcreator/test/test_inplace_solve_sparse.pro b/IDEs/qtcreator/test/test_inplace_solve_sparse.pro index 9f9a32a09..47ebeffe4 100644 --- a/IDEs/qtcreator/test/test_inplace_solve_sparse.pro +++ b/IDEs/qtcreator/test/test_inplace_solve_sparse.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_inplace_solve_sparse -!include (configuration.pri) +include (configuration.pri) DEFINES += \ $$UBLAS_TESTSET_SPARSE \ diff --git a/IDEs/qtcreator/test/test_lu.pro b/IDEs/qtcreator/test/test_lu.pro index 0f2033971..c44e45875 100644 --- a/IDEs/qtcreator/test/test_lu.pro +++ b/IDEs/qtcreator/test/test_lu.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_lu -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/common/testhelper.hpp diff --git a/IDEs/qtcreator/test/test_matrix_vector.pro b/IDEs/qtcreator/test/test_matrix_vector.pro index d61b70bfb..f8fd541e9 100644 --- a/IDEs/qtcreator/test/test_matrix_vector.pro +++ b/IDEs/qtcreator/test/test_matrix_vector.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_matrix_vector -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_ticket7296.pro b/IDEs/qtcreator/test/test_ticket7296.pro index 98752cf75..b57af941d 100644 --- a/IDEs/qtcreator/test/test_ticket7296.pro +++ b/IDEs/qtcreator/test/test_ticket7296.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_ticket7296 -!include (configuration.pri) +include (configuration.pri) HEADERS += \ ../../../test/utils.hpp diff --git a/IDEs/qtcreator/test/test_triangular.pro b/IDEs/qtcreator/test/test_triangular.pro index 15c8ce110..734c985de 100644 --- a/IDEs/qtcreator/test/test_triangular.pro +++ b/IDEs/qtcreator/test/test_triangular.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = test_triangular -!include (configuration.pri) +include (configuration.pri) DEFINES += \ BOOST_CHRONO_DYN_LINK=1 \ diff --git a/IDEs/qtcreator/test/triangular_access.pro b/IDEs/qtcreator/test/triangular_access.pro index 98a87063b..ac6da4ff3 100644 --- a/IDEs/qtcreator/test/triangular_access.pro +++ b/IDEs/qtcreator/test/triangular_access.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = triangular_access -!include (configuration.pri) +include (configuration.pri) DEFINES += NOMESSAGES diff --git a/IDEs/qtcreator/test/triangular_layout.pro b/IDEs/qtcreator/test/triangular_layout.pro index dcfd36f6f..1a16842e5 100644 --- a/IDEs/qtcreator/test/triangular_layout.pro +++ b/IDEs/qtcreator/test/triangular_layout.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = triangular_layout -!include (configuration.pri) +include (configuration.pri) SOURCES += \ ../../../test/triangular_layout.cpp From 55af5c2bae1b969da241548b92aeb71895a2f835 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 13 Apr 2015 02:51:10 +0200 Subject: [PATCH 04/73] Prefix enable_if and disable_if with boost namespace. This is a workaround for msvc-8.0 - ambiguous symbols reported when uBlas and Boost.Test are used together. --- include/boost/numeric/ublas/detail/returntype_deduction.hpp | 4 ++-- include/boost/numeric/ublas/matrix_expression.hpp | 6 +++--- include/boost/numeric/ublas/vector_expression.hpp | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/boost/numeric/ublas/detail/returntype_deduction.hpp b/include/boost/numeric/ublas/detail/returntype_deduction.hpp index 030d1f6b2..6ef1f0be0 100644 --- a/include/boost/numeric/ublas/detail/returntype_deduction.hpp +++ b/include/boost/numeric/ublas/detail/returntype_deduction.hpp @@ -126,13 +126,13 @@ struct error_cant_deduce_type {}; test(unsigned long const&); template - typename disable_if< + typename boost::disable_if< is_basic, x_value_type >::type test(X const&); template - typename disable_if< + typename boost::disable_if< mpl::or_< is_basic , is_same diff --git a/include/boost/numeric/ublas/matrix_expression.hpp b/include/boost/numeric/ublas/matrix_expression.hpp index a36313096..52a944596 100644 --- a/include/boost/numeric/ublas/matrix_expression.hpp +++ b/include/boost/numeric/ublas/matrix_expression.hpp @@ -3411,7 +3411,7 @@ namespace boost { namespace numeric { namespace ublas { // (t * m) [i] [j] = t * m [i] [j] template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename matrix_binary_scalar1_traits >::result_type >::type operator * (const T1 &e1, @@ -3934,7 +3934,7 @@ namespace boost { namespace numeric { namespace ublas { // (m * t) [i] [j] = m [i] [j] * t template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename matrix_binary_scalar2_traits >::result_type >::type operator * (const matrix_expression &e1, @@ -3946,7 +3946,7 @@ namespace boost { namespace numeric { namespace ublas { // (m / t) [i] [j] = m [i] [j] / t template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename matrix_binary_scalar2_traits >::result_type >::type operator / (const matrix_expression &e1, diff --git a/include/boost/numeric/ublas/vector_expression.hpp b/include/boost/numeric/ublas/vector_expression.hpp index aebb403b6..b35222ee8 100644 --- a/include/boost/numeric/ublas/vector_expression.hpp +++ b/include/boost/numeric/ublas/vector_expression.hpp @@ -1235,7 +1235,7 @@ namespace boost { namespace numeric { namespace ublas { // (t * v) [i] = t * v [i] template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename vector_binary_scalar1_traits >::result_type >::type operator * (const T1 &e1, @@ -1478,7 +1478,7 @@ namespace boost { namespace numeric { namespace ublas { // (v * t) [i] = v [i] * t template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename vector_binary_scalar2_traits >::result_type >::type operator * (const vector_expression &e1, @@ -1490,7 +1490,7 @@ namespace boost { namespace numeric { namespace ublas { // (v / t) [i] = v [i] / t template BOOST_UBLAS_INLINE - typename enable_if< is_convertible, + typename boost::enable_if< is_convertible, typename vector_binary_scalar2_traits >::result_type >::type operator / (const vector_expression &e1, From 0e9a3ed022933687d3b00422e723589a0db526df Mon Sep 17 00:00:00 2001 From: Houndie Date: Mon, 20 Apr 2015 10:44:15 -0400 Subject: [PATCH 05/73] Fix typo in fixed_matrix move assignment This is a fix for trac ticket #10762 There was a typo in the move assignment operator, which causes any program #include-ing this file to fail if BOOST_UBLAS_MOVE_SEMANTICS is active. --- include/boost/numeric/ublas/matrix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp index d06391077..aeaa3bb7a 100644 --- a/include/boost/numeric/ublas/matrix.hpp +++ b/include/boost/numeric/ublas/matrix.hpp @@ -1384,7 +1384,7 @@ namespace boost { namespace numeric { /*! @note "pass by value" the key idea to enable move semantics */ BOOST_UBLAS_INLINE - fixed_matrix &operator = (matrix m) { + fixed_matrix &operator = (fixed_matrix m) { assign_temporary(m); return *this; } From 78eecc8bbf035c01316647839be4094748f8e77d Mon Sep 17 00:00:00 2001 From: v4hn Date: Tue, 28 Apr 2015 22:28:52 +0200 Subject: [PATCH 06/73] "template inline" instead of "inline template" This is similar to 19eb8cf30af812c8434dfc7e5f0c6c7ded5477d0 and the header can't be used without this fix. --- include/boost/numeric/ublas/storage.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index 8821309dd..bd648925a 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -777,8 +777,8 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE shallow_array_adaptor (size_type size, pointer data): size_ (size), own_ (false), data_ (data, leaker ()) {} - BOOST_UBLAS_INLINE template + BOOST_UBLAS_INLINE shallow_array_adaptor (T (&data)[N]): size_ (N), own_ (false), data_ (data, leaker ()) {} @@ -833,13 +833,13 @@ namespace boost { namespace numeric { namespace ublas { void resize (size_type size, pointer data, value_type init) { resize_internal (size, data, init, true); } - BOOST_UBLAS_INLINE template + BOOST_UBLAS_INLINE void resize (T (&data)[N]) { resize_internal (N, data, value_type (), false); } - BOOST_UBLAS_INLINE template + BOOST_UBLAS_INLINE void resize (T (&data)[N], value_type init) { resize_internal (N, data, init, true); } From 46ce9f4265a830ad60f7ae0e98aa28716b8cb449 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 24 May 2015 02:39:08 +0200 Subject: [PATCH 07/73] Simplified string concatenation in test_fixed_containers.cpp. --- test/test_fixed_containers.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/test_fixed_containers.cpp b/test/test_fixed_containers.cpp index 23a63827e..0cc0b8be1 100644 --- a/test/test_fixed_containers.cpp +++ b/test/test_fixed_containers.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include "utils.hpp" @@ -20,9 +19,7 @@ using std::endl; template < class T > bool test_vector( std::string type_name) { - std::stringstream stream; - stream << "Testing for: " << type_name; - BOOST_UBLAS_DEBUG_TRACE( stream.str() ); + BOOST_UBLAS_DEBUG_TRACE( std::string("Testing for: ") + type_name ); bool pass = true; @@ -155,9 +152,7 @@ bool test_vector( std::string type_name) template < class T > bool test_matrix( std::string type_name) { - std::stringstream stream; - stream << "Testing for: " << type_name; - BOOST_UBLAS_DEBUG_TRACE( stream.str() ); + BOOST_UBLAS_DEBUG_TRACE( std::string("Testing for: ") + type_name ); bool pass = true; From be950046998ad32b35f5b3873f009bcbc0fd5c0f Mon Sep 17 00:00:00 2001 From: Nasos Date: Fri, 7 Aug 2015 23:10:55 -0400 Subject: [PATCH 08/73] Corrected some merge trash A merge contained some diff file information. --- include/boost/numeric/ublas/matrix.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp index 31d82ee11..aeaa3bb7a 100644 --- a/include/boost/numeric/ublas/matrix.hpp +++ b/include/boost/numeric/ublas/matrix.hpp @@ -1384,11 +1384,7 @@ namespace boost { namespace numeric { /*! @note "pass by value" the key idea to enable move semantics */ BOOST_UBLAS_INLINE -<<<<<<< HEAD - fixed_matrix &operator = (fixed_matrix && m) { -======= fixed_matrix &operator = (fixed_matrix m) { ->>>>>>> c3c4862d86aeedd9586aca5fb017754c9eb05c69 assign_temporary(m); return *this; } From 0aad284672bf99f94dd093767df5b28f237616ae Mon Sep 17 00:00:00 2001 From: qduran Date: Sat, 8 Aug 2015 15:31:09 +0200 Subject: [PATCH 09/73] Typecast the calculation of mean square distance to avoid warnings (funcion mean_square for matrices and vectors). --- test/common/testhelper.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/common/testhelper.hpp b/test/common/testhelper.hpp index b554511fa..2eb6df73e 100644 --- a/test/common/testhelper.hpp +++ b/test/common/testhelper.hpp @@ -94,7 +94,7 @@ typename AE::value_type mean_square(const boost::numeric::ublas::matrix_expressi s += boost::numeric::ublas::scalar_traits::type_abs(me()(i,j)); } } - return s / (me().size1() * me().size2()); + return static_cast(s / (me().size1() * me().size2())); } template @@ -105,7 +105,7 @@ typename AE::value_type mean_square(const boost::numeric::ublas::vector_expressi for (i=0; i!= ve().size(); i++) { s += boost::numeric::ublas::scalar_traits::type_abs(ve()(i)); } - return s / ve().size(); + return static_cast(s / ve().size()); } template < class M1, class M2 > From 74cc99a4bdab9cfdc9c491cd468711be8e674f36 Mon Sep 17 00:00:00 2001 From: qduran Date: Sat, 8 Aug 2015 15:53:58 +0200 Subject: [PATCH 10/73] 'compare_to' function has been renamed to 'compare_distance'. --- test/common/testhelper.hpp | 12 +- test/test_assignment.cpp | 112 +++++++++--------- test/test_coordinate_matrix_inplace_merge.cpp | 6 +- test/test_coordinate_vector_inplace_merge.cpp | 6 +- test/test_matrix_vector.cpp | 28 ++--- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/test/common/testhelper.hpp b/test/common/testhelper.hpp index 2eb6df73e..6dadbf2af 100644 --- a/test/common/testhelper.hpp +++ b/test/common/testhelper.hpp @@ -109,9 +109,9 @@ typename AE::value_type mean_square(const boost::numeric::ublas::vector_expressi } template < class M1, class M2 > -bool compare_to( const boost::numeric::ublas::matrix_expression & m1, - const boost::numeric::ublas::matrix_expression & m2, - double tolerance = 0.0 ) { +bool compare_distance( const boost::numeric::ublas::matrix_expression & m1, + const boost::numeric::ublas::matrix_expression & m2, + double tolerance = 0.0 ) { if ((m1().size1() != m2().size1()) || (m1().size2() != m2().size2())) { return false; @@ -121,9 +121,9 @@ bool compare_to( const boost::numeric::ublas::matrix_expression & m1, } template < class M1, class M2 > -bool compare_to( const boost::numeric::ublas::vector_expression & m1, - const boost::numeric::ublas::vector_expression & m2, - double tolerance = 0.0 ) { +bool compare_distance( const boost::numeric::ublas::vector_expression & m1, + const boost::numeric::ublas::vector_expression & m2, + double tolerance = 0.0 ) { if (m1().size() != m2().size()) { return false; } diff --git a/test/test_assignment.cpp b/test/test_assignment.cpp index c402ac2f8..613023f8c 100644 --- a/test/test_assignment.cpp +++ b/test/test_assignment.cpp @@ -27,35 +27,35 @@ bool test_vector() { V a(3), ra(3); a <<= 1, 2, 3; ra(0) = 1; ra(1) = 2; ra(2) = 3; - pass &= compare_to(a, ra); + pass &= compare_distance(a, ra); V b(7), rb(7); b<<= a, 10, a; rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; - pass &= compare_to(b, rb); + pass &= compare_distance(b, rb); { V c(6), rc(6); c <<= 1, move(2), 3 ,4, 5, move(-5), 10, 10; rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; - pass &= compare_to(c, rc); + pass &= compare_distance(c, rc); V d(6), rd(6); d <<= 1, move_to(3), 3 ,4, 5, move_to(1), 10, 10; rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; - pass &= compare_to(d, rd); + pass &= compare_distance(d, rd); } { V c(6), rc(6); c <<= 1, move<2>(), 3 ,4, 5, move<-5>(), 10, 10; rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; - pass &= compare_to(c, rc); + pass &= compare_distance(c, rc); V d(6), rd(6); d <<= 1, move_to<3>(), 3 ,4, 5, move_to<1>(), 10, 10; rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; - pass &= compare_to(d, rd); + pass &= compare_distance(d, rd); } @@ -65,7 +65,7 @@ bool test_vector() { V fa(3); fa<<= 1, 2, 3; f <<= fill_policy::index_plus_assign(), fa; rf <<= 6,7,8, 5, 5, 5; - pass &= compare_to(f, rf); + pass &= compare_distance(f, rf); } { @@ -74,7 +74,7 @@ bool test_vector() { V fa(3); fa<<= 1, 2, 3; f <<= fill_policy::index_minus_assign(), fa; rf <<= 4,3,2, 5, 5, 5; - pass &= compare_to(f, rf); + pass &= compare_distance(f, rf); } return pass; @@ -87,27 +87,27 @@ bool test_vector_sparse_push_back() { V a(3), ra(3); a <<= fill_policy::sparse_push_back(), 1, 2, 3; ra(0) = 1; ra(1) = 2; ra(2) = 3; - pass &= compare_to(a, ra); + pass &= compare_distance(a, ra); V b(7), rb(7); b<<= fill_policy::sparse_push_back(), a, 10, a; rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; - pass &= compare_to(b, rb); + pass &= compare_distance(b, rb); V c(6), rc(6); c <<= fill_policy::sparse_push_back(), 1, move(2), 3 ,4, 5; // Move back (i.e. negative is dangerous for push_back) rc(0) = 1; rc(1) = 0; rc(2) = 0; rc(3) = 3; rc(4) = 4; rc(5) = 5; - pass &= compare_to(c, rc); + pass &= compare_distance(c, rc); V d(6), rd(6); d <<= fill_policy::sparse_push_back(), 1, move_to(3), 3 ,4, 5; // Move back (i.e. before current index is dangerous for push_back) rd(0) = 1; rd(1) = 0; rd(2) = 0; rd(3) = 3; rd(4) = 4; rd(5) = 5; - pass &= compare_to(d, rd); + pass &= compare_distance(d, rd); V e(6), re(6); e <<= fill_policy::sparse_push_back(), 1, move_to(3), 3 ,4, 5, fill_policy::sparse_insert(), move_to(1), 10, 10; // If you want to move back, use this re(0) = 1; re(1) = 10; re(2) = 10; re(3) = 3; re(4) = 4; re(5) = 5; - pass &= compare_to(e, re); + pass &= compare_distance(e, re); return pass; } @@ -120,23 +120,23 @@ bool test_vector_sparse_insert() { V a(3), ra(3); a <<= fill_policy::sparse_insert(), 1, 2, 3; ra(0) = 1; ra(1) = 2; ra(2) = 3; - pass &= compare_to(a, ra); + pass &= compare_distance(a, ra); V b(7), rb(7); b<<= fill_policy::sparse_insert(), a, 10, a; rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; - pass &= compare_to(b, rb); + pass &= compare_distance(b, rb); V c(6), rc(6); c <<= fill_policy::sparse_insert(), 1, move(2), 3 ,4, 5, move(-5), 10, 10; // Move back (i.e. negative is dangerous for sparse) rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; - pass &= compare_to(c, rc); + pass &= compare_distance(c, rc); V d(6), rd(6); d <<= fill_policy::sparse_insert(), 1, move_to(3), 3 ,4, 5, move_to(1), 10, 10; // Move back (i.e.before is dangerous for sparse) rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; - pass &= compare_to(d, rd); + pass &= compare_distance(d, rd); return pass; @@ -152,7 +152,7 @@ bool test_matrix() { RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); { V B(3,3), RB(3,3); @@ -160,7 +160,7 @@ bool test_matrix() { b<<= 4,5,6; B<<= 1, 2, 3, b, 7, project(b, range(1,3)); RB<<=1, 2, 3, 4, 5, 6, 7, 5, 6; // If the first worked we can now probably use it. - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -169,7 +169,7 @@ bool test_matrix() { b<<= 4,5,6; B<<= move(1,0), b, move_to(0,0), 1, 2, 3, move(1,0), 7, project(b, range(1,3)); RB<<=1, 2, 3, 4, 5, 6, 7, 5, 6; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -178,7 +178,7 @@ bool test_matrix() { b<<= 1, 2, 3, 4, 5, 6, 7, 8, 9; B<<=b; RB<<=1, 2, 3, 4, 5, 6, 7, 8, 9; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -192,7 +192,7 @@ bool test_matrix() { 4,5,4,5, 2,3,2,3, 4,5,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -205,7 +205,7 @@ bool test_matrix() { 4,5,0,0, 0,0,2,3, 0,0,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -218,7 +218,7 @@ bool test_matrix() { 4,5,0,0, 0,0,2,3, 0,0,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -231,7 +231,7 @@ bool test_matrix() { 0,2,3,0, 0,4,5,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -242,7 +242,7 @@ bool test_matrix() { 1,2,0,0, 4,5,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -253,7 +253,7 @@ bool test_matrix() { 0,3,5,0, 0,6,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -264,7 +264,7 @@ bool test_matrix() { 0,3,0,0, 0,0,0,0, 4,5,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -275,7 +275,7 @@ bool test_matrix() { 0,3,0,0, 4,5,6,7, 8,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -286,7 +286,7 @@ bool test_matrix() { 0,3,0,0, 4,5,6,7, 8,9,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -299,7 +299,7 @@ bool test_matrix() { 1,2,3,1, 1,4,5,1, 1,1,1,1; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -312,7 +312,7 @@ bool test_matrix() { 5,4,3,5, 5,2,1,5, 5,5,5,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } @@ -328,7 +328,7 @@ bool test_matrix_sparse_push_back() { RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); { V B(3,3), RB(3,3); @@ -336,7 +336,7 @@ bool test_matrix_sparse_push_back() { b<<= 4,5,6; B<<=fill_policy::sparse_push_back(), 1, 2, 3, b, 7, project(b, range(1,3)); RB<<= 1, 2, 3, 4, 5, 6, 7, 5, 6; // If the first worked we can now probably use it. - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -345,7 +345,7 @@ bool test_matrix_sparse_push_back() { b<<= 4,5,6; B<<=fill_policy::sparse_push_back(), move(1,0), b, fill_policy::sparse_insert(), move_to(0,0), 1, 2, 3, move(1,0), 7, project(b, range(1,3)); RB<<=1, 2, 3, 4, 5, 6, 7, 5, 6; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -354,7 +354,7 @@ bool test_matrix_sparse_push_back() { b<<= 1, 2, 3, 4, 5, 6, 7, 8, 9; B<<=b; RB<<=1, 2, 3, 4, 5, 6, 7, 8, 9; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } @@ -369,7 +369,7 @@ bool test_matrix_sparse_push_back() { 4,5,4,5, 2,3,2,3, 4,5,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } @@ -382,7 +382,7 @@ bool test_matrix_sparse_push_back() { 4,5,0,0, 0,0,2,3, 0,0,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -394,7 +394,7 @@ bool test_matrix_sparse_push_back() { 0,2,3,0, 0,4,5,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -405,7 +405,7 @@ bool test_matrix_sparse_push_back() { 1,2,0,0, 4,5,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } // The next will not work with sparse push_back because elements that are prior to the ones already in are attempted to be added /* @@ -417,7 +417,7 @@ bool test_matrix_sparse_push_back() { 0,3,5,0, 0,6,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } */ { @@ -428,7 +428,7 @@ bool test_matrix_sparse_push_back() { 0,3,0,0, 0,0,0,0, 4,5,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -439,7 +439,7 @@ bool test_matrix_sparse_push_back() { 0,3,0,0, 4,5,6,7, 8,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } // The next will not work with sparse push_back because elements that are prior to the ones already in are attempted to be added @@ -452,7 +452,7 @@ bool test_matrix_sparse_push_back() { 0,3,0,0, 4,5,6,7, 8,9,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } */ return pass; @@ -467,7 +467,7 @@ bool test_matrix_sparse_insert() { RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); { V B(3,3), RB(3,3); @@ -475,7 +475,7 @@ bool test_matrix_sparse_insert() { b<<= 4,5,6; B<<=fill_policy::sparse_insert(), 1, 2, 3, b, 7, project(b, range(1,3)); RB<<=1, 2, 3, 4, 5, 6, 7, 5, 6; // If the first worked we can now probably use it. - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -484,7 +484,7 @@ bool test_matrix_sparse_insert() { b<<= 4,5,6; B<<=fill_policy::sparse_insert(), move(1,0), b, fill_policy::sparse_insert(), move_to(0,0), 1, 2, 3, move(1,0), 7, project(b, range(1,3)); RB<<=1, 2, 3, 4, 5, 6, 7, 5, 6; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -493,7 +493,7 @@ bool test_matrix_sparse_insert() { b<<= 1, 2, 3, 4, 5, 6, 7, 8, 9; B<<=b; RB<<=1, 2, 3, 4, 5, 6, 7, 8, 9; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } @@ -507,7 +507,7 @@ bool test_matrix_sparse_insert() { 4,5,4,5, 2,3,2,3, 4,5,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } @@ -520,7 +520,7 @@ bool test_matrix_sparse_insert() { 4,5,0,0, 0,0,2,3, 0,0,4,5; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -532,7 +532,7 @@ bool test_matrix_sparse_insert() { 0,2,3,0, 0,4,5,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -543,7 +543,7 @@ bool test_matrix_sparse_insert() { 1,2,0,0, 4,5,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -554,7 +554,7 @@ bool test_matrix_sparse_insert() { 0,3,5,0, 0,6,0,0, 0,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -565,7 +565,7 @@ bool test_matrix_sparse_insert() { 0,3,0,0, 0,0,0,0, 4,5,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -576,7 +576,7 @@ bool test_matrix_sparse_insert() { 0,3,0,0, 4,5,6,7, 8,0,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } { @@ -587,7 +587,7 @@ bool test_matrix_sparse_insert() { 0,3,0,0, 4,5,6,7, 8,9,0,0; - pass &= compare_to(B, RB); + pass &= compare_distance(B, RB); } return pass; diff --git a/test/test_coordinate_matrix_inplace_merge.cpp b/test/test_coordinate_matrix_inplace_merge.cpp index 75d1f708a..be0c85227 100644 --- a/test/test_coordinate_matrix_inplace_merge.cpp +++ b/test/test_coordinate_matrix_inplace_merge.cpp @@ -78,12 +78,12 @@ BOOST_UBLAS_TEST_DEF( test_coordinate_matrix_inplace_merge_random ) { bool sorted = check_sortedness(matrix_coord); - bool identical = compare_to(matrix_coord, matrix_dense, TOL); + bool identical = compare_distance(matrix_coord, matrix_dense, TOL); if (!(sorted && identical)) { print_entries(size_x, size_y, entries); } BOOST_UBLAS_TEST_CHECK( check_sortedness(matrix_coord) ); - BOOST_UBLAS_TEST_CHECK( compare_to(matrix_coord, matrix_dense, TOL) ); + BOOST_UBLAS_TEST_CHECK( compare_distance(matrix_coord, matrix_dense, TOL) ); } for (size_t entry = 0; entry < nr_entries; ++ entry) { @@ -97,7 +97,7 @@ BOOST_UBLAS_TEST_DEF( test_coordinate_matrix_inplace_merge_random ) { bool sorted = check_sortedness(matrix_coord); - bool identical = compare_to(matrix_coord, matrix_dense, TOL); + bool identical = compare_distance(matrix_coord, matrix_dense, TOL); if (!(sorted && identical)) { print_entries(size_x, size_y, entries); } diff --git a/test/test_coordinate_vector_inplace_merge.cpp b/test/test_coordinate_vector_inplace_merge.cpp index 9994e86ef..8878f26fb 100644 --- a/test/test_coordinate_vector_inplace_merge.cpp +++ b/test/test_coordinate_vector_inplace_merge.cpp @@ -68,12 +68,12 @@ BOOST_UBLAS_TEST_DEF( test_coordinate_vector_inplace_merge_random ) { bool sorted = check_sortedness(vector_coord); - bool identical = compare_to(vector_coord, vector_dense, TOL); + bool identical = compare_distance(vector_coord, vector_dense, TOL); if (!(sorted && identical)) { print_entries(size_vec, entries); } BOOST_UBLAS_TEST_CHECK( check_sortedness(vector_coord) ); - BOOST_UBLAS_TEST_CHECK( compare_to(vector_coord, vector_dense, TOL) ); + BOOST_UBLAS_TEST_CHECK( compare_distance(vector_coord, vector_dense, TOL) ); } for (size_t entry = 0; entry < nr_entries; ++ entry) { @@ -86,7 +86,7 @@ BOOST_UBLAS_TEST_DEF( test_coordinate_vector_inplace_merge_random ) { bool sorted = check_sortedness(vector_coord); - bool identical = compare_to(vector_coord, vector_dense, TOL); + bool identical = compare_distance(vector_coord, vector_dense, TOL); if (!(sorted && identical)) { print_entries(size_vec, entries); } diff --git a/test/test_matrix_vector.cpp b/test/test_matrix_vector.cpp index a7e8796cd..22266d717 100644 --- a/test/test_matrix_vector.cpp +++ b/test/test_matrix_vector.cpp @@ -70,7 +70,7 @@ bool test_matrix_row_facade() { rows(i) = matrix_row(RA, i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing operator[] @@ -87,7 +87,7 @@ bool test_matrix_row_facade() { rows[i] = matrix_row(RA, i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing operator[] const @@ -101,7 +101,7 @@ bool test_matrix_row_facade() { 7, 8, 9; for(typename Matrix::size_type i = 0; i < RA.size1(); i++) { - pass &= compare_to(rows[i], matrix_row(RA, i)); + pass &= compare_distance(rows[i], matrix_row(RA, i)); } } @@ -119,7 +119,7 @@ bool test_matrix_row_facade() { for(typename RowVector::const_iterator iter = rows.begin(); iter != rows.end(); iter++) { - pass &= compare_to(*iter, matrix_row(RA, i++)); + pass &= compare_distance(*iter, matrix_row(RA, i++)); } } @@ -140,7 +140,7 @@ bool test_matrix_row_facade() { *iter = matrix_row(RA, i++); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing reserse iterator @@ -160,7 +160,7 @@ bool test_matrix_row_facade() { *iter = matrix_row(RA, --i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing const reverse iterator @@ -177,7 +177,7 @@ bool test_matrix_row_facade() { for(typename RowVector::const_reverse_iterator iter = rows.rbegin(); iter != rows.rend(); iter++) { - pass &= compare_to(*iter, matrix_row(RA, --i)); + pass &= compare_distance(*iter, matrix_row(RA, --i)); } } @@ -224,7 +224,7 @@ bool test_matrix_column_facade() { columns(i) = matrix_column(RA, i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing operator[] @@ -241,7 +241,7 @@ bool test_matrix_column_facade() { columns[i] = matrix_column(RA, i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing operator[] const @@ -255,7 +255,7 @@ bool test_matrix_column_facade() { 7, 8, 9; for(typename Matrix::size_type i = 0; i < RA.size2(); i++) { - pass &= compare_to(columns[i], matrix_column(RA, i)); + pass &= compare_distance(columns[i], matrix_column(RA, i)); } } @@ -276,7 +276,7 @@ bool test_matrix_column_facade() { *iter = matrix_column(RA, i++); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing const iterator @@ -293,7 +293,7 @@ bool test_matrix_column_facade() { for(typename ColumnVector::const_iterator iter = columns.begin(); iter != columns.end(); iter++) { - pass &= compare_to(*iter, matrix_column(RA, i++)); + pass &= compare_distance(*iter, matrix_column(RA, i++)); } } @@ -314,7 +314,7 @@ bool test_matrix_column_facade() { *iter = matrix_column(RA, --i); } - pass &= compare_to(A, RA); + pass &= compare_distance(A, RA); } { // Testing const reverse iterator @@ -331,7 +331,7 @@ bool test_matrix_column_facade() { for(typename ColumnVector::const_reverse_iterator iter = columns.rbegin(); iter != columns.rend(); iter++) { - pass &= compare_to(*iter, matrix_column(RA, --i)); + pass &= compare_distance(*iter, matrix_column(RA, --i)); } } From 010df5c35880ba22a0c7da49cac8c273688eaa31 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 10 Aug 2015 00:05:56 +0200 Subject: [PATCH 11/73] Changed the types of variables to remove warnings. --- test/test_banded_storage_layout.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/test_banded_storage_layout.cpp b/test/test_banded_storage_layout.cpp index 6b4e68a7a..74a1be31b 100644 --- a/test/test_banded_storage_layout.cpp +++ b/test/test_banded_storage_layout.cpp @@ -58,7 +58,7 @@ bool test_band_storage() { banded_matrix< int, Orientation > test_matrix( m, n, kl, ku ); test_matrix.clear(); - int band_storage_size = test_matrix.data().size(); + size_t band_storage_size = test_matrix.data().size(); test_matrix( 0, 0 ) = 11; test_matrix( 0, 1 ) = 12; @@ -81,20 +81,20 @@ bool test_band_storage() { BOOST_UBLAS_TEST_TRACE( std::setw( 3 ) << test_matrix ); BOOST_UBLAS_TEST_TRACE( "data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << test_matrix.data()[ i ] << " "; } std::cerr << std::endl; BOOST_UBLAS_TEST_TRACE( "Expected data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << expected_index( i, Orientation() ) << " "; } std::cerr << std::endl; size_t mismatch = 0; - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { if ( test_matrix.data()[ i ] != expected_index( i, Orientation() ) ) { ++mismatch; } @@ -114,7 +114,7 @@ bool test_band_storage_6_by_5() { banded_matrix< int, Orientation > test_matrix( m, n, kl, ku ); test_matrix.clear(); - int band_storage_size = test_matrix.data().size(); + size_t band_storage_size = test_matrix.data().size(); test_matrix( 0, 0 ) = 11; test_matrix( 0, 1 ) = 12; @@ -139,20 +139,20 @@ bool test_band_storage_6_by_5() { BOOST_UBLAS_TEST_TRACE( std::setw( 3 ) << test_matrix ); BOOST_UBLAS_TEST_TRACE( "data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << test_matrix.data()[ i ] << " "; } std::cerr << std::endl; BOOST_UBLAS_TEST_TRACE( "Expected data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << expected_index_6_by_5( i, Orientation() ) << " "; } std::cerr << std::endl; size_t mismatch = 0; - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { if ( test_matrix.data()[ i ] != expected_index_6_by_5( i, Orientation() ) ) { ++mismatch; } @@ -171,7 +171,7 @@ bool test_band_storage_5_by_6() { banded_matrix< int, Orientation > test_matrix( m, n, kl, ku ); test_matrix.clear(); - int band_storage_size = test_matrix.data().size(); + size_t band_storage_size = test_matrix.data().size(); test_matrix( 0, 0 ) = 11; test_matrix( 0, 1 ) = 12; @@ -195,20 +195,20 @@ bool test_band_storage_5_by_6() { BOOST_UBLAS_TEST_TRACE( std::setw( 3 ) << test_matrix ); BOOST_UBLAS_TEST_TRACE( "data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << test_matrix.data()[ i ] << " "; } std::cerr << std::endl; BOOST_UBLAS_TEST_TRACE( "Expected data() of matrix" ); - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { std::cerr << expected_index_5_by_6( i, Orientation() ) << " "; } std::cerr << std::endl; size_t mismatch = 0; - for ( int i = 0; i < band_storage_size; ++i ) { + for ( size_t i = 0; i < band_storage_size; ++i ) { if ( test_matrix.data()[ i ] != expected_index_5_by_6( i, Orientation() ) ) { ++mismatch; } From 2696b885f7d6b3495100eb700e75ab9fdf0ddc18 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Tue, 11 Aug 2015 01:30:17 +0200 Subject: [PATCH 12/73] - Changed types of variables to remove warnings. - Repladed tabs for spaces in line indentation. - Replaced ::std::... by std::... --- test/test_ticket7296.cpp | 440 +++++++++++++++++++-------------------- 1 file changed, 220 insertions(+), 220 deletions(-) diff --git a/test/test_ticket7296.cpp b/test/test_ticket7296.cpp index 65fdb4ba6..bf4d2d861 100644 --- a/test/test_ticket7296.cpp +++ b/test/test_ticket7296.cpp @@ -4,7 +4,7 @@ * \brief Test suite for utils.hpp. * * Copyright (c) 2012, Marco Guazzone - * + * * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) @@ -23,270 +23,270 @@ namespace ublas = boost::numeric::ublas; -static const double tol(1e-6); -static const double mul(tol*10); +static const float tol(1e-6f); +static const float mul(tol*10); BOOST_UBLAS_TEST_DEF( check ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check'" ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check'" ); - BOOST_UBLAS_TEST_CHECK( true ); + BOOST_UBLAS_TEST_CHECK( true ); } BOOST_UBLAS_TEST_DEF( check_eq ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_eq'" ); - - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_EQ( short(1), short(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( int(1), int(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( long(1), long(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( unsigned(1), unsigned(1) ); - - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_EQ( short(1), int(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( short(1), int(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( int(1), long(1) ); - BOOST_UBLAS_TEST_CHECK_EQ( long(1), int(1) ); - - BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); - BOOST_UBLAS_TEST_CHECK_EQUAL( int(1), int(1) ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_eq'" ); + + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_EQ( short(1), short(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( int(1), int(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( long(1), long(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( unsigned(1), unsigned(1) ); + + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_EQ( short(1), int(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( short(1), int(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( int(1), long(1) ); + BOOST_UBLAS_TEST_CHECK_EQ( long(1), int(1) ); + + BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); + BOOST_UBLAS_TEST_CHECK_EQUAL( int(1), int(1) ); } BOOST_UBLAS_TEST_DEF( check_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_close'" ); - - const double c1(1*mul); - const double c2(2*mul); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_CLOSE( float(c1), float(c1), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( double(c1), double(c1), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_CLOSE( float(c1), double(c1), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( double(c1), float(c1), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - BOOST_UBLAS_TEST_CHECK_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - - // Check alias - BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); - BOOST_UBLAS_TEST_CHECK_PRECISION( float(c1), float(c1), tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_close'" ); + + const float c1(1*mul); + const float c2(2*mul); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_CLOSE( float(c1), float(c1), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( double(c1), double(c1), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_CLOSE( float(c1), double(c1), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( double(c1), float(c1), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + BOOST_UBLAS_TEST_CHECK_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + + // Check alias + BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); + BOOST_UBLAS_TEST_CHECK_PRECISION( float(c1), float(c1), tol ); } BOOST_UBLAS_TEST_DEF( check_rel_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_rel_close'" ); - - const double c1(1*mul); - const double c2(2*mul); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( float(c1), float(c1), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( double(c1), double(c1), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( float(c1), double(c1), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( double(c1), float(c1), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - BOOST_UBLAS_TEST_CHECK_REL_CLOSE( ::std::complex(c1,c2), ::std::complex(c1,c2), tol ); - - // Check alias - BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); - BOOST_UBLAS_TEST_CHECK_REL_PRECISION( float(c1), float(c1), tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_rel_close'" ); + + const float c1(1*mul); + const float c2(2*mul); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( float(c1), float(c1), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( double(c1), double(c1), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( float(c1), double(c1), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( double(c1), float(c1), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + BOOST_UBLAS_TEST_CHECK_REL_CLOSE( std::complex(c1,c2), std::complex(c1,c2), tol ); + + // Check alias + BOOST_UBLAS_DEBUG_TRACE( "-- Test aliases." ); + BOOST_UBLAS_TEST_CHECK_REL_PRECISION( float(c1), float(c1), tol ); } BOOST_UBLAS_TEST_DEF( check_vector_eq ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_eq'" ); - - const ::std::size_t n(5); - - ublas::vector sv = ublas::scalar_vector(n, 1); - ublas::vector iv = ublas::scalar_vector(n, 1); - ublas::vector lv = ublas::scalar_vector(n, 1L); - ublas::vector uv = ublas::scalar_vector(n, 1u); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( sv, sv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, iv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( lv, lv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( uv, uv, n ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( sv, iv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, sv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, lv, n ); - BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( lv, iv, n ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_eq'" ); + + const std::size_t n(5); + + ublas::vector sv = ublas::scalar_vector(n, 1); + ublas::vector iv = ublas::scalar_vector(n, 1); + ublas::vector lv = ublas::scalar_vector(n, 1L); + ublas::vector uv = ublas::scalar_vector(n, 1u); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( sv, sv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, iv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( lv, lv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( uv, uv, n ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( sv, iv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, sv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( iv, lv, n ); + BOOST_UBLAS_TEST_CHECK_VECTOR_EQ( lv, iv, n ); } BOOST_UBLAS_TEST_DEF( check_vector_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_close'" ); - - const ::std::size_t n(5); - - ublas::vector fv = ublas::scalar_vector(n, 1); - ublas::vector dv = ublas::scalar_vector(n, 1); - ublas::vector< ::std::complex > cfv = ublas::scalar_vector< ::std::complex >(n, ::std::complex(1,2)); - ublas::vector< ::std::complex > cdv = ublas::scalar_vector< ::std::complex >(n, ::std::complex(1,2)); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( fv, fv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( dv, dv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cfv, cfv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cdv, cdv, n, tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( fv, dv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( dv, fv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cfv, cdv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cdv, cfv, n, tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_close'" ); + + const std::size_t n(5); + + ublas::vector fv = ublas::scalar_vector(n, 1); + ublas::vector dv = ublas::scalar_vector(n, 1); + ublas::vector< std::complex > cfv = ublas::scalar_vector< std::complex >(n, std::complex(1,2)); + ublas::vector< std::complex > cdv = ublas::scalar_vector< std::complex >(n, std::complex(1,2)); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( fv, fv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( dv, dv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cfv, cfv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cdv, cdv, n, tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( fv, dv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( dv, fv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cfv, cdv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_CLOSE( cdv, cfv, n, tol ); } BOOST_UBLAS_TEST_DEF( check_vector_rel_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_rel_close'" ); - - const ::std::size_t n(5); - const double c1(1*mul); - const double c2(2*mul); - - ublas::vector fv = ublas::scalar_vector(n, c1); - ublas::vector dv = ublas::scalar_vector(n, c1); - ublas::vector< ::std::complex > cfv = ublas::scalar_vector< ::std::complex >(n, ::std::complex(c1,c2)); - ublas::vector< ::std::complex > cdv = ublas::scalar_vector< ::std::complex >(n, ::std::complex(c1,c2)); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( fv, fv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( dv, dv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cfv, cfv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cdv, cdv, n, tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( fv, dv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( dv, fv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cfv, cdv, n, tol ); - BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cdv, cfv, n, tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_vector_rel_close'" ); + + const std::size_t n(5); + const float c1(1*mul); + const float c2(2*mul); + + ublas::vector fv = ublas::scalar_vector(n, c1); + ublas::vector dv = ublas::scalar_vector(n, c1); + ublas::vector< std::complex > cfv = ublas::scalar_vector< std::complex >(n, std::complex(c1,c2)); + ublas::vector< std::complex > cdv = ublas::scalar_vector< std::complex >(n, std::complex(c1,c2)); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( fv, fv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( dv, dv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cfv, cfv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cdv, cdv, n, tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( fv, dv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( dv, fv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cfv, cdv, n, tol ); + BOOST_UBLAS_TEST_CHECK_VECTOR_REL_CLOSE( cdv, cfv, n, tol ); } BOOST_UBLAS_TEST_DEF( check_matrix_eq ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_eq'" ); - - const ::std::size_t nr(3); - const ::std::size_t nc(4); - - ublas::matrix sv = ublas::scalar_matrix(nr, nc, 1); - ublas::matrix iv = ublas::scalar_matrix(nr, nc, 1); - ublas::matrix lv = ublas::scalar_matrix(nr, nc, 1L); - ublas::matrix uv = ublas::scalar_matrix(nr, nc, 1u); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( sv, sv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, iv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( lv, lv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( uv, uv, nr, nc ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( sv, iv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, sv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, lv, nr, nc ); - BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( lv, iv, nr, nc ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_eq'" ); + + const std::size_t nr(3); + const std::size_t nc(4); + + ublas::matrix sv = ublas::scalar_matrix(nr, nc, 1); + ublas::matrix iv = ublas::scalar_matrix(nr, nc, 1); + ublas::matrix lv = ublas::scalar_matrix(nr, nc, 1L); + ublas::matrix uv = ublas::scalar_matrix(nr, nc, 1u); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( sv, sv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, iv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( lv, lv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( uv, uv, nr, nc ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( sv, iv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, sv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( iv, lv, nr, nc ); + BOOST_UBLAS_TEST_CHECK_MATRIX_EQ( lv, iv, nr, nc ); } BOOST_UBLAS_TEST_DEF( check_matrix_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_close'" ); - - const ::std::size_t nr(3); - const ::std::size_t nc(4); - const double c1(1*mul); - const double c2(2*mul); - - ublas::matrix fA = ublas::scalar_matrix(nr, nc, c1); - ublas::matrix dA = ublas::scalar_matrix(nr, nc, c1); - ublas::matrix< ::std::complex > cfA = ublas::scalar_matrix< ::std::complex >(nr, nc, ::std::complex(c1,c2)); - ublas::matrix< ::std::complex > cdA = ublas::scalar_matrix< ::std::complex >(nr, nc, ::std::complex(c1,c2)); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( fA, fA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( dA, dA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cfA, cfA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cdA, cdA, nr, nc, tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( fA, dA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( dA, fA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cfA, cdA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cdA, cfA, nr, nc, tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_close'" ); + + const std::size_t nr(3); + const std::size_t nc(4); + const float c1(1*mul); + const float c2(2*mul); + + ublas::matrix fA = ublas::scalar_matrix(nr, nc, c1); + ublas::matrix dA = ublas::scalar_matrix(nr, nc, c1); + ublas::matrix< std::complex > cfA = ublas::scalar_matrix< std::complex >(nr, nc, std::complex(c1,c2)); + ublas::matrix< std::complex > cdA = ublas::scalar_matrix< std::complex >(nr, nc, std::complex(c1,c2)); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( fA, fA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( dA, dA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cfA, cfA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cdA, cdA, nr, nc, tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( fA, dA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( dA, fA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cfA, cdA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_CLOSE( cdA, cfA, nr, nc, tol ); } BOOST_UBLAS_TEST_DEF( check_matrix_rel_close ) { - BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_rel_close'" ); - - const ::std::size_t nr(3); - const ::std::size_t nc(4); - const double c1(1*mul); - const double c2(2*mul); - - ublas::matrix fA = ublas::scalar_matrix(nr, nc, c1); - ublas::matrix dA = ublas::scalar_matrix(nr, nc, c1); - ublas::matrix< ::std::complex > cfA = ublas::scalar_matrix< ::std::complex >(nr, nc, ::std::complex(c1,c2)); - ublas::matrix< ::std::complex > cdA = ublas::scalar_matrix< ::std::complex >(nr, nc, ::std::complex(c1,c2)); - - // Check T vs. T - BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( fA, fA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( dA, dA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cfA, cfA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cdA, cdA, nr, nc, tol ); - - // Check T1 vs. T2 - BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( fA, dA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( dA, fA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cfA, cdA, nr, nc, tol ); - BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cdA, cfA, nr, nc, tol ); + BOOST_UBLAS_TEST_TRACE( "Test case: 'check_matrix_rel_close'" ); + + const std::size_t nr(3); + const std::size_t nc(4); + const float c1(1*mul); + const float c2(2*mul); + + ublas::matrix fA = ublas::scalar_matrix(nr, nc, c1); + ublas::matrix dA = ublas::scalar_matrix(nr, nc, c1); + ublas::matrix< std::complex > cfA = ublas::scalar_matrix< std::complex >(nr, nc, std::complex(c1,c2)); + ublas::matrix< std::complex > cdA = ublas::scalar_matrix< std::complex >(nr, nc, std::complex(c1,c2)); + + // Check T vs. T + BOOST_UBLAS_DEBUG_TRACE( "-- Test against same types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( fA, fA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( dA, dA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cfA, cfA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cdA, cdA, nr, nc, tol ); + + // Check T1 vs. T2 + BOOST_UBLAS_DEBUG_TRACE( "-- Test against different types." ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( fA, dA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( dA, fA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cfA, cdA, nr, nc, tol ); + BOOST_UBLAS_TEST_CHECK_MATRIX_REL_CLOSE( cdA, cfA, nr, nc, tol ); } int main() { - BOOST_UBLAS_TEST_SUITE( "Test 'utils.hpp' functionalities" ); - - BOOST_UBLAS_TEST_BEGIN(); - BOOST_UBLAS_TEST_DO( check ); - BOOST_UBLAS_TEST_DO( check_eq ); - BOOST_UBLAS_TEST_DO( check_close ); - BOOST_UBLAS_TEST_DO( check_rel_close ); - BOOST_UBLAS_TEST_DO( check_vector_eq ); - BOOST_UBLAS_TEST_DO( check_vector_close ); - BOOST_UBLAS_TEST_DO( check_vector_rel_close ); - BOOST_UBLAS_TEST_DO( check_matrix_eq ); - BOOST_UBLAS_TEST_DO( check_matrix_close ); - BOOST_UBLAS_TEST_DO( check_matrix_rel_close ); - BOOST_UBLAS_TEST_END(); + BOOST_UBLAS_TEST_SUITE( "Test 'utils.hpp' functionalities" ); + + BOOST_UBLAS_TEST_BEGIN(); + BOOST_UBLAS_TEST_DO( check ); + BOOST_UBLAS_TEST_DO( check_eq ); + BOOST_UBLAS_TEST_DO( check_close ); + BOOST_UBLAS_TEST_DO( check_rel_close ); + BOOST_UBLAS_TEST_DO( check_vector_eq ); + BOOST_UBLAS_TEST_DO( check_vector_close ); + BOOST_UBLAS_TEST_DO( check_vector_rel_close ); + BOOST_UBLAS_TEST_DO( check_matrix_eq ); + BOOST_UBLAS_TEST_DO( check_matrix_close ); + BOOST_UBLAS_TEST_DO( check_matrix_rel_close ); + BOOST_UBLAS_TEST_END(); } From 849a83392259e22f9b534ada7f713cde8320e984 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Wed, 12 Aug 2015 14:06:18 +0200 Subject: [PATCH 13/73] Changed variable type to remove a warning. --- test/test_lu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_lu.cpp b/test/test_lu.cpp index e2b203f8e..866ecf2f2 100644 --- a/test/test_lu.cpp +++ b/test/test_lu.cpp @@ -54,7 +54,7 @@ int main () { permutation_matrix<> pm(3); - int result = lu_factorize >(A, pm); + std::size_t result = lu_factorize >(A, pm); assertTrue("factorization completed: ", 0 == result); assertTrue("LU factors are correct: ", compare(A, LU)); From 1e738286511ffa1378e14990f4343ab7d0360ecb Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Wed, 12 Aug 2015 14:08:25 +0200 Subject: [PATCH 14/73] - Qualified double literals as float. - Changed variables type in for loop to remove warnings and added temporal variable. --- test/test_complex_norms.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/test_complex_norms.cpp b/test/test_complex_norms.cpp index e923d7087..d58a788ee 100644 --- a/test/test_complex_norms.cpp +++ b/test/test_complex_norms.cpp @@ -45,28 +45,32 @@ BOOST_UBLAS_TEST_DEF ( test_double_complex_norm_2 ) { BOOST_UBLAS_TEST_DEF ( test_float_complex_norm_inf ) { typedef std::complex dComplex; vector v(4); - for (unsigned int i = 0; i < v.size(); ++i) - v[i] = dComplex(i, i + 1); + for (unsigned short i = 0; i < v.size(); ++i) { + unsigned short imag(i + 1); + v[i] = dComplex(i, imag); + } const float expected = abs(v[3]); BOOST_UBLAS_DEBUG_TRACE( "norm is " << norm_inf(v) ); BOOST_UBLAS_TEST_CHECK(std::abs(norm_inf(v) - expected) < TOL); - v *= 3.; + v *= 3.f; BOOST_UBLAS_TEST_CHECK(std::abs(norm_inf(v) - (3.0*expected)) < TOL); } BOOST_UBLAS_TEST_DEF ( test_float_complex_norm_2 ) { typedef std::complex dComplex; vector v(4); - for (unsigned int i = 0; i < v.size(); ++i) - v[i] = dComplex(i, i + 1); + for (unsigned short i = 0; i < v.size(); ++i) { + unsigned short imag(i + 1); + v[i] = dComplex(i, imag); + } const double expected = sqrt(44.0); BOOST_UBLAS_DEBUG_TRACE( "norm is " << norm_2(v) ); BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - expected) < TOL); - v *= 3.; + v *= 3.f; BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - (3.0*expected)) < TOL); } From b7e7f840506793b49611bc95095bc1ea225ab61c Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Wed, 12 Aug 2015 14:13:39 +0200 Subject: [PATCH 15/73] Cast numeric literals to remove warnings. --- test/test_assignment.cpp | 60 ++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/test/test_assignment.cpp b/test/test_assignment.cpp index 613023f8c..78fe2c314 100644 --- a/test/test_assignment.cpp +++ b/test/test_assignment.cpp @@ -26,35 +26,40 @@ bool test_vector() { V a(3), ra(3); a <<= 1, 2, 3; - ra(0) = 1; ra(1) = 2; ra(2) = 3; + ra(0) = typename V::value_type(1); ra(1) = typename V::value_type(2); ra(2) = typename V::value_type(3); pass &= compare_distance(a, ra); V b(7), rb(7); b<<= a, 10, a; - rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; + rb(0) = typename V::value_type(1); rb(1) = typename V::value_type(2); rb(2) = typename V::value_type(3); + rb(3) = typename V::value_type(10); rb(4) = typename V::value_type(1); rb(5) = typename V::value_type(2); rb(6) = typename V::value_type(3); pass &= compare_distance(b, rb); { V c(6), rc(6); c <<= 1, move(2), 3 ,4, 5, move(-5), 10, 10; - rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; + rc(0) = typename V::value_type(1); rc(1) = typename V::value_type(10); rc(2) = typename V::value_type(10); + rc(3) = typename V::value_type(3); rc(4) = typename V::value_type(4); rc(5) = typename V::value_type(5); pass &= compare_distance(c, rc); V d(6), rd(6); d <<= 1, move_to(3), 3 ,4, 5, move_to(1), 10, 10; - rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; + rd(0) = typename V::value_type(1); rd(1) = typename V::value_type(10); rd(2) = typename V::value_type(10); + rd(3) = typename V::value_type(3); rd(4) = typename V::value_type(4); rd(5) = typename V::value_type(5); pass &= compare_distance(d, rd); } { V c(6), rc(6); c <<= 1, move<2>(), 3 ,4, 5, move<-5>(), 10, 10; - rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; + rc(0) = typename V::value_type(1); rc(1) = typename V::value_type(10); rc(2) = typename V::value_type(10); + rc(3) = typename V::value_type(3); rc(4) = typename V::value_type(4); rc(5) = typename V::value_type(5); pass &= compare_distance(c, rc); V d(6), rd(6); d <<= 1, move_to<3>(), 3 ,4, 5, move_to<1>(), 10, 10; - rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; + rd(0) = typename V::value_type(1); rd(1) = typename V::value_type(10); rd(2) = typename V::value_type(10); + rd(3) = typename V::value_type(3); rd(4) = typename V::value_type(4); rd(5) = typename V::value_type(5); pass &= compare_distance(d, rd); } @@ -86,27 +91,31 @@ bool test_vector_sparse_push_back() { V a(3), ra(3); a <<= fill_policy::sparse_push_back(), 1, 2, 3; - ra(0) = 1; ra(1) = 2; ra(2) = 3; + ra(0) = typename V::value_type(1); ra(1) = typename V::value_type(2); ra(2) = typename V::value_type(3); pass &= compare_distance(a, ra); V b(7), rb(7); b<<= fill_policy::sparse_push_back(), a, 10, a; - rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; + rb(0) = typename V::value_type(1); rb(1) = typename V::value_type(2); rb(2) = typename V::value_type(3); + rb(3) = typename V::value_type(10), rb(4)= typename V::value_type(1); rb(5) = typename V::value_type(2); rb(6) = typename V::value_type(3); pass &= compare_distance(b, rb); V c(6), rc(6); c <<= fill_policy::sparse_push_back(), 1, move(2), 3 ,4, 5; // Move back (i.e. negative is dangerous for push_back) - rc(0) = 1; rc(1) = 0; rc(2) = 0; rc(3) = 3; rc(4) = 4; rc(5) = 5; + rc(0) = typename V::value_type(1); rc(1) = typename V::value_type(0); rc(2) = typename V::value_type(0); + rc(3) = typename V::value_type(3); rc(4) = typename V::value_type(4); rc(5) = typename V::value_type(5); pass &= compare_distance(c, rc); V d(6), rd(6); d <<= fill_policy::sparse_push_back(), 1, move_to(3), 3 ,4, 5; // Move back (i.e. before current index is dangerous for push_back) - rd(0) = 1; rd(1) = 0; rd(2) = 0; rd(3) = 3; rd(4) = 4; rd(5) = 5; + rd(0) = typename V::value_type(1); rd(1) = typename V::value_type(0); rd(2) = typename V::value_type(0); + rd(3) = typename V::value_type(3); rd(4) = typename V::value_type(4); rd(5) = typename V::value_type(5); pass &= compare_distance(d, rd); V e(6), re(6); e <<= fill_policy::sparse_push_back(), 1, move_to(3), 3 ,4, 5, fill_policy::sparse_insert(), move_to(1), 10, 10; // If you want to move back, use this - re(0) = 1; re(1) = 10; re(2) = 10; re(3) = 3; re(4) = 4; re(5) = 5; + re(0) = typename V::value_type(1); re(1) = typename V::value_type(10); re(2) = typename V::value_type(10); + re(3) = typename V::value_type(3); re(4) = typename V::value_type(4); re(5) = typename V::value_type(5); pass &= compare_distance(e, re); return pass; @@ -119,23 +128,26 @@ bool test_vector_sparse_insert() { V a(3), ra(3); a <<= fill_policy::sparse_insert(), 1, 2, 3; - ra(0) = 1; ra(1) = 2; ra(2) = 3; + ra(0) = typename V::value_type(1); ra(1) = typename V::value_type(2); ra(2) = typename V::value_type(3); pass &= compare_distance(a, ra); V b(7), rb(7); b<<= fill_policy::sparse_insert(), a, 10, a; - rb(0) = 1; rb(1) = 2; rb(2) = 3; rb(3)=10, rb(4)= 1; rb(5)=2; rb(6)=3; + rb(0) = typename V::value_type(1); rb(1) = typename V::value_type(2); rb(2) = typename V::value_type(3); + rb(3) = typename V::value_type(10), rb(4) = typename V::value_type(1); rb(5)= typename V::value_type(2); rb(6) = typename V::value_type(3); pass &= compare_distance(b, rb); V c(6), rc(6); c <<= fill_policy::sparse_insert(), 1, move(2), 3 ,4, 5, move(-5), 10, 10; // Move back (i.e. negative is dangerous for sparse) - rc(0) = 1; rc(1) = 10; rc(2) = 10; rc(3) = 3; rc(4) = 4; rc(5) = 5; + rc(0) = typename V::value_type(1); rc(1) = typename V::value_type(10); rc(2) = typename V::value_type(10); + rc(3) = typename V::value_type(3); rc(4) = typename V::value_type(4); rc(5) = typename V::value_type(5); pass &= compare_distance(c, rc); V d(6), rd(6); d <<= fill_policy::sparse_insert(), 1, move_to(3), 3 ,4, 5, move_to(1), 10, 10; // Move back (i.e.before is dangerous for sparse) - rd(0) = 1; rd(1) = 10; rd(2) = 10; rd(3) = 3; rd(4) = 4; rd(5) = 5; + rd(0) = typename V::value_type(1); rd(1) = typename V::value_type(10); rd(2) = typename V::value_type(10); + rd(3) = typename V::value_type(3); rd(4) = typename V::value_type(4); rd(5) = typename V::value_type(5); pass &= compare_distance(d, rd); @@ -149,9 +161,9 @@ bool test_matrix() { V A(3,3), RA(3,3); A <<= 1, 2, 3, 4, 5, 6, 7, 8, 9; - RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; - RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; - RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; + RA(0,0)= typename V::value_type(1); RA(0,1)=typename V::value_type(2); RA(0,2)=typename V::value_type(3); + RA(1,0)= typename V::value_type(4); RA(1,1)=typename V::value_type(5); RA(1,2)=typename V::value_type(6); + RA(2,0)= typename V::value_type(7); RA(2,1)=typename V::value_type(8); RA(2,2)=typename V::value_type(9); pass &= compare_distance(A, RA); { @@ -325,9 +337,9 @@ bool test_matrix_sparse_push_back() { V A(3,3), RA(3,3); A <<= fill_policy::sparse_push_back(), 1, 2, 3, 4, 5, 6, 7, 8, 9; - RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; - RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; - RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; + RA(0,0)= typename V::value_type(1); RA(0,1)= typename V::value_type(2); RA(0,2)= typename V::value_type(3); + RA(1,0)= typename V::value_type(4); RA(1,1)= typename V::value_type(5); RA(1,2)= typename V::value_type(6); + RA(2,0)= typename V::value_type(7); RA(2,1)= typename V::value_type(8); RA(2,2)= typename V::value_type(9); pass &= compare_distance(A, RA); { @@ -464,9 +476,9 @@ bool test_matrix_sparse_insert() { V A(3,3), RA(3,3); A <<= fill_policy::sparse_insert(), 1, 2, 3, 4, 5, 6, 7, 8, 9; - RA(0,0)= 1; RA(0,1)=2; RA(0,2)=3; - RA(1,0)= 4; RA(1,1)=5; RA(1,2)=6; - RA(2,0)= 7; RA(2,1)=8; RA(2,2)=9; + RA(0,0)= typename V::value_type(1); RA(0,1)= typename V::value_type(2); RA(0,2)= typename V::value_type(3); + RA(1,0)= typename V::value_type(4); RA(1,1)= typename V::value_type(5); RA(1,2)= typename V::value_type(6); + RA(2,0)= typename V::value_type(7); RA(2,1)= typename V::value_type(8); RA(2,2)= typename V::value_type(9); pass &= compare_distance(A, RA); { From a1942dfa037f07c298f3f79a478e9afbb8a03fdb Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 14 Aug 2015 01:39:12 +0200 Subject: [PATCH 16/73] For MSVC compliers, disabled warning C4996 (https://msdn.microsoft.com/en-us/library/ttcz0bys.aspx) --- test/Jamfile.v2 | 56 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bd4092e1c..d6d64e971 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -63,6 +63,7 @@ test-suite numeric/uBLAS : # input files : # requirements $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test2.cpp test21.cpp @@ -70,6 +71,7 @@ test-suite numeric/uBLAS test23.cpp : : : $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test3.cpp test31.cpp @@ -77,6 +79,7 @@ test-suite numeric/uBLAS test33.cpp : : : $(UBLAS_TESTSET_SPARSE) + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test3.cpp test31.cpp @@ -84,6 +87,7 @@ test-suite numeric/uBLAS test33.cpp : : : $(UBLAS_TESTSET_SPARSE_COO) + msvc:_SCL_SECURE_NO_WARNINGS : test3_coo : ] @@ -105,18 +109,21 @@ test-suite numeric/uBLAS test43.cpp : : : $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test5.cpp test52.cpp test53.cpp : : : $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test6.cpp test62.cpp test63.cpp : : : $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS ] # Test commented out because boost::interval does not behave like a scalar type # [ run test7.cpp @@ -139,6 +146,8 @@ test-suite numeric/uBLAS darwin:"-fabi-version=0" ] [ run test_lu.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] [ run triangular_access.cpp : : : @@ -147,8 +156,12 @@ test-suite numeric/uBLAS [ run triangular_layout.cpp ] [ run comp_mat_erase.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] [ run sparse_view_test.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] [ run begin_end.cpp ] @@ -169,28 +182,34 @@ test-suite numeric/uBLAS ] [ run test_complex_norms.cpp ] - [ run test_assignment.cpp - : : : BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT - : : - ] - [ run test_triangular.cpp - : - : - : /boost/timer//boost_timer - ] - [ run test_ticket7296.cpp - ] + [ run test_assignment.cpp + : : : + BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT + msvc:_SCL_SECURE_NO_WARNINGS + : : + ] + [ run test_triangular.cpp + : + : + : /boost/timer//boost_timer + msvc:_SCL_SECURE_NO_WARNINGS + ] + [ run test_ticket7296.cpp + ] [ run test_inplace_solve.cpp : : - : $(UBLAS_TESTSET) + : $(UBLAS_TESTSET) + msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_basic : ] [ run test_inplace_solve.cpp : : - : $(UBLAS_TESTSET_SPARSE) $(UBLAS_TESTSET_SPARSE_COO) + : $(UBLAS_TESTSET_SPARSE) + $(UBLAS_TESTSET_SPARSE_COO) + msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_sparse : ] @@ -198,12 +217,17 @@ test-suite numeric/uBLAS : : : USE_MAPPED_VECTOR_OF_MAPPED_VECTOR + msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_mvov : ] - [ run test_coordinate_vector_inplace_merge.cpp + [ run test_coordinate_vector_inplace_merge.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] - [ run test_coordinate_matrix_inplace_merge.cpp + [ run test_coordinate_matrix_inplace_merge.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] [ run test_banded_storage_layout.cpp : @@ -218,5 +242,7 @@ test-suite numeric/uBLAS : ] [ run test_matrix_vector.cpp + : : : + msvc:_SCL_SECURE_NO_WARNINGS ] ; From a3ebf8a4cc6d2c7ba6da23bd0799b7eb8c482829 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Thu, 20 Aug 2015 00:22:38 +0200 Subject: [PATCH 17/73] Enabled async-exception to test comp_mat_erase. --- test/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d6d64e971..b081edd6e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -158,6 +158,7 @@ test-suite numeric/uBLAS [ run comp_mat_erase.cpp : : : msvc:_SCL_SECURE_NO_WARNINGS + msvc:on ] [ run sparse_view_test.cpp : : : From 149d012bfec5a3c905da2c2847e75317e8452a30 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 21 Aug 2015 00:02:54 +0200 Subject: [PATCH 18/73] Fixed warning about possible loss of data. --- test/test33.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test33.cpp b/test/test33.cpp index b7d658cfa..48e1424f4 100644 --- a/test/test33.cpp +++ b/test/test33.cpp @@ -36,7 +36,7 @@ struct test_my_matrix { std::cout << "m1.swap (m2) = " << m1 << " " << m2 << std::endl; // Zero assignment - m1 = ublas::zero_matrix<> (m1.size1 (), m1.size2 ()); + m1 = ublas::zero_matrix (m1.size1 (), m1.size2 ()); std::cout << "m1.zero_matrix = " << m1 << std::endl; m1 = m2; From bdc1b17ee4c045ea62a0cec0d2421e99b82ba5b2 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 21 Aug 2015 12:28:11 +0200 Subject: [PATCH 19/73] Fix type of parameters in matrix_vector.hpp --- include/boost/numeric/ublas/matrix_vector.hpp | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/include/boost/numeric/ublas/matrix_vector.hpp b/include/boost/numeric/ublas/matrix_vector.hpp index fec1f65df..45af34b59 100644 --- a/include/boost/numeric/ublas/matrix_vector.hpp +++ b/include/boost/numeric/ublas/matrix_vector.hpp @@ -162,16 +162,20 @@ class matrix_row_vector { return end(); } - value_type operator()(difference_type index) const { + value_type operator()(size_type index) { return value_type(matrix_, index); } - reference operator[](difference_type index){ - return reference(matrix_, index); + value_type operator()(size_type index) const { + return value_type(matrix_, index); + } + + reference operator[](size_type index){ + return (*this) (index); } - const_reference operator[](difference_type index) const { - return const_reference(matrix_, index); + const_reference operator[](size_type index) const { + return (*this) (index); } size_type size() const { @@ -291,16 +295,20 @@ class matrix_column_vector return rend(); } - value_type operator()(difference_type index) const { + value_type operator()(size_type index) { + return value_type(matrix_, index); + } + + value_type operator()(size_type index) const { return value_type(matrix_, index); } - reference operator[](difference_type index) { - return reference(matrix_, index); + reference operator[](size_type index) { + return (*this) (index); } - const_reference operator[](difference_type index) const { - return const_reference(matrix_, index); + const_reference operator[](size_type index) const { + return (*this) (index); } size_type size() const { From 27fd2ae4e1a0d8d2882c81d3ce8e95cab9e0e0f4 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 21 Aug 2015 12:43:31 +0200 Subject: [PATCH 20/73] Added BOOST_UBLAS_INLINE macro in functions of file matrix_vector.hpp. --- include/boost/numeric/ublas/matrix_vector.hpp | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/include/boost/numeric/ublas/matrix_vector.hpp b/include/boost/numeric/ublas/matrix_vector.hpp index 45af34b59..5eb37184e 100644 --- a/include/boost/numeric/ublas/matrix_vector.hpp +++ b/include/boost/numeric/ublas/matrix_vector.hpp @@ -43,10 +43,12 @@ class matrix_vector_iterator: public boost::iterator_facade< matrix_vector_iterator(){} ///\brief constructs a matrix_vector_iterator as pointing to the i-th proxy + BOOST_UBLAS_INLINE matrix_vector_iterator(Matrix& matrix, std::size_t position) : matrix_(&matrix),position_(position) {} template + BOOST_UBLAS_INLINE matrix_vector_iterator(matrix_vector_iterator const& other) : matrix_(other.matrix_),position_(other.position_) {} @@ -54,28 +56,36 @@ class matrix_vector_iterator: public boost::iterator_facade< friend class boost::iterator_core_access; template friend class matrix_vector_iterator; + BOOST_UBLAS_INLINE void increment() { ++position_; } + + BOOST_UBLAS_INLINE void decrement() { --position_; } + BOOST_UBLAS_INLINE void advance(std::ptrdiff_t n){ position_ += n; } template + BOOST_UBLAS_INLINE std::ptrdiff_t distance_to(matrix_vector_iterator const& other) const{ BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ()); return (std::ptrdiff_t)other.position_ - (std::ptrdiff_t)position_; } template + BOOST_UBLAS_INLINE bool equal(matrix_vector_iterator const& other) const{ BOOST_UBLAS_CHECK (matrix_ == other.matrix_, external_logic ()); return (position_ == other.position_); } + + BOOST_UBLAS_INLINE Reference dereference() const { return Reference(*matrix_,position_); } @@ -109,79 +119,97 @@ class matrix_row_vector { typedef typename boost::iterator_difference::type difference_type; typedef typename Matrix::size_type size_type; + BOOST_UBLAS_INLINE matrix_row_vector(Matrix& matrix) : matrix_(matrix) { } - + BOOST_UBLAS_INLINE iterator begin(){ return iterator(matrix_, 0); } + BOOST_UBLAS_INLINE const_iterator begin() const { return const_iterator(matrix_, 0); } + BOOST_UBLAS_INLINE const_iterator cbegin() const { return begin(); } + BOOST_UBLAS_INLINE iterator end() { return iterator(matrix_, matrix_.size1()); } + BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator(matrix_, matrix_.size1()); } + BOOST_UBLAS_INLINE const_iterator cend() const { return end(); } + BOOST_UBLAS_INLINE reverse_iterator rbegin() { return reverse_iterator(end()); } + BOOST_UBLAS_INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + BOOST_UBLAS_INLINE const_reverse_iterator crbegin() const { return rbegin(); } + BOOST_UBLAS_INLINE reverse_iterator rend() { return reverse_iterator(begin()); } + BOOST_UBLAS_INLINE const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + BOOST_UBLAS_INLINE const_reverse_iterator crend() const { return end(); } + BOOST_UBLAS_INLINE value_type operator()(size_type index) { return value_type(matrix_, index); } + BOOST_UBLAS_INLINE value_type operator()(size_type index) const { return value_type(matrix_, index); } + BOOST_UBLAS_INLINE reference operator[](size_type index){ return (*this) (index); } + BOOST_UBLAS_INLINE const_reference operator[](size_type index) const { return (*this) (index); } + BOOST_UBLAS_INLINE size_type size() const { return matrix_.size1(); } + BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { matrix_.resize(size, matrix_.size2(), preserve); } @@ -200,6 +228,7 @@ class matrix_row_vector { * \tparam Matrix the type of matrix that \c matrix_row_vector is referring. */ template +BOOST_UBLAS_INLINE matrix_row_vector make_row_vector(matrix_expression& matrix){ return matrix_row_vector(matrix()); } @@ -214,6 +243,7 @@ matrix_row_vector make_row_vector(matrix_expression& matrix){ * \tparam Matrix the type of matrix that \c matrix_row_vector is referring. */ template +BOOST_UBLAS_INLINE matrix_row_vector make_row_vector(matrix_expression const& matrix){ return matrix_row_vector(matrix()); } @@ -243,78 +273,97 @@ class matrix_column_vector typedef typename boost::iterator_difference::type difference_type; typedef typename Matrix::size_type size_type; + BOOST_UBLAS_INLINE matrix_column_vector(Matrix& matrix) : matrix_(matrix){ } + BOOST_UBLAS_INLINE iterator begin() { return iterator(matrix_, 0); } + BOOST_UBLAS_INLINE const_iterator begin() const { return const_iterator(matrix_, 0); } + BOOST_UBLAS_INLINE const_iterator cbegin() const { return begin(); } + BOOST_UBLAS_INLINE iterator end() { return iterator(matrix_, matrix_.size2()); } + BOOST_UBLAS_INLINE const_iterator end() const { return const_iterator(matrix_, matrix_.size2()); } + BOOST_UBLAS_INLINE const_iterator cend() const { return end(); } + BOOST_UBLAS_INLINE reverse_iterator rbegin() { return reverse_iterator(end()); } + BOOST_UBLAS_INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + BOOST_UBLAS_INLINE const_reverse_iterator crbegin() const { return rbegin(); - } + } + BOOST_UBLAS_INLINE reverse_iterator rend() { return reverse_iterator(begin()); } + BOOST_UBLAS_INLINE const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + BOOST_UBLAS_INLINE const_reverse_iterator crend() const { return rend(); } + BOOST_UBLAS_INLINE value_type operator()(size_type index) { return value_type(matrix_, index); } + BOOST_UBLAS_INLINE value_type operator()(size_type index) const { return value_type(matrix_, index); } + BOOST_UBLAS_INLINE reference operator[](size_type index) { return (*this) (index); } + BOOST_UBLAS_INLINE const_reference operator[](size_type index) const { return (*this) (index); } + BOOST_UBLAS_INLINE size_type size() const { return matrix_.size2(); } + BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { matrix_.resize(matrix_.size1(), size, preserve); } @@ -333,6 +382,7 @@ class matrix_column_vector * \tparam Matrix the type of matrix that \c matrix_column_vector is referring. */ template +BOOST_UBLAS_INLINE matrix_column_vector make_column_vector(matrix_expression& matrix){ return matrix_column_vector(matrix()); } @@ -347,6 +397,7 @@ matrix_column_vector make_column_vector(matrix_expression& matri * \tparam Matrix the type of matrix that \c matrix_column_vector is referring. */ template +BOOST_UBLAS_INLINE matrix_column_vector make_column_vector(matrix_expression const& matrix){ return matrix_column_vector(matrix()); } From b4561a86b34f46e94d1ca46eda8f78906adb51aa Mon Sep 17 00:00:00 2001 From: qduran Date: Tue, 25 Aug 2015 20:03:08 +0200 Subject: [PATCH 21/73] Fixed type conversion in test_fixed_containers. Fixed variadic template constructor in fixed_vector and fixed_matrix. Reordered constructors in fixed_matrix. --- include/boost/numeric/ublas/matrix.hpp | 17 ++--- include/boost/numeric/ublas/vector.hpp | 17 ++--- test/test_fixed_containers.cpp | 90 +++++++++++++++++--------- 3 files changed, 72 insertions(+), 52 deletions(-) mode change 100644 => 100755 include/boost/numeric/ublas/matrix.hpp mode change 100644 => 100755 include/boost/numeric/ublas/vector.hpp mode change 100644 => 100755 test/test_fixed_containers.cpp diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp old mode 100644 new mode 100755 index aeaa3bb7a..b079bd316 --- a/include/boost/numeric/ublas/matrix.hpp +++ b/include/boost/numeric/ublas/matrix.hpp @@ -1234,14 +1234,6 @@ namespace boost { namespace numeric { matrix_container (), data_ () {} - /// \brief Construct a fixed_matrix from a list of values - /// The list may be included in curly braces. Typical syntax is choices are : - /// fixed_matrix v = { 1, 2, 3, 4 } or fixed_matrix v( {1, 2, 3, 4} ) or fixed_matrix v( 1, 2, 3, 4 ) - template - fixed_matrix(value_type v0, Types... vrest) : - matrix_container (), - data_{ { v0, vrest... } } {} - /** Dense fixed_matrix constructor with defined initial value for all the matrix elements * \param init initial value assigned to all elements */ @@ -1278,6 +1270,15 @@ namespace boost { namespace numeric { matrix_assign (*this, ae); } + /// \brief Construct a fixed_matrix from a list of values + /// The list may be included in curly braces. Typical syntax is choices are : + /// fixed_matrix v = { 1, 2, 3, 4 } or fixed_matrix v( {1, 2, 3, 4} ) or fixed_matrix v( 1, 2, 3, 4 ) + template + BOOST_UBLAS_INLINE + fixed_matrix(value_type v0, Types... vrest) : + matrix_container (), + data_( array_type{ v0, vrest... } ) {} + // Accessors /** Return the number of rows of the fixed_matrix * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a fixed_matrix diff --git a/include/boost/numeric/ublas/vector.hpp b/include/boost/numeric/ublas/vector.hpp old mode 100644 new mode 100755 index c1384c145..73a387dcd --- a/include/boost/numeric/ublas/vector.hpp +++ b/include/boost/numeric/ublas/vector.hpp @@ -903,21 +903,14 @@ namespace boost { namespace numeric { namespace ublas { vector_assign (*this, ae); } - /// \brief Construct a fixed_vector from a list of values - /// This constructor enables initialization by using any of: - /// fixed_vector v = { 1, 2, 3 } or fixed_vector v( {1, 2, 3} ) or fixed_vector v( 1, 2, 3 ) -#if defined(BOOST_MSVC) - // This may or may not work. Maybe use this for all instead only for MSVC - template - fixed_vector(U&&... values) : - vector_container (), - data_{{ std::forward(values)... }} {} -#else + /// \brief Construct a fixed_vector from a list of values + /// This constructor enables initialization by using any of: + /// fixed_vector v = { 1, 2, 3 } or fixed_vector v( {1, 2, 3} ) or fixed_vector v( 1, 2, 3 ) template + BOOST_UBLAS_INLINE fixed_vector(value_type v0, Types... vrest) : vector_container (), - data_{ { v0, vrest... } } {} -#endif + data_( array_type{ v0, vrest... } ) {} // ----------------------- // Random Access Container diff --git a/test/test_fixed_containers.cpp b/test/test_fixed_containers.cpp old mode 100644 new mode 100755 index 0cc0b8be1..1a706acda --- a/test/test_fixed_containers.cpp +++ b/test/test_fixed_containers.cpp @@ -16,9 +16,23 @@ using namespace boost::numeric::ublas; using std::cout; using std::endl; + +template +struct data_type { + typedef T value_type; +}; + +template +struct data_type< std::complex > { + typedef typename std::complex::value_type value_type; +}; + + template < class T > bool test_vector( std::string type_name) { + typedef typename data_type::value_type component_type; + BOOST_UBLAS_DEBUG_TRACE( std::string("Testing for: ") + type_name ); bool pass = true; @@ -26,34 +40,36 @@ bool test_vector( std::string type_name) { typedef fixed_vector vec1; - vec1 v1( 122.0 ); + vec1 v1( static_cast(122.0) ); - pass &= ( v1(0) == (T)122 ); + pass &= ( v1(0) == static_cast(122.0) ); } { typedef fixed_vector vec3; - vec3 v1((T)0.0, (T)0.0, (T)0.0); + vec3 v1(static_cast(0.0), + static_cast(0.0), + static_cast(0.0)); - pass &=(sizeof( vec3 ) == v1.size()*sizeof( T ) ) ; + pass &=(sizeof( vec3 ) == v1.size() * sizeof( T ) ) ; vector v( 3, 0 ) ; pass &= compare( v1, v ); - v1 <<= 10.0, 10, 33; - v <<= 10.0, 10, 33; - - //cout << std::setprecision(20) << v1 << '\n' << v; + v1 <<= static_cast(10.0), 10, 33; + v <<= static_cast(10.0), 10, 33; pass &= compare( v1, v ); vec3 v2; - v2( 0 ) = 10.0; v2( 1 ) = 10; v2( 2 ) = 33; + v2( 0 ) = static_cast(10.0); + v2( 1 ) = 10; + v2( 2 ) = 33; pass &= compare( v, v2 ); v2 += v; @@ -65,16 +81,24 @@ bool test_vector( std::string type_name) pass &= compare( v1, (3-2*6)*v ); - vec3 v3{ (T)-90.0, (T)-90.0, (T)-297.0 }; + vec3 v3{ static_cast(-90.0), + static_cast(-90.0), + static_cast(-297.0) }; pass &= compare( v3, v1 ); - vec3 v4 = { (T)-90.0, (T)-90.0, (T)-297.0 }; + vec3 v4 = { static_cast(-90.0), + static_cast(-90.0), + static_cast(-297.0) }; pass &= compare( v4, v1 ); - vec3 v5( (T)-90.0, (T)-90.0, (T)-297.0 ); + vec3 v5( static_cast(-90.0), + static_cast(-90.0), + static_cast(-297.0) ); pass &= compare( v5, v1 ); - vec3 v6((T) 5.0, (T)8.0, (T)9.0); + vec3 v6( static_cast(5.0), + static_cast(8.0), + static_cast(9.0) ); matrix M = outer_prod( v6, v6), L( 3, 3); @@ -84,15 +108,15 @@ bool test_vector( std::string type_name) L <<= 1, 2, 3, 4, 5, 6, 7, 8, 9; v6 <<= 4, 5, 6; - vec3 v7 ( (T)32.0, (T)77.0, (T)122.0 ); + vec3 v7 ( static_cast(32.0), + static_cast(77.0), + static_cast(122.0) ); pass &= compare( v7, prod(L, v6) ); - vec3 v8; - noalias( v8 ) = prod(L, v6); + vec3 v8(prod(L, v6)); pass &= compare( v7, v8 ); - } @@ -103,10 +127,10 @@ bool test_vector( std::string type_name) vec33 v1; vector v( N ); - for ( std::size_t i = 0; i!= v1.size(); i++) + for ( std::size_t i = 0; i != v1.size(); i++) { - v1( i ) = 3.14159*i; - v ( i ) = 3.14159*i; + v1( i ) = static_cast(3.14159*i); + v ( i ) = static_cast(3.14159*i); } pass &= compare( v1, v ); @@ -115,7 +139,7 @@ bool test_vector( std::string type_name) auto ip = inner_prod( v, v); auto ip1 = inner_prod( v1, v1); - pass &= ( ip == ip1 ) ; + pass &= ( ip == ip1 ) ; T c = 0; for (auto i = v1.begin(); i != v1.end(); i++) @@ -152,6 +176,8 @@ bool test_vector( std::string type_name) template < class T > bool test_matrix( std::string type_name) { + typedef typename data_type::value_type component_type; + BOOST_UBLAS_DEBUG_TRACE( std::string("Testing for: ") + type_name ); bool pass = true; @@ -164,18 +190,18 @@ bool test_matrix( std::string type_name) { typedef fixed_matrix mat1; - mat1 m1( 122.0 ); + mat1 m1( static_cast(122.0) ); - pass &= ( m1(0, 0) == (T)122 ); + pass &= ( m1(0, 0) == static_cast(122.0) ); } { - mat34 m1( 3.0 ); + mat34 m1( T(static_cast(3.0)) ); - pass &=(sizeof( mat34 ) == m1.size1()*m1.size2()*sizeof( T ) ) ; + pass &=(sizeof( mat34 ) == m1.size1()*m1.size2()*sizeof( T ) ) ; - matrix m( 3.0, 4.0, 3.0 ) ; + matrix m( 3, 4, static_cast(3.0) ) ; pass &= compare( m1, m ); @@ -191,7 +217,7 @@ bool test_matrix( std::string type_name) cout << m1 << endl; cout << m << endl; - mat34 m2( 0.0 ); + mat34 m2( static_cast(0.0) ); T count = 1 ; for ( std::size_t i = 0; i != m2.size1(); i++) @@ -208,10 +234,10 @@ bool test_matrix( std::string type_name) } { - mat34 m1 = { (T)1, (T)2, (T)3, (T)3, (T)3, (T)2, (T)5, (T)4, (T)2, (T)6, (T)5, (T)2 }; - mat43 m2 = { (T)4, (T)5, (T)6, (T)3, (T)2, (T)2, (T)1, (T)4, (T)2, (T)6, (T)5, (T)2 }; + mat34 m1((T)1, (T)2, (T)3, (T)3, (T)3, (T)2, (T)5, (T)4, (T)2, (T)6, (T)5, (T)2); + mat43 m2((T)4, (T)5, (T)6, (T)3, (T)2, (T)2, (T)1, (T)4, (T)2, (T)6, (T)5, (T)2); - mat33 m3 = prod(m1, m2); + mat33 m3(prod(m1, m2)); matrix m(3, 3); m <<= 31,36,22,47,59,40,43,52,38; @@ -220,7 +246,7 @@ bool test_matrix( std::string type_name) mat33 m4; m4 <<= (T)1, (T)2, (T)1, (T)2, (T)1, (T)3, (T)1, (T)2, (T) 5; - m3 = prod(m4, trans(m4)); + m3 = prod(m4, trans(m4)); m<<=6,7,10,7,14,19,10,19,30; @@ -229,7 +255,7 @@ bool test_matrix( std::string type_name) m3 = 2 * m4 - 1 * m3; - cout << m3; + cout << m3 << endl; m <<= -4,-3,-8,-3,-12,-13,-8,-15,-20; From c606ddb07565ac51b8d9205c524d362cb6ec6459 Mon Sep 17 00:00:00 2001 From: qduran Date: Wed, 26 Aug 2015 01:10:08 +0200 Subject: [PATCH 22/73] Fix file permissions. --- include/boost/numeric/ublas/matrix.hpp | 0 include/boost/numeric/ublas/vector.hpp | 0 test/test_fixed_containers.cpp | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 include/boost/numeric/ublas/matrix.hpp mode change 100755 => 100644 include/boost/numeric/ublas/vector.hpp mode change 100755 => 100644 test/test_fixed_containers.cpp diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp old mode 100755 new mode 100644 diff --git a/include/boost/numeric/ublas/vector.hpp b/include/boost/numeric/ublas/vector.hpp old mode 100755 new mode 100644 diff --git a/test/test_fixed_containers.cpp b/test/test_fixed_containers.cpp old mode 100755 new mode 100644 From 5699c16bcde8c277063f66aa058cbadb5614278a Mon Sep 17 00:00:00 2001 From: qduran Date: Thu, 27 Aug 2015 02:52:09 +0200 Subject: [PATCH 23/73] For MSVC compliers, unabled warning C4996 (undo previous commit) --- test/Jamfile.v2 | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b081edd6e..eb5623e0e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -63,7 +63,6 @@ test-suite numeric/uBLAS : # input files : # requirements $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test2.cpp test21.cpp @@ -71,7 +70,6 @@ test-suite numeric/uBLAS test23.cpp : : : $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test3.cpp test31.cpp @@ -79,7 +77,6 @@ test-suite numeric/uBLAS test33.cpp : : : $(UBLAS_TESTSET_SPARSE) - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test3.cpp test31.cpp @@ -87,7 +84,6 @@ test-suite numeric/uBLAS test33.cpp : : : $(UBLAS_TESTSET_SPARSE_COO) - msvc:_SCL_SECURE_NO_WARNINGS : test3_coo : ] @@ -109,21 +105,18 @@ test-suite numeric/uBLAS test43.cpp : : : $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test5.cpp test52.cpp test53.cpp : : : $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test6.cpp test62.cpp test63.cpp : : : $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS ] # Test commented out because boost::interval does not behave like a scalar type # [ run test7.cpp @@ -147,7 +140,6 @@ test-suite numeric/uBLAS ] [ run test_lu.cpp : : : - msvc:_SCL_SECURE_NO_WARNINGS ] [ run triangular_access.cpp : : : @@ -157,12 +149,9 @@ test-suite numeric/uBLAS ] [ run comp_mat_erase.cpp : : : - msvc:_SCL_SECURE_NO_WARNINGS msvc:on ] [ run sparse_view_test.cpp - : : : - msvc:_SCL_SECURE_NO_WARNINGS ] [ run begin_end.cpp ] @@ -186,14 +175,11 @@ test-suite numeric/uBLAS [ run test_assignment.cpp : : : BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT - msvc:_SCL_SECURE_NO_WARNINGS - : : ] [ run test_triangular.cpp : : : /boost/timer//boost_timer - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test_ticket7296.cpp ] @@ -201,7 +187,6 @@ test-suite numeric/uBLAS : : : $(UBLAS_TESTSET) - msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_basic : ] @@ -210,7 +195,6 @@ test-suite numeric/uBLAS : : $(UBLAS_TESTSET_SPARSE) $(UBLAS_TESTSET_SPARSE_COO) - msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_sparse : ] @@ -218,17 +202,12 @@ test-suite numeric/uBLAS : : : USE_MAPPED_VECTOR_OF_MAPPED_VECTOR - msvc:_SCL_SECURE_NO_WARNINGS : test_inplace_solve_mvov : ] [ run test_coordinate_vector_inplace_merge.cpp - : : : - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test_coordinate_matrix_inplace_merge.cpp - : : : - msvc:_SCL_SECURE_NO_WARNINGS ] [ run test_banded_storage_layout.cpp : @@ -243,7 +222,5 @@ test-suite numeric/uBLAS : ] [ run test_matrix_vector.cpp - : : : - msvc:_SCL_SECURE_NO_WARNINGS ] ; From e3c9bc79338d5bb22bce652acb847be28053ad7c Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Thu, 1 Oct 2015 02:10:14 +0200 Subject: [PATCH 24/73] The type of the distance of matrices and vectors is deduced. --- test/common/testhelper.hpp | 48 +++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/test/common/testhelper.hpp b/test/common/testhelper.hpp index 6dadbf2af..5af53cd64 100644 --- a/test/common/testhelper.hpp +++ b/test/common/testhelper.hpp @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include static unsigned _success_counter = 0; static unsigned _fail_counter = 0; @@ -85,33 +88,56 @@ bool compare( const boost::numeric::ublas::vector_expression & m1, // Compare if two matrices or vectors are equals based on distance. +template +struct promote_distance { + typedef typename boost::mpl::if_c::value, + long double, + T>::type type; +}; + +template +struct distance { +private: + typedef typename boost::numeric::ublas::promote_traits::promote_type value_type; + +public: + typedef typename promote_distance::type type; +}; + +template +struct distance { + typedef typename promote_distance::type type; +}; + + template -typename AE::value_type mean_square(const boost::numeric::ublas::matrix_expression &me) { - typename AE::value_type s(0); +typename distance::type mean_square(const boost::numeric::ublas::matrix_expression &me) { + typename distance::type s(0); typename AE::size_type i, j; for (i=0; i!= me().size1(); i++) { for (j=0; j!= me().size2(); j++) { s += boost::numeric::ublas::scalar_traits::type_abs(me()(i,j)); } } - return static_cast(s / (me().size1() * me().size2())); + return s / (me().size1() * me().size2()); } template -typename AE::value_type mean_square(const boost::numeric::ublas::vector_expression &ve) { +typename distance::type mean_square(const boost::numeric::ublas::vector_expression &ve) { // We could have use norm2 here, but ublas' ABS does not support unsigned types. - typename AE::value_type s(0); + typename distance::type s(0); typename AE::size_type i; - for (i=0; i!= ve().size(); i++) { + for (i = 0; i != ve().size(); i++) { s += boost::numeric::ublas::scalar_traits::type_abs(ve()(i)); } - return static_cast(s / ve().size()); + return s / ve().size(); } template < class M1, class M2 > bool compare_distance( const boost::numeric::ublas::matrix_expression & m1, - const boost::numeric::ublas::matrix_expression & m2, - double tolerance = 0.0 ) { + const boost::numeric::ublas::matrix_expression & m2, + typename distance::type tolerance = 0 ) { if ((m1().size1() != m2().size1()) || (m1().size2() != m2().size2())) { return false; @@ -122,8 +148,8 @@ bool compare_distance( const boost::numeric::ublas::matrix_expression & m1, template < class M1, class M2 > bool compare_distance( const boost::numeric::ublas::vector_expression & m1, - const boost::numeric::ublas::vector_expression & m2, - double tolerance = 0.0 ) { + const boost::numeric::ublas::vector_expression & m2, + typename distance::type tolerance = 0 ) { if (m1().size() != m2().size()) { return false; } From 6881b5189ecdb8f97197894112e5099cf93a10d3 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 12 Oct 2015 00:45:37 +0200 Subject: [PATCH 25/73] In matrix_sparse: remove the name of unused parameters to avoid warnings. --- include/boost/numeric/ublas/matrix_sparse.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/numeric/ublas/matrix_sparse.hpp b/include/boost/numeric/ublas/matrix_sparse.hpp index b70274334..d9677540d 100644 --- a/include/boost/numeric/ublas/matrix_sparse.hpp +++ b/include/boost/numeric/ublas/matrix_sparse.hpp @@ -1461,7 +1461,7 @@ namespace boost { namespace numeric { namespace ublas { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); } BOOST_UBLAS_INLINE - mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0): + mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type /*non_zeros*/ = 0): matrix_container (), size1_ (size1), size2_ (size2), data_ () { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); @@ -1472,7 +1472,7 @@ namespace boost { namespace numeric { namespace ublas { size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} template BOOST_UBLAS_INLINE - mapped_vector_of_mapped_vector (const matrix_expression &ae, size_type non_zeros = 0): + mapped_vector_of_mapped_vector (const matrix_expression &ae, size_type /*non_zeros*/ = 0): matrix_container (), size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); From 6227919917ee6f10e724af1ce3bdbcbcb960469b Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 18 Oct 2015 00:44:47 +0200 Subject: [PATCH 26/73] test42.cpp: Fixed warnings about unused parameters. --- test/test42.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test42.cpp b/test/test42.cpp index a1fd3f278..d284e6854 100644 --- a/test/test42.cpp +++ b/test/test42.cpp @@ -11,6 +11,7 @@ // #include "test4.hpp" +#include "utils.hpp" // Test matrix & vector expression templates template @@ -45,6 +46,10 @@ struct test_my_matrix_vector { std::cout << "prod (m1, v1) = " << v2 << std::endl; v2 = ublas::prod (v1, m1); std::cout << "prod (v1, m1) = " << v2 << std::endl; +#else + BOOST_UBLAS_NOT_USED(v1); + BOOST_UBLAS_NOT_USED(v2); + BOOST_UBLAS_NOT_USED(m1); #endif } } From 1c2cf5dcf24033332ecc59e5b9727f5452eb583c Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 18 Oct 2015 00:51:18 +0200 Subject: [PATCH 27/73] testhelper: fixed warnings about unused parameters. --- test/common/testhelper.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/common/testhelper.hpp b/test/common/testhelper.hpp index 5af53cd64..4bc152ca3 100644 --- a/test/common/testhelper.hpp +++ b/test/common/testhelper.hpp @@ -22,6 +22,8 @@ static inline void assertTrue(const char* message, bool condition) { #ifndef NOMESSAGES std::cout << message; +#else + (void)message; #endif if ( condition ) { ++ _success_counter; @@ -36,6 +38,8 @@ template < class T > void assertEquals(const char* message, T expected, T actual) { #ifndef NOMESSAGES std::cout << message; +#else + (void)message; #endif if ( expected == actual ) { ++ _success_counter; From 2c0f251d9e841a97bc12dfdc9abc189de2dfe7c0 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 19 Oct 2015 23:04:50 +0200 Subject: [PATCH 28/73] In test_matrix_vector, unnedded return statement has been removed. --- test/test_matrix_vector.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_matrix_vector.cpp b/test/test_matrix_vector.cpp index 22266d717..586028737 100644 --- a/test/test_matrix_vector.cpp +++ b/test/test_matrix_vector.cpp @@ -453,6 +453,4 @@ int main () { BOOST_UBLAS_TEST_DO( test_matrix_column_facade ); BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS;; } From 54af3fbf7c34f54964f67163b94be35e7b84c9a7 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 19 Oct 2015 23:24:21 +0200 Subject: [PATCH 29/73] utils.hpp: the values of the result of the test are assigned using EXIT macros. --- test/utils.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils.hpp b/test/utils.hpp index c1b69b92a..65708e17e 100644 --- a/test/utils.hpp +++ b/test/utils.hpp @@ -219,12 +219,12 @@ bool rel_close_to(::std::complex const& x, ::std::complex const& y, T3 t if (test_fails__ > 0) \ { \ ::std::cerr << "Number of failed tests: " << test_fails__ << ::std::endl; \ - return 1; \ + return EXIT_FAILURE; \ } \ else \ { \ ::std::cerr << "No failed test" << ::std::endl; \ - return 0; \ + return EXIT_SUCCESS; \ } \ } /* End of test suite */ \ /* [/BOOST_UBLAS_TEST_END] */ From 96c2547a1f670dca53e1bbb24a883d86ec796989 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Thu, 22 Oct 2015 02:14:01 +0200 Subject: [PATCH 30/73] Fixed issues in Qt build system: - Fixed libraries and include paths. - In windows, the filename of the tests programs (to be executed after compilation) has been fixed. - In windows, all tests programs and benchmark programs are compiled as console programs. - In windows, the warning C4996 has been disabled. - In windows, asyncronous exceptions are captured in comp_mat_erase test. --- IDEs/qtcreator/benchmarks/configuration.pri | 4 +++- IDEs/qtcreator/test/comp_mat_erase.pro | 2 ++ IDEs/qtcreator/test/configuration.pri | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/IDEs/qtcreator/benchmarks/configuration.pri b/IDEs/qtcreator/benchmarks/configuration.pri index d25d7e40a..a7bc632a1 100644 --- a/IDEs/qtcreator/benchmarks/configuration.pri +++ b/IDEs/qtcreator/benchmarks/configuration.pri @@ -1,5 +1,6 @@ CONFIG -= qt CONFIG += depend_includepath +win*: CONFIG += console # ublas include directory INCLUDEPATH += \ @@ -9,5 +10,6 @@ INCLUDEPATH += \ # then boost headers and boost libraries should be used. exists(../../../../../../boost-build.jam) { INCLUDEPATH += ../../../../../../.. - #LIBS += -L../../../../../../../stage/lib + LIBS += -L../../../../../../../stage/lib + QMAKE_RPATHDIR += ../../../../../../../stage/lib } diff --git a/IDEs/qtcreator/test/comp_mat_erase.pro b/IDEs/qtcreator/test/comp_mat_erase.pro index d5b766757..b61828bc4 100644 --- a/IDEs/qtcreator/test/comp_mat_erase.pro +++ b/IDEs/qtcreator/test/comp_mat_erase.pro @@ -1,6 +1,8 @@ TEMPLATE = app TARGET = comp_mat_erase +win*: QMAKE_CXXFLAGS += /EHa + include (configuration.pri) SOURCES += \ diff --git a/IDEs/qtcreator/test/configuration.pri b/IDEs/qtcreator/test/configuration.pri index 3fdb4aa52..8233c9b34 100644 --- a/IDEs/qtcreator/test/configuration.pri +++ b/IDEs/qtcreator/test/configuration.pri @@ -2,6 +2,8 @@ CONFIG -= qt CONFIG += \ depend_includepath \ debug +win*: CONFIG += console + QMAKE_CXXFLAGS += -fno-inline # Create a directory for each test. @@ -29,13 +31,15 @@ UBLAS_TESTSET_SPARSE_COO = \ DEFINES += BOOST_UBLAS_NO_EXCEPTIONS +win*: DEFINES += _SCL_SECURE_NO_WARNINGS + #Visual age IBM xlc: DEFINES += BOOST_UBLAS_NO_ELEMENT_PROXIES # ublas include and test directory are included INCLUDEPATH += \ ../../../include \ - ../../test + ../../../test # If ublas tests are build with boost source code then, # then boost headers and boost libraries should be used. @@ -46,6 +50,6 @@ exists(../../../../../../boost-build.jam) { } # Execute test once compiled. -win32: QMAKE_POST_LINK = ./$${DESTDIR}/$${TARGET}.exe +win*: QMAKE_POST_LINK = .\\$${DESTDIR}\\$${TARGET}.exe else: QMAKE_POST_LINK = ./$${DESTDIR}/$${TARGET} From 701619a67db8751f6b9e530f4c961dff43b0476b Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 25 Oct 2015 02:41:37 +0100 Subject: [PATCH 31/73] - In the test sparse_view_test.cpp, the asyncronous exceptions are captured in bjam and Qt build system. - In bjam build system, the warning C4996 has been disabled in all tests. --- IDEs/qtcreator/test/sparse_view_test.pro | 2 ++ test/Jamfile.v2 | 3 +++ 2 files changed, 5 insertions(+) diff --git a/IDEs/qtcreator/test/sparse_view_test.pro b/IDEs/qtcreator/test/sparse_view_test.pro index 0a84afa70..adfff586b 100644 --- a/IDEs/qtcreator/test/sparse_view_test.pro +++ b/IDEs/qtcreator/test/sparse_view_test.pro @@ -1,6 +1,8 @@ TEMPLATE = app TARGET = sparse_view_test +QMAKE_CXXFLAGS += /EHa + include (configuration.pri) SOURCES += \ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index eb5623e0e..6d6398837 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -51,6 +51,7 @@ project : requirements BOOST_UBLAS_NO_EXCEPTIONS vacpp:"BOOST_UBLAS_NO_ELEMENT_PROXIES" + msvc:_SCL_SECURE_NO_WARNINGS ; @@ -152,6 +153,8 @@ test-suite numeric/uBLAS msvc:on ] [ run sparse_view_test.cpp + : : : + msvc:on ] [ run begin_end.cpp ] From 8886f24389ec3a555ef53d3d92449c1b09921415 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 25 Oct 2015 19:15:35 +0100 Subject: [PATCH 32/73] - boost_numeric_ublas_sqrt (const T& t): if the type T is integuer, it returns a double. If not, it returns the type T. - vector_norm_2: casted the return value of function type_sqrt to the return type of vector_norm_2. --- include/boost/numeric/ublas/functional.hpp | 12 ++++++------ include/boost/numeric/ublas/traits.hpp | 8 +++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index c7c92614c..10c6ea6b4 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -441,7 +441,7 @@ namespace boost { namespace numeric { namespace ublas { real_type u (type_traits::norm_2 (e () (i))); t += u * u; } - return type_traits::type_sqrt (t); + return static_cast(type_traits::type_sqrt (t)); #else real_type scale = real_type (); real_type sum_squares (1); @@ -458,7 +458,7 @@ namespace boost { namespace numeric { namespace ublas { sum_squares += v * v; } } - return scale * type_traits::type_sqrt (sum_squares); + return static_cast(scale * type_traits::type_sqrt (sum_squares)); #endif } // Dense case @@ -472,7 +472,7 @@ namespace boost { namespace numeric { namespace ublas { t += u * u; ++ it; } - return type_traits::type_sqrt (t); + return static_cast(type_traits::type_sqrt (t)); #else real_type scale = real_type (); real_type sum_squares (1); @@ -488,7 +488,7 @@ namespace boost { namespace numeric { namespace ublas { } ++ it; } - return scale * type_traits::type_sqrt (sum_squares); + return static_cast(scale * type_traits::type_sqrt (sum_squares)); #endif } // Sparse case @@ -502,7 +502,7 @@ namespace boost { namespace numeric { namespace ublas { t += u * u; ++ it; } - return type_traits::type_sqrt (t); + return static_cast(type_traits::type_sqrt (t)); #else real_type scale = real_type (); real_type sum_squares (1); @@ -518,7 +518,7 @@ namespace boost { namespace numeric { namespace ublas { } ++ it; } - return scale * type_traits::type_sqrt (sum_squares); + return static_cast(scale * type_traits::type_sqrt (sum_squares)); #endif } }; diff --git a/include/boost/numeric/ublas/traits.hpp b/include/boost/numeric/ublas/traits.hpp index ecd52cad8..56fe5fd43 100644 --- a/include/boost/numeric/ublas/traits.hpp +++ b/include/boost/numeric/ublas/traits.hpp @@ -32,10 +32,16 @@ #include #include #include +#include + // anonymous namespace to avoid ADL issues namespace { - template T boost_numeric_ublas_sqrt (const T& t) { + template + typename boost::mpl::if_c::value, + double, + T>::type + boost_numeric_ublas_sqrt (const T& t) { using namespace std; // we'll find either std::sqrt or else another version via ADL: return sqrt (t); From c0a60f52123c2402f22abe22007c685b1f95b3d4 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sat, 31 Oct 2015 17:40:22 +0100 Subject: [PATCH 33/73] Remove redundant return statements in test_fixed_containers test. --- test/test_fixed_containers.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/test_fixed_containers.cpp b/test/test_fixed_containers.cpp index 1a706acda..76f5a2886 100644 --- a/test/test_fixed_containers.cpp +++ b/test/test_fixed_containers.cpp @@ -313,8 +313,6 @@ int main () { BOOST_UBLAS_TEST_DO( test_fixed ); BOOST_UBLAS_TEST_END(); - return EXIT_SUCCESS; - } #else @@ -323,8 +321,5 @@ int main () { BOOST_UBLAS_TEST_BEGIN(); BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS; - } #endif // BOOST_UBLAS_CPP_GE_2011 From 78a8e3371fc8f045ccfcaf45b02575ee308bf284 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sat, 31 Oct 2015 17:43:39 +0100 Subject: [PATCH 34/73] Matrix_column_vector and column_row_vector are noncopiable classes (clear warning C4512). Add explicit word in the construtor of each class. --- include/boost/numeric/ublas/matrix_vector.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/numeric/ublas/matrix_vector.hpp b/include/boost/numeric/ublas/matrix_vector.hpp index 5eb37184e..6498b4cc4 100644 --- a/include/boost/numeric/ublas/matrix_vector.hpp +++ b/include/boost/numeric/ublas/matrix_vector.hpp @@ -9,7 +9,8 @@ #ifndef BOOST_UBLAS_MATRIX_VECTOR_HPP #define BOOST_UBLAS_MATRIX_VECTOR_HPP -#include //for matrix_row, matrix_column and matrix_expression +#include +#include //for matrix_row, matrix_column and matrix_expression #include #include #include @@ -105,7 +106,7 @@ class matrix_vector_iterator: public boost::iterator_facade< * the underlaying matrix. */ template -class matrix_row_vector { +class matrix_row_vector: private boost::noncopyable { public: typedef ublas::matrix_row value_type; typedef ublas::matrix_row reference; @@ -120,7 +121,7 @@ class matrix_row_vector { typedef typename Matrix::size_type size_type; BOOST_UBLAS_INLINE - matrix_row_vector(Matrix& matrix) : + explicit matrix_row_vector(Matrix& matrix) : matrix_(matrix) { } @@ -258,8 +259,7 @@ matrix_row_vector make_row_vector(matrix_expression const& * the underlaying matrix. */ template -class matrix_column_vector -{ +class matrix_column_vector: private boost::noncopyable { public: typedef ublas::matrix_column value_type; typedef ublas::matrix_column reference; @@ -274,7 +274,7 @@ class matrix_column_vector typedef typename Matrix::size_type size_type; BOOST_UBLAS_INLINE - matrix_column_vector(Matrix& matrix) : + explicit matrix_column_vector(Matrix& matrix) : matrix_(matrix){ } From 9231cb4287e4e11914faa9ecd4ed7fa7f0651d56 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sat, 31 Oct 2015 17:47:50 +0100 Subject: [PATCH 35/73] In storage.hpp, add a null expression for a parameter to clear unused parameter warning (The expression could confuse the compiler). --- include/boost/numeric/ublas/storage.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index bd648925a..f5b625db5 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -303,6 +303,7 @@ namespace boost { namespace numeric { namespace ublas { // Handle explict destroy on a (possibly indexed) iterator BOOST_UBLAS_INLINE static void iterator_destroy (iterator &i) { + (void)(i); (&(*i)) -> ~value_type (); } ALLOC alloc_; From 281cf37d292adb7ce0145803c17550e716e050e4 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 1 Nov 2015 01:59:36 +0100 Subject: [PATCH 36/73] In test sparse_view_test, only the msvc compilers need the support for asynchronous structured exception handling. --- IDEs/qtcreator/test/sparse_view_test.pro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/IDEs/qtcreator/test/sparse_view_test.pro b/IDEs/qtcreator/test/sparse_view_test.pro index adfff586b..cd8172c98 100644 --- a/IDEs/qtcreator/test/sparse_view_test.pro +++ b/IDEs/qtcreator/test/sparse_view_test.pro @@ -1,7 +1,9 @@ TEMPLATE = app TARGET = sparse_view_test -QMAKE_CXXFLAGS += /EHa +win*:QMAKE_CXXFLAGS += /EHa +# Support asynchronous structured exception handling +# (SEH) with the native C++ catch(...) clause. include (configuration.pri) From ed4cbeb7a3a3f704d15a1ba230b63b8eb6265ecd Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 6 Nov 2015 00:48:06 +0100 Subject: [PATCH 37/73] Vector_expression_assigner and matrix_expression_assigner are noncopyable classes (clear warning C4512). --- include/boost/numeric/ublas/assignment.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/numeric/ublas/assignment.hpp b/include/boost/numeric/ublas/assignment.hpp index d2079e13d..838fe0a28 100644 --- a/include/boost/numeric/ublas/assignment.hpp +++ b/include/boost/numeric/ublas/assignment.hpp @@ -8,6 +8,8 @@ #ifndef ASSIGNMENT_HPP #define ASSIGNMENT_HPP + +#include #include #include @@ -920,7 +922,7 @@ namespace traverse_policy { * \todo Add examples link */ template -class vector_expression_assigner { +class vector_expression_assigner : private boost::noncopyable { public: typedef typename E::expression_type::value_type value_type; typedef typename E::expression_type::size_type size_type; @@ -1096,7 +1098,7 @@ vector_expression_assigner, T> operator<<=(vector_expressio * \todo Add examples link */ template -class matrix_expression_assigner { +class matrix_expression_assigner : private boost::noncopyable { public: typedef typename E::expression_type::size_type size_type; From b8a7853df8a617c2946772a404670709a5b0694c Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 6 Nov 2015 01:30:01 +0100 Subject: [PATCH 38/73] Removed redundant return statement in four tests. --- test/test_assignment.cpp | 2 -- test/test_banded_storage_layout.cpp | 6 +----- test/test_coordinate_matrix_inplace_merge.cpp | 2 -- test/test_coordinate_vector_inplace_merge.cpp | 2 -- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/test/test_assignment.cpp b/test/test_assignment.cpp index 78fe2c314..ab8be58c6 100644 --- a/test/test_assignment.cpp +++ b/test/test_assignment.cpp @@ -787,6 +787,4 @@ int main () { BOOST_UBLAS_TEST_DO( test_matrix ); BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS; } diff --git a/test/test_banded_storage_layout.cpp b/test/test_banded_storage_layout.cpp index 74a1be31b..021103ca3 100644 --- a/test/test_banded_storage_layout.cpp +++ b/test/test_banded_storage_layout.cpp @@ -283,9 +283,5 @@ int main() BOOST_UBLAS_TEST_DO( banded_matrix_row_major_5_by_6 ); - BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS; + BOOST_UBLAS_TEST_END(); } - - diff --git a/test/test_coordinate_matrix_inplace_merge.cpp b/test/test_coordinate_matrix_inplace_merge.cpp index be0c85227..aac3504eb 100644 --- a/test/test_coordinate_matrix_inplace_merge.cpp +++ b/test/test_coordinate_matrix_inplace_merge.cpp @@ -115,6 +115,4 @@ int main() BOOST_UBLAS_TEST_DO( test_coordinate_matrix_inplace_merge_random ); BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS;; } diff --git a/test/test_coordinate_vector_inplace_merge.cpp b/test/test_coordinate_vector_inplace_merge.cpp index 8878f26fb..73a4247ce 100644 --- a/test/test_coordinate_vector_inplace_merge.cpp +++ b/test/test_coordinate_vector_inplace_merge.cpp @@ -104,6 +104,4 @@ int main() BOOST_UBLAS_TEST_DO( test_coordinate_vector_inplace_merge_random ); BOOST_UBLAS_TEST_END(); - - return EXIT_SUCCESS;; } From d5460ba83ea31759a9371cb282a987fd62700734 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 9 Nov 2015 00:42:12 +0100 Subject: [PATCH 39/73] In function boost_numeric_ublas_abs, force type conversion back to T type for char and short types. --- include/boost/numeric/ublas/traits.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/traits.hpp b/include/boost/numeric/ublas/traits.hpp index 56fe5fd43..765632967 100644 --- a/include/boost/numeric/ublas/traits.hpp +++ b/include/boost/numeric/ublas/traits.hpp @@ -52,7 +52,8 @@ inline typename boost::disable_if< boost::is_unsigned, T >::type boost_numeric_ublas_abs (const T &t ) { using namespace std; - return abs( t ); + // force a type conversion back to T for char and short types + return static_cast(abs( t )); } template From 852d1d38986a5ebcfa679d513be4d18cb3fc3054 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 9 Nov 2015 01:27:38 +0100 Subject: [PATCH 40/73] In dereference operation in vector_expression, cast the result of functor_type::apply to value_type, to clear the warning of possible loss of data. --- include/boost/numeric/ublas/vector_expression.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/vector_expression.hpp b/include/boost/numeric/ublas/vector_expression.hpp index b35222ee8..98abb93df 100644 --- a/include/boost/numeric/ublas/vector_expression.hpp +++ b/include/boost/numeric/ublas/vector_expression.hpp @@ -819,7 +819,7 @@ namespace boost { namespace numeric { namespace ublas { if (it2_ != it2_end_) if (it2_.index () == i_) t2 = *it2_; - return functor_type::apply (t1, t2); + return static_cast(functor_type::apply (t1, t2)); } public: From a936eac9221e3b369346e78e9ac120855d030005 Mon Sep 17 00:00:00 2001 From: Seth Heeren Date: Mon, 26 Oct 2015 11:19:26 +0100 Subject: [PATCH 41/73] Add allocator support to map_std<> --- include/boost/numeric/ublas/storage_sparse.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/numeric/ublas/storage_sparse.hpp b/include/boost/numeric/ublas/storage_sparse.hpp index c8a64a9d5..641a22d53 100644 --- a/include/boost/numeric/ublas/storage_sparse.hpp +++ b/include/boost/numeric/ublas/storage_sparse.hpp @@ -195,14 +195,13 @@ namespace boost { namespace numeric { namespace ublas { // Default map type is simply forwarded to std::map - // FIXME should use ALLOC for map but std::allocator of std::pair and std::pair fail to compile template - class map_std : public std::map { + class map_std : public std::map, ALLOC> { public: // Serialization template void serialize(Archive & ar, const unsigned int /* file_version */){ - ar & serialization::make_nvp("base", boost::serialization::base_object< std::map >(*this)); + ar & serialization::make_nvp("base", boost::serialization::base_object< std::map, ALLOC> >(*this)); } }; From 3d9611c3c0c041017b97ddb0f0265bb66ed3ed51 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Thu, 3 Dec 2015 00:00:55 +0100 Subject: [PATCH 42/73] The template function OneElement returns 'one' and the vector partial specialization of function OneElement has been removed. --- include/boost/numeric/ublas/detail/concepts.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/include/boost/numeric/ublas/detail/concepts.hpp b/include/boost/numeric/ublas/detail/concepts.hpp index 674c610ed..f85041fe5 100644 --- a/include/boost/numeric/ublas/detail/concepts.hpp +++ b/include/boost/numeric/ublas/detail/concepts.hpp @@ -644,7 +644,7 @@ namespace boost { namespace numeric { namespace ublas { template T ZeroElement (T) { - return T(0.0); + return static_cast (0); } template @@ -662,13 +662,7 @@ namespace boost { namespace numeric { namespace ublas { template T OneElement (T) { - return T(0.0); - } - - template - vector - OneElement (vector) { - return zero_vector (); + return static_cast (1); } template From 9bf9d05943f1cec725d13e9abaffdb9af95c3b0b Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 4 Dec 2015 00:36:20 +0100 Subject: [PATCH 43/73] Removed old source code. --- .../boost/numeric/ublas/detail/concepts.hpp | 104 ------------------ 1 file changed, 104 deletions(-) diff --git a/include/boost/numeric/ublas/detail/concepts.hpp b/include/boost/numeric/ublas/detail/concepts.hpp index f85041fe5..21d550145 100644 --- a/include/boost/numeric/ublas/detail/concepts.hpp +++ b/include/boost/numeric/ublas/detail/concepts.hpp @@ -671,110 +671,6 @@ namespace boost { namespace numeric { namespace ublas { return identity_matrix (); } -// template<> -// float -// ZeroElement (float) { -// return 0.f; -// } -// template<> -// double -// ZeroElement (double) { -// return 0.; -// } -// template<> -// vector -// ZeroElement (vector) { -// return zero_vector (); -// } -// template<> -// vector -// ZeroElement (vector) { -// return zero_vector (); -// } -// template<> -// matrix -// ZeroElement (matrix) { -// return zero_matrix (); -// } -// template<> -// matrix -// ZeroElement (matrix) { -// return zero_matrix (); -// } -// template<> -// std::complex -// ZeroElement (std::complex) { -// return std::complex (0.f); -// } -// template<> -// std::complex -// ZeroElement (std::complex) { -// return std::complex (0.); -// } -// template<> -// vector > -// ZeroElement (vector >) { -// return zero_vector > (); -// } -// template<> -// vector > -// ZeroElement (vector >) { -// return zero_vector > (); -// } -// template<> -// matrix > -// ZeroElement (matrix >) { -// return zero_matrix > (); -// } -// template<> -// matrix > -// ZeroElement (matrix >) { -// return zero_matrix > (); -// } - -// template -// T -// OneElement (T); -// template<> -// float -// OneElement (float) { -// return 1.f; -// } -// template<> -// double -// OneElement (double) { -// return 1.; -// } -// template<> -// matrix -// OneElement (matrix) { -// return identity_matrix (); -// } -// template<> -// matrix -// OneElement (matrix) { -// return identity_matrix (); -// } -// template<> -// std::complex -// OneElement (std::complex) { -// return std::complex (1.f); -// } -// template<> -// std::complex -// OneElement (std::complex) { -// return std::complex (1.); -// } -// template<> -// matrix > -// OneElement (matrix >) { -// return identity_matrix > (); -// } -// template<> -// matrix > -// OneElement (matrix >) { -// return identity_matrix > (); -// } template bool From e6f4adb604d90abdeaa7a91b4006091bdb4e7738 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Fri, 11 Dec 2015 01:41:05 +0100 Subject: [PATCH 44/73] matrix_expression_assigner, vector_expression_assigner, matrix_row_vector and matrix_column_vector are copyable classes. --- include/boost/numeric/ublas/assignment.hpp | 51 +++++++++---------- include/boost/numeric/ublas/matrix_vector.hpp | 45 ++++++++-------- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/include/boost/numeric/ublas/assignment.hpp b/include/boost/numeric/ublas/assignment.hpp index 838fe0a28..d69d005ed 100644 --- a/include/boost/numeric/ublas/assignment.hpp +++ b/include/boost/numeric/ublas/assignment.hpp @@ -9,7 +9,6 @@ #ifndef ASSIGNMENT_HPP #define ASSIGNMENT_HPP -#include #include #include @@ -922,35 +921,35 @@ namespace traverse_policy { * \todo Add examples link */ template -class vector_expression_assigner : private boost::noncopyable { +class vector_expression_assigner { public: typedef typename E::expression_type::value_type value_type; typedef typename E::expression_type::size_type size_type; BOOST_UBLAS_INLINE - vector_expression_assigner(E &e):ve(e), i(0) { + vector_expression_assigner(E &e):ve(&e), i(0) { } BOOST_UBLAS_INLINE - vector_expression_assigner(size_type k, E &e):ve(e), i(k) { + vector_expression_assigner(size_type k, E &e):ve(&e), i(k) { // Overloaded like that so it can be differentiated from (E, val). // Otherwise there would be an ambiquity when value_type == size_type. } BOOST_UBLAS_INLINE - vector_expression_assigner(E &e, value_type val):ve(e), i(0) { + vector_expression_assigner(E &e, value_type val):ve(&e), i(0) { operator,(val); } template BOOST_UBLAS_INLINE - vector_expression_assigner(E &e, const vector_expression &nve):ve(e), i(0) { + vector_expression_assigner(E &e, const vector_expression &nve):ve(&e), i(0) { operator,(nve); } template BOOST_UBLAS_INLINE - vector_expression_assigner(E &e, const index_manipulator &ta):ve(e), i(0) { + vector_expression_assigner(E &e, const index_manipulator &ta):ve(&e), i(0) { operator,(ta); } @@ -978,18 +977,18 @@ class vector_expression_assigner : private boost::noncopyable { template BOOST_UBLAS_INLINE vector_expression_assigner operator, (fill_policy_wrapper) const { - return vector_expression_assigner(i, ve); + return vector_expression_assigner(i, *ve); } private: BOOST_UBLAS_INLINE vector_expression_assigner &apply(const typename E::expression_type::value_type& val) { - Fill_Policy::apply(ve, i++, val); + Fill_Policy::apply(*ve, i++, val); return *this; } private: - E &ve; + E *ve; size_type i; }; @@ -1098,44 +1097,44 @@ vector_expression_assigner, T> operator<<=(vector_expressio * \todo Add examples link */ template -class matrix_expression_assigner : private boost::noncopyable { +class matrix_expression_assigner { public: typedef typename E::expression_type::size_type size_type; BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e): me(e), i(0), j(0) { + matrix_expression_assigner(E &e): me(&e), i(0), j(0) { } BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e, size_type k, size_type l): me(e), i(k), j(l) { + matrix_expression_assigner(E &e, size_type k, size_type l): me(&e), i(k), j(l) { } BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(e), i(0), j(0) { + matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(&e), i(0), j(0) { operator,(val); } template BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e, const vector_expression &nve):me(e), i(0), j(0) { + matrix_expression_assigner(E &e, const vector_expression &nve):me(&e), i(0), j(0) { operator,(nve); } template BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e, const matrix_expression &nme):me(e), i(0), j(0) { + matrix_expression_assigner(E &e, const matrix_expression &nme):me(&e), i(0), j(0) { operator,(nme); } template BOOST_UBLAS_INLINE - matrix_expression_assigner(E &e, const index_manipulator &ta):me(e), i(0), j(0) { + matrix_expression_assigner(E &e, const index_manipulator &ta):me(&e), i(0), j(0) { operator,(ta); } BOOST_UBLAS_INLINE matrix_expression_assigner &operator, (const typename E::expression_type::value_type& val) { - Traverse_Policy::apply_wrap(me, i ,j); + Traverse_Policy::apply_wrap(*me, i ,j); return apply(val); } @@ -1164,21 +1163,21 @@ class matrix_expression_assigner : private boost::noncopyable { template BOOST_UBLAS_INLINE matrix_expression_assigner operator, (fill_policy_wrapper) const { - return matrix_expression_assigner(me, i, j); + return matrix_expression_assigner(*me, i, j); } template BOOST_UBLAS_INLINE matrix_expression_assigner operator, (traverse_policy_wrapper) { - Traverse_Policy::apply_wrap(me, i ,j); - return matrix_expression_assigner(me, i, j); + Traverse_Policy::apply_wrap(*me, i ,j); + return matrix_expression_assigner(*me, i, j); } private: BOOST_UBLAS_INLINE matrix_expression_assigner &apply(const typename E::expression_type::value_type& val) { - Fill_Policy::apply(me, i, j, val); + Fill_Policy::apply(*me, i, j, val); Traverse_Policy::advance(i,j); return *this; } @@ -1189,14 +1188,14 @@ class matrix_expression_assigner : private boost::noncopyable { size_type bi = i; size_type bj = j; typename AE::size_type k=0, l=0; - Fill_Policy::apply(me, i, j, nme()(k, l)); - while (Traverse_Policy::next(nme, me, i, j, bi, bj, k, l)) - Fill_Policy::apply(me, i, j, nme()(k, l)); + Fill_Policy::apply(*me, i, j, nme()(k, l)); + while (Traverse_Policy::next(nme, *me, i, j, bi, bj, k, l)) + Fill_Policy::apply(*me, i, j, nme()(k, l)); return *this; } private: - E &me; + E *me; size_type i, j; }; diff --git a/include/boost/numeric/ublas/matrix_vector.hpp b/include/boost/numeric/ublas/matrix_vector.hpp index 6498b4cc4..cf032bffb 100644 --- a/include/boost/numeric/ublas/matrix_vector.hpp +++ b/include/boost/numeric/ublas/matrix_vector.hpp @@ -9,7 +9,6 @@ #ifndef BOOST_UBLAS_MATRIX_VECTOR_HPP #define BOOST_UBLAS_MATRIX_VECTOR_HPP -#include #include //for matrix_row, matrix_column and matrix_expression #include #include @@ -106,7 +105,7 @@ class matrix_vector_iterator: public boost::iterator_facade< * the underlaying matrix. */ template -class matrix_row_vector: private boost::noncopyable { +class matrix_row_vector { public: typedef ublas::matrix_row value_type; typedef ublas::matrix_row reference; @@ -122,17 +121,17 @@ class matrix_row_vector: private boost::noncopyable { BOOST_UBLAS_INLINE explicit matrix_row_vector(Matrix& matrix) : - matrix_(matrix) { + matrix_(&matrix) { } BOOST_UBLAS_INLINE iterator begin(){ - return iterator(matrix_, 0); + return iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator begin() const { - return const_iterator(matrix_, 0); + return const_iterator(*matrix_, 0); } BOOST_UBLAS_INLINE @@ -142,12 +141,12 @@ class matrix_row_vector: private boost::noncopyable { BOOST_UBLAS_INLINE iterator end() { - return iterator(matrix_, matrix_.size1()); + return iterator(*matrix_, matrix_->size1()); } BOOST_UBLAS_INLINE const_iterator end() const { - return const_iterator(matrix_, matrix_.size1()); + return const_iterator(*matrix_, matrix_->size1()); } BOOST_UBLAS_INLINE @@ -187,12 +186,12 @@ class matrix_row_vector: private boost::noncopyable { BOOST_UBLAS_INLINE value_type operator()(size_type index) { - return value_type(matrix_, index); + return value_type(*matrix_, index); } BOOST_UBLAS_INLINE value_type operator()(size_type index) const { - return value_type(matrix_, index); + return value_type(*matrix_, index); } BOOST_UBLAS_INLINE @@ -207,16 +206,16 @@ class matrix_row_vector: private boost::noncopyable { BOOST_UBLAS_INLINE size_type size() const { - return matrix_.size1(); + return matrix_->size1(); } BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { - matrix_.resize(size, matrix_.size2(), preserve); + matrix_->resize(size, matrix_->size2(), preserve); } private: - Matrix& matrix_; + Matrix* matrix_; }; @@ -259,7 +258,7 @@ matrix_row_vector make_row_vector(matrix_expression const& * the underlaying matrix. */ template -class matrix_column_vector: private boost::noncopyable { +class matrix_column_vector { public: typedef ublas::matrix_column value_type; typedef ublas::matrix_column reference; @@ -275,17 +274,17 @@ class matrix_column_vector: private boost::noncopyable { BOOST_UBLAS_INLINE explicit matrix_column_vector(Matrix& matrix) : - matrix_(matrix){ + matrix_(&matrix){ } BOOST_UBLAS_INLINE iterator begin() { - return iterator(matrix_, 0); + return iterator(*matrix_, 0); } BOOST_UBLAS_INLINE const_iterator begin() const { - return const_iterator(matrix_, 0); + return const_iterator(*matrix_, 0); } BOOST_UBLAS_INLINE @@ -295,12 +294,12 @@ class matrix_column_vector: private boost::noncopyable { BOOST_UBLAS_INLINE iterator end() { - return iterator(matrix_, matrix_.size2()); + return iterator(*matrix_, matrix_->size2()); } BOOST_UBLAS_INLINE const_iterator end() const { - return const_iterator(matrix_, matrix_.size2()); + return const_iterator(*matrix_, matrix_->size2()); } BOOST_UBLAS_INLINE @@ -340,12 +339,12 @@ class matrix_column_vector: private boost::noncopyable { BOOST_UBLAS_INLINE value_type operator()(size_type index) { - return value_type(matrix_, index); + return value_type(*matrix_, index); } BOOST_UBLAS_INLINE value_type operator()(size_type index) const { - return value_type(matrix_, index); + return value_type(*matrix_, index); } BOOST_UBLAS_INLINE @@ -360,16 +359,16 @@ class matrix_column_vector: private boost::noncopyable { BOOST_UBLAS_INLINE size_type size() const { - return matrix_.size2(); + return matrix_->size2(); } BOOST_UBLAS_INLINE void resize(size_type size, bool preserve = true) { - matrix_.resize(matrix_.size1(), size, preserve); + matrix_->resize(matrix_->size1(), size, preserve); } private: - Matrix& matrix_; + Matrix* matrix_; }; From 5fa629bb09270c4f425e600e26782057dd6b660a Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sat, 12 Dec 2015 00:42:41 +0100 Subject: [PATCH 45/73] Changed the type of functions parameter to fix type conversion warnings in test_banded_storage_layout. --- test/test_banded_storage_layout.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_banded_storage_layout.cpp b/test/test_banded_storage_layout.cpp index 021103ca3..d5c640b93 100644 --- a/test/test_banded_storage_layout.cpp +++ b/test/test_banded_storage_layout.cpp @@ -9,7 +9,7 @@ using namespace boost::numeric::ublas; -int expected_index( int index, column_major ) { +int expected_index( size_t index, column_major ) { // this is the data shown on http://www.netlib.org/lapack/lug/node124.html // read column-by-column, aka column_major int mapping[] = { 0, 11, 21, 31, 12, 22, 32, 42, 23, 33, 43, 53, 34, 44, 54, 0, 45, 55, 0, 0 }; @@ -17,32 +17,32 @@ int expected_index( int index, column_major ) { } -int expected_index( int index, row_major ) { +int expected_index( size_t index, row_major ) { // this is the data shown on http://www.netlib.org/lapack/lug/node124.html // read row-by-row, aka row_major int mapping[] = { 0, 0, 11, 12, 0, 21, 22, 23, 31, 32, 33, 34, 42, 43, 44, 45, 53, 54, 55, 0 }; return mapping[ index ]; } -int expected_index_6_by_5( int index, column_major ) { +int expected_index_6_by_5( size_t index, column_major ) { // read column-by-column, aka column_major int mapping[] = { 0, 11, 21, 31, 12, 22, 32, 42, 23, 33, 43, 53, 34, 44, 54, 64, 45, 55, 65, 0 }; return mapping[ index ]; } -int expected_index_6_by_5( int index, row_major ) { +int expected_index_6_by_5( size_t index, row_major ) { // read row-by-row, aka row_major int mapping[] = { 0, 0, 11, 12, 0, 21, 22, 23, 31, 32, 33, 34, 42, 43, 44, 45, 53, 54, 55, 0, 64, 65, 0, 0 }; return mapping[ index ]; } -int expected_index_5_by_6( int index, column_major ) { +int expected_index_5_by_6( size_t index, column_major ) { // read column-by-column, aka column_major int mapping[] = { 0, 11, 21, 31, 12, 22, 32, 42, 23, 33, 43, 53, 34, 44, 54, 0, 45, 55, 0, 0, 56, 0, 0, 0 }; return mapping[ index ]; } -int expected_index_5_by_6( int index, row_major ) { +int expected_index_5_by_6( size_t index, row_major ) { // read row-by-row, aka row_major int mapping[] = { 0, 0, 11, 12, 0, 21, 22, 23, 31, 32, 33, 34, 42, 43, 44, 45, 53, 54, 55, 56}; return mapping[ index ]; From 54c429154b82a24413eab02378364235532de9d6 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Sun, 13 Dec 2015 03:01:53 +0100 Subject: [PATCH 46/73] Disable MSCV iterator debugging to avoid program failure when a MVOV is traversed by column and then by row. https://msdn.microsoft.com/en-us/library/hh697468.aspx --- include/boost/numeric/ublas/vector_sparse.hpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/boost/numeric/ublas/vector_sparse.hpp b/include/boost/numeric/ublas/vector_sparse.hpp index 07c64cbf0..134a62061 100644 --- a/include/boost/numeric/ublas/vector_sparse.hpp +++ b/include/boost/numeric/ublas/vector_sparse.hpp @@ -13,6 +13,31 @@ #ifndef _BOOST_UBLAS_VECTOR_SPARSE_ #define _BOOST_UBLAS_VECTOR_SPARSE_ +#include + +// In debug mode, MSCV enables iterator debugging, which additional checks are +// executed for consistency. So, when two iterators are compared, it is tested +// that they point to elements of the same container. If the check fails, then +// the program is aborted. +// +// When matrices MVOV are traversed by column and then by row, the previous +// check fails. +// +// MVOV::iterator2 iter2 = mvov.begin2(); +// for (; iter2 != mvov.end() ; iter2++) { +// MVOV::iterator1 iter1 = iter2.begin(); +// ..... +// } +// +// These additional checks in iterators are disabled in this file, but their +// status are restored at the end of file. +// https://msdn.microsoft.com/en-us/library/hh697468.aspx +#ifdef BOOST_MSVC +#define _BACKUP_ITERATOR_DEBUG_LEVEL _ITERATOR_DEBUG_LEVEL +#undef _ITERATOR_DEBUG_LEVEL +#define _ITERATOR_DEBUG_LEVEL 0 +#endif + #include #include #include @@ -2212,4 +2237,10 @@ namespace boost { namespace numeric { namespace ublas { }}} +#ifdef BOOST_MSVC +#undef _ITERATOR_DEBUG_LEVEL +#define _ITERATOR_DEBUG_LEVEL _BACKUP_ITERATOR_DEBUG_LEVEL +#undef _BACKUP_ITERATOR_DEBUG_LEVEL +#endif + #endif From 7734abaa985af73656529b47fe61a59d121c475c Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Thu, 31 Dec 2015 18:44:26 +0100 Subject: [PATCH 47/73] Fixed warnings C4245 in file assignment.hpp. --- include/boost/numeric/ublas/assignment.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/boost/numeric/ublas/assignment.hpp b/include/boost/numeric/ublas/assignment.hpp index d69d005ed..d14ada02b 100644 --- a/include/boost/numeric/ublas/assignment.hpp +++ b/include/boost/numeric/ublas/assignment.hpp @@ -175,7 +175,11 @@ template class static_vector_move_manip: public index_manipulator > { public: template - BOOST_UBLAS_INLINE void manip(V &k) const { k+=I; } + BOOST_UBLAS_INLINE void manip(V &k) const { + // With the equivalent expression using '+=' operator, mscv reports waring C4245: + // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch + k = k + I; + } }; /** @@ -376,8 +380,10 @@ class static_matrix_move_manip: public index_manipulator BOOST_UBLAS_INLINE void manip(V &k, K &l) const { - k+=I; - l+=J; + // With the equivalent expression using '+=' operator, mscv reports waring C4245: + // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch + k = k + I; + l = l + J; } }; From bc211a890595790c421055cc47d5c3be160183f7 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Tue, 5 Jan 2016 03:08:37 +0100 Subject: [PATCH 48/73] In matrix and vector expressions, the local variables of type value type that stores values of E1 or E2 has been redefined as E1::value_type or E2::value_type. Fixes warning C4244: conversion with possible loss of data. --- .../boost/numeric/ublas/matrix_expression.hpp | 24 +++++++++---------- .../boost/numeric/ublas/vector_expression.hpp | 8 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/boost/numeric/ublas/matrix_expression.hpp b/include/boost/numeric/ublas/matrix_expression.hpp index 52a944596..8e6c2f68b 100644 --- a/include/boost/numeric/ublas/matrix_expression.hpp +++ b/include/boost/numeric/ublas/matrix_expression.hpp @@ -397,7 +397,7 @@ namespace boost { namespace numeric { namespace ublas { const_subiterator1_type it1_end (e1_.find (size1 ())); const_subiterator2_type it2 (e2_.find (j)); const_subiterator2_type it2_end (e2_.find (size2 ())); - if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type/*zero*/()))) { + if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) { it1 = it1_end; it2 = it2_end; } @@ -405,7 +405,7 @@ namespace boost { namespace numeric { namespace ublas { return const_iterator1 (*this, it1.index (), it2.index ()); #else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type/*zero*/()); + return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/()); #else return const_iterator1 (*this, it1, it2); #endif @@ -417,7 +417,7 @@ namespace boost { namespace numeric { namespace ublas { const_subiterator2_type it2_end (e2_.find (size2 ())); const_subiterator1_type it1 (e1_.find (i)); const_subiterator1_type it1_end (e1_.find (size1 ())); - if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type/*zero*/()))) { + if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) { it2 = it2_end; it1 = it1_end; } @@ -425,7 +425,7 @@ namespace boost { namespace numeric { namespace ublas { return const_iterator2 (*this, it1.index (), it2.index ()); #else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type/*zero*/()); + return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/()); #else return const_iterator2 (*this, it1, it2); #endif @@ -2195,13 +2195,13 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (packed_random_access_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); if (it1_.index1 () == i_) t1 = *it1_; } - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) { BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); if (it2_.index1 () == i_) @@ -2271,13 +2271,13 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (sparse_bidirectional_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); if (it1_.index1 () == i_) t1 = *it1_; } - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) { BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); if (it2_.index1 () == i_) @@ -2546,13 +2546,13 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (packed_random_access_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); if (it1_.index2 () == j_) t1 = *it1_; } - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) { BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); if (it2_.index2 () == j_) @@ -2622,13 +2622,13 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (sparse_bidirectional_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) { BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); if (it1_.index2 () == j_) t1 = *it1_; } - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) { BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); if (it2_.index2 () == j_) diff --git a/include/boost/numeric/ublas/vector_expression.hpp b/include/boost/numeric/ublas/vector_expression.hpp index 98abb93df..d92207c98 100644 --- a/include/boost/numeric/ublas/vector_expression.hpp +++ b/include/boost/numeric/ublas/vector_expression.hpp @@ -739,11 +739,11 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (packed_random_access_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) if (it1_.index () == i_) t1 = *it1_; - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) if (it2_.index () == i_) t2 = *it2_; @@ -811,11 +811,11 @@ namespace boost { namespace numeric { namespace ublas { } BOOST_UBLAS_INLINE value_type dereference (sparse_bidirectional_iterator_tag) const { - value_type t1 = value_type/*zero*/(); + typename E1::value_type t1 = typename E1::value_type/*zero*/(); if (it1_ != it1_end_) if (it1_.index () == i_) t1 = *it1_; - value_type t2 = value_type/*zero*/(); + typename E2::value_type t2 = typename E2::value_type/*zero*/(); if (it2_ != it2_end_) if (it2_.index () == i_) t2 = *it2_; From ee448e4fc77a6b4983a353040f87a81fcf9a8afa Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 11 Jan 2016 01:43:28 +0100 Subject: [PATCH 49/73] Fixed warnings C4127 (conditional expression is constant) by replacing 'while (true)' with 'for(;;)'. --- include/boost/numeric/ublas/detail/matrix_assign.hpp | 12 ++++++------ include/boost/numeric/ublas/detail/vector_assign.hpp | 6 +++--- include/boost/numeric/ublas/functional.hpp | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/boost/numeric/ublas/detail/matrix_assign.hpp b/include/boost/numeric/ublas/detail/matrix_assign.hpp index be172dd63..e31598a8f 100644 --- a/include/boost/numeric/ublas/detail/matrix_assign.hpp +++ b/include/boost/numeric/ublas/detail/matrix_assign.hpp @@ -74,7 +74,7 @@ namespace detail { #endif if (it2 != it2_end && it2e != it2e_end) { size_type it2_index = it2.index2 (), it2e_index = it2e.index2 (); - while (true) { + for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 0) { ++ it2, ++ it2e; @@ -177,7 +177,7 @@ namespace detail { #endif if (it1 != it1_end && it1e != it1e_end) { size_type it1_index = it1.index1 (), it1e_index = it1e.index1 (); - while (true) { + for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 0) { ++ it1, ++ it1e; @@ -1002,7 +1002,7 @@ namespace detail { #endif if (it2 != it2_end && it2e != it2e_end) { size_type it2_index = it2.index2 (), it2e_index = it2e.index2 (); - while (true) { + for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 0) { functor_type::apply (*it2, *it2e); @@ -1125,7 +1125,7 @@ namespace detail { #endif if (it1 != it1_end && it1e != it1e_end) { size_type it1_index = it1.index1 (), it1e_index = it1e.index1 (); - while (true) { + for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 0) { functor_type::apply (*it1, *it1e); @@ -1390,7 +1390,7 @@ namespace detail { #endif if (it2 != it2_end && it2e != it2e_end) { size_type it2_index = it2.index2 (), it2e_index = it2e.index2 (); - while (true) { + for (;;) { difference_type compare2 = it2_index - it2e_index; if (compare2 == 0) { functor_type::apply (*it2, *it2e); @@ -1515,7 +1515,7 @@ namespace detail { #endif if (it1 != it1_end && it1e != it1e_end) { size_type it1_index = it1.index1 (), it1e_index = it1e.index1 (); - while (true) { + for (;;) { difference_type compare2 = it1_index - it1e_index; if (compare2 == 0) { functor_type::apply (*it1, *it1e); diff --git a/include/boost/numeric/ublas/detail/vector_assign.hpp b/include/boost/numeric/ublas/detail/vector_assign.hpp index e612876df..0bb42c69a 100644 --- a/include/boost/numeric/ublas/detail/vector_assign.hpp +++ b/include/boost/numeric/ublas/detail/vector_assign.hpp @@ -59,7 +59,7 @@ namespace detail { typename E::const_iterator ite_end (e ().end ()); if (it != it_end && ite != ite_end) { size_type it_index = it.index (), ite_index = ite.index (); - while (true) { + for (;;) { difference_type compare = it_index - ite_index; if (compare == 0) { ++ it, ++ ite; @@ -393,7 +393,7 @@ namespace detail { typename E::const_iterator ite_end (e ().end ()); if (it != it_end && ite != ite_end) { size_type it_index = it.index (), ite_index = ite.index (); - while (true) { + for (;;) { difference_type compare = it_index - ite_index; if (compare == 0) { functor_type::apply (*it, *ite); @@ -524,7 +524,7 @@ namespace detail { typename E::iterator ite_end (e ().end ()); if (it != it_end && ite != ite_end) { size_type it_index = it.index (), ite_index = ite.index (); - while (true) { + for (;;) { difference_type compare = it_index - ite_index; if (compare == 0) { functor_type::apply (*it, *ite); diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index 10c6ea6b4..b0be20608 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -749,7 +749,7 @@ namespace boost { namespace numeric { namespace ublas { result_type apply (I1 it1, const I1 &it1_end, I2 it2, const I2 &it2_end, sparse_bidirectional_iterator_tag) { result_type t = result_type (0); if (it1 != it1_end && it2 != it2_end) { - while (true) { + for (;;) { if (it1.index () == it2.index ()) { t += *it1 * *it2, ++ it1, ++ it2; if (it1 == it1_end || it2 == it2_end) @@ -887,7 +887,7 @@ namespace boost { namespace numeric { namespace ublas { result_type t = result_type (0); if (it1 != it1_end && it2 != it2_end) { size_type it1_index = it1.index2 (), it2_index = it2.index (); - while (true) { + for (;;) { difference_type compare = it1_index - it2_index; if (compare == 0) { t += *it1 * *it2, ++ it1, ++ it2; @@ -1055,7 +1055,7 @@ namespace boost { namespace numeric { namespace ublas { result_type t = result_type (0); if (it1 != it1_end && it2 != it2_end) { size_type it1_index = it1.index (), it2_index = it2.index1 (); - while (true) { + for (;;) { difference_type compare = it1_index - it2_index; if (compare == 0) { t += *it1 * *it2, ++ it1, ++ it2; @@ -1232,7 +1232,7 @@ namespace boost { namespace numeric { namespace ublas { result_type t = result_type (0); if (it1 != it1_end && it2 != it2_end) { size_type it1_index = it1.index2 (), it2_index = it2.index1 (); - while (true) { + for (;;) { difference_type compare = difference_type (it1_index - it2_index); if (compare == 0) { t += *it1 * *it2, ++ it1, ++ it2; From 3330c0e13f1304cae6d7fdfb0f4aa5b5a25fbef6 Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 11 Jan 2016 02:50:38 +0100 Subject: [PATCH 50/73] Disabled warning C4127 in the if statements which its conditional expression is constant. --- .../numeric/ublas/detail/matrix_assign.hpp | 147 ++++++++++++++++++ .../numeric/ublas/detail/vector_assign.hpp | 41 ++++- include/boost/numeric/ublas/storage.hpp | 32 ++++ 3 files changed, 219 insertions(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/detail/matrix_assign.hpp b/include/boost/numeric/ublas/detail/matrix_assign.hpp index e31598a8f..efaf9ab81 100644 --- a/include/boost/numeric/ublas/detail/matrix_assign.hpp +++ b/include/boost/numeric/ublas/detail/matrix_assign.hpp @@ -670,7 +670,15 @@ namespace detail { size1 = (std::min) (- diff1, it1_size); if (size1 > 0) { it1_size -= size1; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size1 >= 0) { // zeroing #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator2 it2 (it1.begin ()); @@ -719,7 +727,15 @@ namespace detail { size2 = (std::min) (- diff2, it2_size); if (size2 > 0) { it2_size -= size2; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size2 >= 0) // zeroing functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2; } else { @@ -734,7 +750,15 @@ namespace detail { while (-- size2 >= 0) functor_type::apply (*it2, *it2e), ++ it2, ++ it2e; size2 = it2_size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size2 >= 0) // zeroing functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2; } else { @@ -743,7 +767,15 @@ namespace detail { ++ it1, ++ it1e; } size1 = it1_size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size1 >= 0) { // zeroing #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator2 it2 (it1.begin ()); @@ -802,7 +834,15 @@ namespace detail { size2 = (std::min) (- diff2, it2_size); if (size2 > 0) { it2_size -= size2; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size2 >= 0) { // zeroing #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator1 it1 (it2.begin ()); @@ -851,7 +891,15 @@ namespace detail { size1 = (std::min) (- diff1, it1_size); if (size1 > 0) { it1_size -= size1; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size1 >= 0) // zeroing functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1; } else { @@ -866,7 +914,16 @@ namespace detail { while (-- size1 >= 0) functor_type::apply (*it1, *it1e), ++ it1, ++ it1e; size1 = it1_size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { + +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size1 >= 0) // zeroing functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1; } else { @@ -875,7 +932,15 @@ namespace detail { ++ it2, ++ it2e; } size2 = it2_size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size2 >= 0) { // zeroing #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator1 it1 (it2.begin ()); @@ -903,7 +968,16 @@ namespace detail { void matrix_assign (M &m, const matrix_expression &e, sparse_tag, row_major_tag) { typedef F functor_type; // R unnecessary, make_conformant not required + +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif BOOST_STATIC_ASSERT ((!functor_type::computed)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef typename M::value_type value_type; @@ -935,7 +1009,16 @@ namespace detail { void matrix_assign (M &m, const matrix_expression &e, sparse_tag, column_major_tag) { typedef F functor_type; // R unnecessary, make_conformant not required + +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif BOOST_STATIC_ASSERT ((!functor_type::computed)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ()); BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ()); typedef typename M::value_type value_type; @@ -1013,7 +1096,15 @@ namespace detail { } else break; } else if (compare2 < 0) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif functor_type::apply (*it2, expr_value_type/*zero*/()); ++ it2; } else @@ -1031,7 +1122,15 @@ namespace detail { } } } +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (it2 != it2_end) { // zeroing functor_type::apply (*it2, expr_value_type/*zero*/()); ++ it2; @@ -1041,7 +1140,15 @@ namespace detail { } ++ it1, ++ it1e; } else if (compare < 0) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator2 it2 (it1.begin ()); typename M::iterator2 it2_end (it1.end ()); @@ -1061,7 +1168,15 @@ namespace detail { increment (it1e, it1e_end, compare); } } +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (it1 != it1_end) { #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator2 it2 (it1.begin ()); @@ -1136,7 +1251,15 @@ namespace detail { } else break; } else if (compare2 < 0) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing ++ it1; } else @@ -1154,7 +1277,15 @@ namespace detail { } } } +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (it1 != it1_end) { // zeroing functor_type::apply (*it1, expr_value_type/*zero*/()); ++ it1; @@ -1164,7 +1295,15 @@ namespace detail { } ++ it2, ++ it2e; } else if (compare < 0) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator1 it1 (it2.begin ()); typename M::iterator1 it1_end (it2.end ()); @@ -1184,7 +1323,15 @@ namespace detail { increment (it2e, it2e_end, compare); } } +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (it2 != it2_end) { #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION typename M::iterator1 it1 (it2.begin ()); diff --git a/include/boost/numeric/ublas/detail/vector_assign.hpp b/include/boost/numeric/ublas/detail/vector_assign.hpp index 0bb42c69a..b0ffacfb6 100644 --- a/include/boost/numeric/ublas/detail/vector_assign.hpp +++ b/include/boost/numeric/ublas/detail/vector_assign.hpp @@ -316,7 +316,15 @@ namespace detail { difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size)); if (size > 0) { it_size -= size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size >= 0) // zeroing functor_type::apply (*it, value_type/*zero*/()), ++ it; } else { @@ -330,7 +338,15 @@ namespace detail { while (-- size >= 0) functor_type::apply (*it, *ite), ++ it, ++ ite; size = it_size; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (-- size >= 0) // zeroing functor_type::apply (*it, value_type/*zero*/()), ++ it; } else { @@ -348,7 +364,15 @@ namespace detail { void vector_assign (V &v, const vector_expression &e, sparse_tag) { BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ()); typedef F functor_type; +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif BOOST_STATIC_ASSERT ((!functor_type::computed)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif typedef typename V::value_type value_type; #if BOOST_UBLAS_TYPE_CHECK vector cv (v.size ()); @@ -404,7 +428,15 @@ namespace detail { } else break; } else if (compare < 0) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif functor_type::apply (*it, value_type/*zero*/()); ++ it; } else @@ -422,8 +454,15 @@ namespace detail { } } } - +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (!functor_type::computed) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif while (it != it_end) { // zeroing functor_type::apply (*it, value_type/*zero*/()); ++ it; diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index f5b625db5..410301845 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -66,7 +66,15 @@ namespace boost { namespace numeric { namespace ublas { alloc_(a), size_ (size) { if (size_) { data_ = alloc_.allocate (size_); +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (! detail::has_trivial_constructor::value) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif for (pointer d = data_; d != data_ + size_; ++d) alloc_.construct(d, value_type()); } @@ -99,7 +107,15 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE ~unbounded_array () { if (size_) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (! detail::has_trivial_destructor::value) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif // std::_Destroy (begin(), end(), alloc_); const iterator i_end = end(); for (iterator i = begin (); i != i_end; ++i) { @@ -138,7 +154,15 @@ namespace boost { namespace numeric { namespace ublas { } } else { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (! detail::has_trivial_constructor::value) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif for (pointer di = data_; di != data_ + size; ++di) alloc_.construct (di, value_type()); } @@ -146,7 +170,15 @@ namespace boost { namespace numeric { namespace ublas { } if (size_) { +//Disabled warning C4127 because the conditional expression is constant +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif if (! detail::has_trivial_destructor::value) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif for (pointer si = p_data; si != p_data + size_; ++si) alloc_.destroy (si); } From 02e598368453950fb37f846f492480f7cc8bda0f Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 11 Jan 2016 02:54:59 +0100 Subject: [PATCH 51/73] In Jamfile.v2: - Enabled all warnings in g++ and mscv - Prevent warnings about the checked versions of SCL and CRT libraries. - test_ticket7296: disabled warning d4127 (based from https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines) --- test/Jamfile.v2 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6d6398837..77e296c91 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -51,7 +51,21 @@ project : requirements BOOST_UBLAS_NO_EXCEPTIONS vacpp:"BOOST_UBLAS_NO_ELEMENT_PROXIES" + gcc:"-Wall -pedantic -Wextra" + msvc:"/W4" # == all + # The define of macros below prevent warnings about the checked versions of SCL and CRT libraries. + # Most Boost code does not need these versions (as they are markedly slower). msvc:_SCL_SECURE_NO_WARNINGS + msvc:_SCL_SECURE_NO_DEPRECATE + msvc:_CRT_SECURE_NO_WARNINGS + msvc:_CRT_SECURE_NO_DEPRECATE + msvc:_CRT_NONSTDC_NO_DEPRECATE # Suppresses other warnings about using standard POSIX and C9X. + # Alternatively, you can just suppress the warnings (perhaps not the best way). + #msvc:/wd4996 # 'putenv': The POSIX name for this item is deprecated. + #msvc:/wd4512 # assignment operator could not be generated. + #msvc:/wd4224 # nonstandard extension used : formal parameter 'arg' was previously defined as a type. + #msvc:/wd4127 # expression is constant. + #msvc:/wd4701 # unreachable code - needed for lexical cast - temporary for Boost 1.40 & earlier. ; @@ -185,6 +199,11 @@ test-suite numeric/uBLAS : /boost/timer//boost_timer ] [ run test_ticket7296.cpp + : + : + : msvc:/wd4127 # The program checks that test facilities work fine. The warning appears many times. + : + : ] [ run test_inplace_solve.cpp : From 6c55e2b2f0359b70759c581bc4653c838ec6ffab Mon Sep 17 00:00:00 2001 From: Joaquim Duran Date: Mon, 11 Jan 2016 02:56:08 +0100 Subject: [PATCH 52/73] promote_traits uses BOOST_TYPEOF_TPL (boost::typeof) macro. --- include/boost/numeric/ublas/traits.hpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/include/boost/numeric/ublas/traits.hpp b/include/boost/numeric/ublas/traits.hpp index 765632967..cc8a05042 100644 --- a/include/boost/numeric/ublas/traits.hpp +++ b/include/boost/numeric/ublas/traits.hpp @@ -33,6 +33,7 @@ #include #include #include +#include // anonymous namespace to avoid ADL issues @@ -147,24 +148,10 @@ namespace boost { namespace numeric { namespace ublas { return in1 / R (in2); } - // Use Joel de Guzman's return type deduction // uBLAS assumes a common return type for all binary arithmetic operators template struct promote_traits { - typedef type_deduction_detail::base_result_of base_type; - static typename base_type::x_type x; - static typename base_type::y_type y; - static const std::size_t size = sizeof ( - type_deduction_detail::test< - typename base_type::x_type - , typename base_type::y_type - >(x + y) // Use x+y to stand of all the arithmetic actions - ); - - static const std::size_t index = (size / sizeof (char)) - 1; - typedef typename mpl::at_c< - typename base_type::types, index>::type id; - typedef typename id::type promote_type; + typedef BOOST_TYPEOF_TPL(X() + Y()) promote_type; }; From 5a8731e15241829ee58eeb2815f79a2cb3aad1f5 Mon Sep 17 00:00:00 2001 From: Shangtong Zhang Date: Mon, 14 Mar 2016 00:54:41 +0800 Subject: [PATCH 53/73] Fix bug in weak equality check --- include/boost/numeric/ublas/detail/matrix_assign.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/numeric/ublas/detail/matrix_assign.hpp b/include/boost/numeric/ublas/detail/matrix_assign.hpp index be172dd63..d42d495fc 100644 --- a/include/boost/numeric/ublas/detail/matrix_assign.hpp +++ b/include/boost/numeric/ublas/detail/matrix_assign.hpp @@ -30,7 +30,7 @@ namespace detail { template BOOST_UBLAS_INLINE bool equals (const matrix_expression &e1, const matrix_expression &e2, S epsilon, S min_norm) { - return norm_inf (e1 - e2) < epsilon * + return norm_inf (e1 - e2) <= epsilon * std::max (std::max (norm_inf (e1), norm_inf (e2)), min_norm); } From 986547a60d34a9fae17d875109dc4fb75b520e6e Mon Sep 17 00:00:00 2001 From: Ronald Wampler Date: Mon, 28 Mar 2016 13:01:17 -0400 Subject: [PATCH 54/73] Add norm_2_square --- include/boost/numeric/ublas/functional.hpp | 46 +++++++++++++++++++ .../boost/numeric/ublas/vector_expression.hpp | 10 ++++ test/test_complex_norms.cpp | 33 +++++++++++++ 3 files changed, 89 insertions(+) diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index b0be20608..3613f7ad4 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -522,6 +522,52 @@ namespace boost { namespace numeric { namespace ublas { #endif } }; + + template + struct vector_norm_2_square : + public vector_scalar_real_unary_functor { + typedef typename vector_scalar_real_unary_functor::value_type value_type; + typedef typename vector_scalar_real_unary_functor::real_type real_type; + typedef typename vector_scalar_real_unary_functor::result_type result_type; + + template + static BOOST_UBLAS_INLINE + result_type apply (const vector_expression &e) { + real_type t = real_type (); + typedef typename E::size_type vector_size_type; + vector_size_type size (e ().size ()); + for (vector_size_type i = 0; i < size; ++ i) { + real_type u (type_traits::norm_2 (e () (i))); + t += u * u; + } + return t; + } + // Dense case + template + static BOOST_UBLAS_INLINE + result_type apply (D size, I it) { + real_type t = real_type (); + while (-- size >= 0) { + real_type u (type_traits::norm_2 (*it)); + t += u * u; + ++ it; + } + return t; + } + // Sparse case + template + static BOOST_UBLAS_INLINE + result_type apply (I it, const I &it_end) { + real_type t = real_type (); + while (it != it_end) { + real_type u (type_traits::norm_2 (*it)); + t += u * u; + ++ it; + } + return t; + } + }; + template struct vector_norm_inf: public vector_scalar_real_unary_functor { diff --git a/include/boost/numeric/ublas/vector_expression.hpp b/include/boost/numeric/ublas/vector_expression.hpp index d92207c98..6f952a464 100644 --- a/include/boost/numeric/ublas/vector_expression.hpp +++ b/include/boost/numeric/ublas/vector_expression.hpp @@ -1609,6 +1609,16 @@ namespace boost { namespace numeric { namespace ublas { return expression_type (e ()); } + // real: norm_2_square v = sum(v [i] * v [i]) + // complex: norm_2_square v = sum(v [i] * conj (v [i])) + template + BOOST_UBLAS_INLINE + typename vector_scalar_unary_traits >::result_type + norm_2_square (const vector_expression &e) { + typedef typename vector_scalar_unary_traits >::expression_type expression_type; + return expression_type (e ()); + } + // real: norm_inf v = maximum (abs (v [i])) // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i])))) template diff --git a/test/test_complex_norms.cpp b/test/test_complex_norms.cpp index d58a788ee..0c37ed45b 100644 --- a/test/test_complex_norms.cpp +++ b/test/test_complex_norms.cpp @@ -42,6 +42,21 @@ BOOST_UBLAS_TEST_DEF ( test_double_complex_norm_2 ) { BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - (3.0*expected)) < TOL); } +BOOST_UBLAS_TEST_DEF ( test_double_complex_norm_2_square ) { + typedef std::complex dComplex; + vector v(4); + for (unsigned int i = 0; i < v.size(); ++i) + v[i] = dComplex(i, i + 1); + + const double expected = 44; + + BOOST_UBLAS_DEBUG_TRACE( "square norm is " << norm_2_square(v) ); + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2_square(v) - expected) < TOL); + v *= 3.; + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2_square(v) - (9.0*expected)) < TOL); +} + + BOOST_UBLAS_TEST_DEF ( test_float_complex_norm_inf ) { typedef std::complex dComplex; vector v(4); @@ -74,6 +89,22 @@ BOOST_UBLAS_TEST_DEF ( test_float_complex_norm_2 ) { BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - (3.0*expected)) < TOL); } +BOOST_UBLAS_TEST_DEF ( test_float_complex_norm_2_square ) { + typedef std::complex dComplex; + vector v(4); + for (unsigned short i = 0; i < v.size(); ++i) { + unsigned short imag(i + 1); + v[i] = dComplex(i, imag); + } + + const double expected = 44; + + BOOST_UBLAS_DEBUG_TRACE( "square norm is " << norm_2_square(v) ); + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2_square(v) - expected) < TOL); + v *= 3.f; + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2_square(v) - (9.0*expected)) < TOL); +} + int main() { BOOST_UBLAS_TEST_BEGIN(); @@ -81,6 +112,8 @@ int main() { BOOST_UBLAS_TEST_DO( test_float_complex_norm_inf ); BOOST_UBLAS_TEST_DO( test_double_complex_norm_2 ); BOOST_UBLAS_TEST_DO( test_float_complex_norm_2 ); + BOOST_UBLAS_TEST_DO( test_double_complex_norm_2_square ); + BOOST_UBLAS_TEST_DO( test_float_complex_norm_2_square ); BOOST_UBLAS_TEST_END(); } From e88fc29650960ad0d1b9f7dbc5ce7fb2b7053a60 Mon Sep 17 00:00:00 2001 From: Ronald Wampler Date: Mon, 28 Mar 2016 13:34:15 -0400 Subject: [PATCH 55/73] Add documentation for norm_2_square --- doc/operations_overview.html | 3 ++- doc/vector_expression.html | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/operations_overview.html b/doc/operations_overview.html index 42d994212..212fcbebf 100644 --- a/doc/operations_overview.html +++ b/doc/operations_overview.html @@ -87,7 +87,8 @@

norms


 t = norm_inf(v); i = index_norm_inf(v);
-t = norm_1(v);   t = norm_2(v); 
+t = norm_1(v);   t = norm_2(v);
+t = norm_2_square(v);
 t = norm_inf(A); i = index_norm_inf(A);
 t = norm_1(A);   t = norm_frobenius(A); 
 
diff --git a/doc/vector_expression.html b/doc/vector_expression.html index 7838007ff..2372ec3df 100644 --- a/doc/vector_expression.html +++ b/doc/vector_expression.html @@ -847,6 +847,11 @@

Prototypes

typename vector_scalar_unary_traits<E, vector_norm_2<typename E::value_type> >::result_type norm_2 (const vector_expression<E> &e); + // norm_2_square v = sum (v [i] * v [i]) + template<class E> + typename vector_scalar_unary_traits<E, vector_norm_2_square<typename E::value_type> >::result_type + norm_2_square (const vector_expression<E> &e); + // norm_inf v = max (abs (v [i])) template<class E> typename vector_scalar_unary_traits<E, vector_norm_inf<typename E::value_type> >::result_type From ad76936f49fe3ad4c981afb5c4aab76df20615de Mon Sep 17 00:00:00 2001 From: Ronald Wampler Date: Thu, 7 Apr 2016 15:10:27 -0400 Subject: [PATCH 56/73] Fix compilation error when BOOST_UBLAS_SCALED_NORM is defined Commit e6b113 changed the `size_type` typedef to be based on the container and in doing so missed the case in vector_norm_2 when BOOST_UBLAS_SCALED_NORM is define. Also added test cases. --- include/boost/numeric/ublas/functional.hpp | 7 ++-- test/Jamfile.v2 | 4 +++ test/test_scaled_norm.cpp | 41 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/test_scaled_norm.cpp diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index 3613f7ad4..f54b441fe 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -433,10 +433,10 @@ namespace boost { namespace numeric { namespace ublas { template static BOOST_UBLAS_INLINE result_type apply (const vector_expression &e) { -#ifndef BOOST_UBLAS_SCALED_NORM - real_type t = real_type (); typedef typename E::size_type vector_size_type; vector_size_type size (e ().size ()); +#ifndef BOOST_UBLAS_SCALED_NORM + real_type t = real_type (); for (vector_size_type i = 0; i < size; ++ i) { real_type u (type_traits::norm_2 (e () (i))); t += u * u; @@ -445,8 +445,7 @@ namespace boost { namespace numeric { namespace ublas { #else real_type scale = real_type (); real_type sum_squares (1); - size_type size (e ().size ()); - for (size_type i = 0; i < size; ++ i) { + for (vector_size_type i = 0; i < size; ++ i) { real_type u (type_traits::norm_2 (e () (i))); if ( real_type () /* zero */ == u ) continue; if (scale < u) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 77e296c91..f990b76b9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -189,6 +189,10 @@ test-suite numeric/uBLAS ] [ run test_complex_norms.cpp ] + [ run test_scaled_norm.cpp + : : : + BOOST_UBLAS_SCALED_NORM + ] [ run test_assignment.cpp : : : BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT diff --git a/test/test_scaled_norm.cpp b/test/test_scaled_norm.cpp new file mode 100644 index 000000000..74065048f --- /dev/null +++ b/test/test_scaled_norm.cpp @@ -0,0 +1,41 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include "utils.hpp" + +using namespace boost::numeric::ublas; + +static const double TOL(1.0e-5); ///< Used for comparing two real numbers. + +BOOST_UBLAS_TEST_DEF ( test_double_scaled_norm_2 ) { + vector v(2); + v[0] = 0; v[1] = 1.0e155; + + const double expected = 1.0e155; + + BOOST_UBLAS_DEBUG_TRACE( "norm is " << norm_2(v) ); + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - expected) < TOL); +} + +BOOST_UBLAS_TEST_DEF ( test_float_scaled_norm_2 ) { + vector v(2); + v[0] = 0; v[1] = 1.0e20; + + const float expected = 1.0e20; + + BOOST_UBLAS_DEBUG_TRACE( "norm is " << norm_2(v) ); + BOOST_UBLAS_TEST_CHECK(std::abs(norm_2(v) - expected) < TOL); +} + +int main() { + BOOST_UBLAS_TEST_BEGIN(); + + BOOST_UBLAS_TEST_DO( test_double_scaled_norm_2 ); + BOOST_UBLAS_TEST_DO( test_float_scaled_norm_2 ); + + BOOST_UBLAS_TEST_END(); +} From 565dd1f5d08a5a2a40912dec3450163362285f7c Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 28 Apr 2018 12:22:16 -0400 Subject: [PATCH 57/73] Add basic CI support. --- .appveyor.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 .appveyor.yml create mode 100644 .travis.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..21bc96334 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,43 @@ +# Copyright 2018 Stefan Seefeld +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +version: 1.0.{build}-{branch} + +shallow_clone: true + +branches: + only: + - master + - develop + - /feature\/.*/ + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + TOOLSET: msvc-14.0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: msvc-14.1 + CXXSTD: 17 + +install: + - set BOOST_BRANCH=develop + - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master + - cd .. + - git clone -b %BOOST_BRANCH% https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/build + - git submodule update --init libs/config + - git submodule update --init tools/boostdep + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\numeric\ublas + - python tools/boostdep/depinst/depinst.py numeric/ublas + - cmd /c bootstrap + - b2 -d0 headers + +build: off + +test_script: + - PATH=%ADDPATH%%PATH% + - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j3 libs/numeric/ublas/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..088904827 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,50 @@ +# Copyright 2018 Stefan Seefeld +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +language: cpp + +sudo: false + +branches: + only: + - master + - develop + - doc + - ci + +matrix: + include: + - os: linux + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: osx + env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11 + + +install: + - cd .. + - git clone -b master --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/build + - git submodule update --init libs/config + - git submodule update --init tools/boostdep + - mkdir -p libs/numeric/ + - cp -r $TRAVIS_BUILD_DIR/* libs/numeric/ublas + - python tools/boostdep/depinst/depinst.py numeric/ublas + - ./bootstrap.sh + - ./b2 headers + +script: + - |- + echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" > ~/user-config.jam + - ./b2 libs/numeric/ublas/test toolset=$TOOLSET + +notifications: + email: + on_success: always From f14af0902086bc18195ce482d903f4b01cc40210 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 1 May 2018 18:33:18 -0400 Subject: [PATCH 58/73] Add CI badges. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a0387df25..c027ee79f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ ublas ===== +# Building [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=develop)](https://travis-ci.org/boostorg/ublas) [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/develop) + + The Boost.uBLAS Linear Algebra Library v1.0 - To follow development and test experimental features, you can clone the Github project uBLAS/ublas From ae28c2de699ae2d6901e3fac315163a609bf71f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Bron?= Date: Thu, 9 Aug 2018 07:06:57 +0200 Subject: [PATCH 59/73] Fixed unused argument warning in basic_column_major::upper_element Fixes issue #55 --- include/boost/numeric/ublas/functional.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/numeric/ublas/functional.hpp b/include/boost/numeric/ublas/functional.hpp index f54b441fe..571f510fa 100644 --- a/include/boost/numeric/ublas/functional.hpp +++ b/include/boost/numeric/ublas/functional.hpp @@ -1719,6 +1719,7 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_CHECK (i < size_i, bad_index ()); BOOST_UBLAS_CHECK (j < size_j, bad_index ()); BOOST_UBLAS_CHECK (i <= j, bad_index ()); + boost::ignore_unused(size_i, size_j); // FIXME size_type overflow // sigma_j (j + 1) = (j + 1) * j / 2 // j = 0 1 2 3, sigma = 0 1 3 6 From 1f0445c760fe3924f905dfafce47ceb3e648db89 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 26 Aug 2018 22:53:15 -0400 Subject: [PATCH 60/73] Introduce new benchmark framework. --- benchmarks/Jamfile | 11 +++++++ benchmarks/benchmark.hpp | 52 ++++++++++++++++++++++++++++++++ benchmarks/init.hpp | 37 +++++++++++++++++++++++ benchmarks/mm_prod.cpp | 62 ++++++++++++++++++++++++++++++++++++++ benchmarks/mv_prod.cpp | 64 ++++++++++++++++++++++++++++++++++++++++ benchmarks/plot.py | 60 +++++++++++++++++++++++++++++++++++++ benchmarks/prod.hpp | 36 ++++++++++++++++++++++ 7 files changed, 322 insertions(+) create mode 100644 benchmarks/Jamfile create mode 100644 benchmarks/benchmark.hpp create mode 100644 benchmarks/init.hpp create mode 100644 benchmarks/mm_prod.cpp create mode 100644 benchmarks/mv_prod.cpp create mode 100755 benchmarks/plot.py create mode 100644 benchmarks/prod.hpp diff --git a/benchmarks/Jamfile b/benchmarks/Jamfile new file mode 100644 index 000000000..9e70ee5dc --- /dev/null +++ b/benchmarks/Jamfile @@ -0,0 +1,11 @@ +# Copyright (c) 2018 Stefan Seefeld +# Use, modification and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +project boost/ublas/benchmarks + : requirements /boost/program_options//boost_program_options + ; + +exe mm_prod : mm_prod.cpp ; +exe mv_prod : mv_prod.cpp ; diff --git a/benchmarks/benchmark.hpp b/benchmarks/benchmark.hpp new file mode 100644 index 000000000..b06cbe55f --- /dev/null +++ b/benchmarks/benchmark.hpp @@ -0,0 +1,52 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +class benchmark +{ + using clock = std::chrono::system_clock; +public: + benchmark(std::string const &name) : name_(name) {} + void print_header() + { + std::cout << "# benchmark : " << name_ << '\n' + << "# size \ttime (ms)" << std::endl; + } + virtual void setup(long) {} + virtual void operation(long) {} + virtual void teardown() {} + + void run(std::vector const &sizes, unsigned times = 10) + { + print_header(); + for (auto s : sizes) + { + setup(s); + auto start = clock::now(); + for (unsigned i = 0; i != times; ++i) + operation(s); + auto duration = std::chrono::duration_cast(clock::now() - start); + teardown(); + std::cout << s << '\t' << duration.count()*1./times << std::endl; + } + } +private: + std::string name_; +}; + +}}}} diff --git a/benchmarks/init.hpp b/benchmarks/init.hpp new file mode 100644 index 000000000..1528389c3 --- /dev/null +++ b/benchmarks/init.hpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template +void init(vector &v, unsigned long size, int max_value) +{ + v = vector(size); + for (unsigned long i = 0; i < v.size(); ++i) + v(i) = std::rand() % max_value; +} + +template +void init(matrix &m, unsigned long size1, unsigned long size2, int max_value) +{ + m = matrix(size1, size2); + for (unsigned long i = 0; i < m.size1(); ++i) + for (unsigned long j = 0; j < m.size2(); ++j) + m(i, j) = std::rand() % max_value; +} + +template +void init(matrix &m, unsigned long size, int max_value) +{ + return init(m, size, size, max_value); +} + +}}}} diff --git a/benchmarks/mm_prod.cpp b/benchmarks/mm_prod.cpp new file mode 100644 index 000000000..fd7feb066 --- /dev/null +++ b/benchmarks/mm_prod.cpp @@ -0,0 +1,62 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "prod.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using matrix = ublas::matrix>; + bm::prod p("prod(matrix<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512}));//, 1024})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Matrix product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/mv_prod.cpp b/benchmarks/mv_prod.cpp new file mode 100644 index 000000000..c05e706a1 --- /dev/null +++ b/benchmarks/mv_prod.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "prod.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using matrix = ublas::matrix>; + using vector = ublas::vector; + bm::prod p("prod(matrix<" + type + ">, vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Matrix-vector product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/plot.py b/benchmarks/plot.py new file mode 100755 index 000000000..1ca5e5a7f --- /dev/null +++ b/benchmarks/plot.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# Copyright (c) 2018 Stefan Seefeld +# All rights reserved. +# +# This file is part of Boost.uBLAS. It is made available under the +# Boost Software License, Version 1.0. +# (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +import argparse +import matplotlib.pyplot as plt +import numpy as np + + +class plot(object): + + def __init__(self, label, data): + self.label = label + self.data = data + + +def load_file(filename): + + lines = open(filename, 'r').readlines() + label = lines[0][1:-1].strip() + lines = [l.strip() for l in lines] + lines = [l.split('#', 1)[0] for l in lines] + lines = [l for l in lines if l] + data = [l.split() for l in lines] + return plot(label, list(zip(*data))) + + +def main(argv): + + parser = argparse.ArgumentParser(prog=argv[0], description='benchmark plotter') + parser.add_argument('data', nargs='+', help='benchmark data to plot') + parser.add_argument('--log', choices=['no', 'all', 'x', 'y'], help='use a logarithmic scale') + args = parser.parse_args(argv[1:]) + runs = [load_file(d) for d in args.data] + plt.title('Benchmark plot') + plt.xlabel('size') + plt.ylabel('time (s)') + if args.log == 'all': + plot = plt.loglog + elif args.log == 'x': + plot = plt.semilogx + elif args.log == 'y': + plot = plt.semilogy + else: + plot = plt.plot + plots = [plot(r.data[0], r.data[1], label=r.label) for r in runs] + plt.legend() + plt.show() + return True + + +if __name__ == '__main__': + + import sys + sys.exit(0 if main(sys.argv) else 1) diff --git a/benchmarks/prod.hpp b/benchmarks/prod.hpp new file mode 100644 index 000000000..243bafcba --- /dev/null +++ b/benchmarks/prod.hpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include "init.hpp" +#include "benchmark.hpp" + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class prod; + +template +class prod : public benchmark +{ +public: + prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + c = ublas::prod(a, b); + } +private: + O1 a; + O2 b; + R c; +}; + +}}}} From daab9b0ea67d0ad0d6609b37b589c7ba170acf05 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 1 Sep 2018 10:53:52 -0400 Subject: [PATCH 61/73] Enable benchmark building during CI. --- .appveyor.yml | 3 ++- .travis.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 21bc96334..332227375 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -30,7 +30,7 @@ install: - git submodule update --init libs/config - git submodule update --init tools/boostdep - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\numeric\ublas - - python tools/boostdep/depinst/depinst.py numeric/ublas + - python tools/boostdep/depinst/depinst.py -I benchmarks numeric/ublas - cmd /c bootstrap - b2 -d0 headers @@ -41,3 +41,4 @@ test_script: - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% - b2 -j3 libs/numeric/ublas/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% + - b2 -j3 libs/numeric/ublas/benchmarks toolset=%TOOLSET% %CXXSTD% %ADDRMD% diff --git a/.travis.yml b/.travis.yml index 088904827..dea6389b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ install: - git submodule update --init tools/boostdep - mkdir -p libs/numeric/ - cp -r $TRAVIS_BUILD_DIR/* libs/numeric/ublas - - python tools/boostdep/depinst/depinst.py numeric/ublas + - python tools/boostdep/depinst/depinst.py -I benchmarks numeric/ublas - ./bootstrap.sh - ./b2 headers @@ -44,6 +44,7 @@ script: - |- echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" > ~/user-config.jam - ./b2 libs/numeric/ublas/test toolset=$TOOLSET + - ./b2 libs/numeric/ublas/benchmarks toolset=$TOOLSET notifications: email: From b788d5c8ebaa498c01319bf4e5f511e79619abb7 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 27 Sep 2018 20:48:25 -0400 Subject: [PATCH 62/73] Add more operations. --- benchmarks/Jamfile | 9 +++ benchmarks/add.cpp | 63 +++++++++++++++++++ benchmarks/add.hpp | 36 +++++++++++ benchmarks/inner_prod.cpp | 89 +++++++++++++++++++++++++++ benchmarks/mm_prod.cpp | 4 +- benchmarks/mv_prod.cpp | 4 +- benchmarks/outer_prod.cpp | 90 ++++++++++++++++++++++++++++ benchmarks/reference/add.cpp | 88 +++++++++++++++++++++++++++ benchmarks/reference/inner_prod.cpp | 91 ++++++++++++++++++++++++++++ benchmarks/reference/mm_prod.cpp | 93 +++++++++++++++++++++++++++++ benchmarks/reference/mv_prod.cpp | 92 ++++++++++++++++++++++++++++ benchmarks/reference/outer_prod.cpp | 92 ++++++++++++++++++++++++++++ 12 files changed, 747 insertions(+), 4 deletions(-) create mode 100644 benchmarks/add.cpp create mode 100644 benchmarks/add.hpp create mode 100644 benchmarks/inner_prod.cpp create mode 100644 benchmarks/outer_prod.cpp create mode 100644 benchmarks/reference/add.cpp create mode 100644 benchmarks/reference/inner_prod.cpp create mode 100644 benchmarks/reference/mm_prod.cpp create mode 100644 benchmarks/reference/mv_prod.cpp create mode 100644 benchmarks/reference/outer_prod.cpp diff --git a/benchmarks/Jamfile b/benchmarks/Jamfile index 9e70ee5dc..2e24c4a9d 100644 --- a/benchmarks/Jamfile +++ b/benchmarks/Jamfile @@ -7,5 +7,14 @@ project boost/ublas/benchmarks : requirements /boost/program_options//boost_program_options ; +exe add : add.cpp ; exe mm_prod : mm_prod.cpp ; exe mv_prod : mv_prod.cpp ; +exe inner_prod : inner_prod.cpp ; +exe outer_prod : outer_prod.cpp ; + +exe reference/add : reference/add.cpp ; +exe reference/mm_prod : reference/mm_prod.cpp ; +exe reference/mv_prod : reference/mv_prod.cpp ; +exe reference/inner_prod : reference/inner_prod.cpp ; +exe reference/outer_prod : reference/outer_prod.cpp ; diff --git a/benchmarks/add.cpp b/benchmarks/add.cpp new file mode 100644 index 000000000..0bab90bc1 --- /dev/null +++ b/benchmarks/add.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "add.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using vector = ublas::vector; + bm::add a("add(vector<" + type + ">, vector<" + type + ">)"); + a.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Vector-vector addition\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/add.hpp b/benchmarks/add.hpp new file mode 100644 index 000000000..d5d03d09f --- /dev/null +++ b/benchmarks/add.hpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include "init.hpp" +#include "benchmark.hpp" + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class add; + +template +class add : public benchmark +{ +public: + add(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + c = a + b; + } +private: + O1 a; + O2 b; + R c; +}; + +}}}} diff --git a/benchmarks/inner_prod.cpp b/benchmarks/inner_prod.cpp new file mode 100644 index 000000000..9d95a3339 --- /dev/null +++ b/benchmarks/inner_prod.cpp @@ -0,0 +1,89 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "init.hpp" +#include "benchmark.hpp" +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class inner_prod; + +template +class inner_prod : public benchmark +{ +public: + inner_prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + c = ublas::inner_prod(a, b); + } +private: + V1 a; + V2 b; + R c; +}; + +}}}} + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using vector = ublas::vector; + bm::inner_prod p("inner_prod(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Inner product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/mm_prod.cpp b/benchmarks/mm_prod.cpp index fd7feb066..f87271c7e 100644 --- a/benchmarks/mm_prod.cpp +++ b/benchmarks/mm_prod.cpp @@ -26,7 +26,7 @@ void benchmark(std::string const &type) int main(int argc, char **argv) { - po::variables_map vm; + po::variables_map vm; try { po::options_description desc("Matrix product\n" @@ -35,7 +35,7 @@ int main(int argc, char **argv) desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); + po::notify(vm); if (vm.count("help")) { diff --git a/benchmarks/mv_prod.cpp b/benchmarks/mv_prod.cpp index c05e706a1..bc6da2046 100644 --- a/benchmarks/mv_prod.cpp +++ b/benchmarks/mv_prod.cpp @@ -28,7 +28,7 @@ void benchmark(std::string const &type) int main(int argc, char **argv) { - po::variables_map vm; + po::variables_map vm; try { po::options_description desc("Matrix-vector product\n" @@ -37,7 +37,7 @@ int main(int argc, char **argv) desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); + po::notify(vm); if (vm.count("help")) { diff --git a/benchmarks/outer_prod.cpp b/benchmarks/outer_prod.cpp new file mode 100644 index 000000000..b907c360f --- /dev/null +++ b/benchmarks/outer_prod.cpp @@ -0,0 +1,90 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "init.hpp" +#include "benchmark.hpp" +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class outer_prod; + +template +class outer_prod : public benchmark +{ +public: + outer_prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + c = ublas::outer_prod(a, b); + } +private: + V1 a; + V2 b; + R c; +}; + +}}}} + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using vector = ublas::vector; + using matrix = ublas::matrix; + bm::outer_prod p("outer_prod(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Outer product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/reference/add.cpp b/benchmarks/reference/add.cpp new file mode 100644 index 000000000..d5b988701 --- /dev/null +++ b/benchmarks/reference/add.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "../init.hpp" +#include "../benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template +class add : public benchmark +{ +public: + add(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + for (int i = 0; i < l; ++i) + c(i) = a(i) + b(i); + } +private: + ublas::vector a; + ublas::vector b; + ublas::vector c; +}; + +}}}} + +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + bm::add p("ref::add(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Vector-vector addition (reference implementation)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/reference/inner_prod.cpp b/benchmarks/reference/inner_prod.cpp new file mode 100644 index 000000000..dc1752579 --- /dev/null +++ b/benchmarks/reference/inner_prod.cpp @@ -0,0 +1,91 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "../init.hpp" +#include "../benchmark.hpp" +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class inner_prod; + +template +class inner_prod : public benchmark +{ +public: + inner_prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + c = R(0); + for (int i = 0; i < l; ++i) + c += a(i) * b(i); + } +private: + V1 a; + V2 b; + R c; +}; + +}}}} + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using vector = ublas::vector; + bm::inner_prod p("ref::inner_prod(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Inner product (reference implementation)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/reference/mm_prod.cpp b/benchmarks/reference/mm_prod.cpp new file mode 100644 index 000000000..4b4363167 --- /dev/null +++ b/benchmarks/reference/mm_prod.cpp @@ -0,0 +1,93 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "../init.hpp" +#include "../benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template +class prod : public benchmark +{ +public: + prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + for (int i = 0; i < l; ++i) + for (int j = 0; j < l; ++j) + { + c(i,j) = 0; + for (int k = 0; k < l; ++k) + c(i,j) += a(i,k) * b(k,j); + } + } +private: + ublas::matrix a; + ublas::matrix b; + ublas::matrix c; +}; + +}}}} + +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + // using matrix = ublas::matrix>; + bm::prod p("ref::prod(matrix<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512}));//, 1024})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Matrix product (reference implementation)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/reference/mv_prod.cpp b/benchmarks/reference/mv_prod.cpp new file mode 100644 index 000000000..e3a157454 --- /dev/null +++ b/benchmarks/reference/mv_prod.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include "../init.hpp" +#include "../benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template +class prod : public benchmark +{ +public: + prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + for (int i = 0; i < l; ++i) + { + c(i) = 0; + for (int j = 0; j < l; ++j) + c(i) += a(i,j) * b(j); + } + } +private: + ublas::matrix a; + ublas::vector b; + ublas::vector c; +}; + +}}}} + +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + bm::prod p("ref::prod(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Matrix-vector product (reference implementation)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/reference/outer_prod.cpp b/benchmarks/reference/outer_prod.cpp new file mode 100644 index 000000000..a300066c2 --- /dev/null +++ b/benchmarks/reference/outer_prod.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "../init.hpp" +#include "../benchmark.hpp" +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template class outer_prod; + +template +class outer_prod : public benchmark +{ +public: + outer_prod(std::string const &name) : benchmark(name) {} + virtual void setup(long l) + { + init(a, l, 200); + init(b, l, 200); + } + virtual void operation(long l) + { + for (int i = 0; i < l; ++i) + for (int j = 0; j < l; ++j) + c(i,j) = - a(i) * b(j); + } +private: + V1 a; + V2 b; + R c; +}; + +}}}} + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; + +template +void benchmark(std::string const &type) +{ + using vector = ublas::vector; + using matrix = ublas::matrix; + bm::outer_prod p("ref::outer_prod(vector<" + type + ">)"); + p.run(std::vector({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096})); +} + +int main(int argc, char **argv) +{ + po::variables_map vm; + try + { + po::options_description desc("Outer product (reference implementation)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + if (type == "float") + benchmark("float"); + else if (type == "double") + benchmark("double"); + else if (type == "fcomplex") + benchmark>("std::complex"); + else if (type == "dcomplex") + benchmark>("std::complex"); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} From 44e7d7d853c69bd42d686059db5e6e2304bbef48 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 27 Sep 2018 20:53:53 -0400 Subject: [PATCH 63/73] Remove obsolete benchmarks. --- benchmarks/bench1/Jamfile.v2 | 10 - benchmarks/bench1/bench1.cpp | 122 ------ benchmarks/bench1/bench1.hpp | 159 -------- benchmarks/bench1/bench11.cpp | 287 -------------- benchmarks/bench1/bench12.cpp | 491 ------------------------ benchmarks/bench1/bench13.cpp | 192 ---------- benchmarks/bench2/Jamfile.v2 | 10 - benchmarks/bench2/bench2.cpp | 122 ------ benchmarks/bench2/bench2.hpp | 182 --------- benchmarks/bench2/bench21.cpp | 282 -------------- benchmarks/bench2/bench22.cpp | 469 ----------------------- benchmarks/bench2/bench23.cpp | 196 ---------- benchmarks/bench3/Jamfile.v2 | 10 - benchmarks/bench3/bench3.cpp | 122 ------ benchmarks/bench3/bench3.hpp | 159 -------- benchmarks/bench3/bench31.cpp | 296 --------------- benchmarks/bench3/bench32.cpp | 501 ------------------------- benchmarks/bench3/bench33.cpp | 198 ---------- benchmarks/bench4/Jamfile.v2 | 12 - benchmarks/bench4/bench4.cpp | 135 ------- benchmarks/bench4/bench41.cpp | 46 --- benchmarks/bench4/bench42.cpp | 46 --- benchmarks/bench4/bench43.cpp | 46 --- benchmarks/bench5/Jamfile.v2 | 11 - benchmarks/bench5/assignment_bench.cpp | 141 ------- 25 files changed, 4245 deletions(-) delete mode 100644 benchmarks/bench1/Jamfile.v2 delete mode 100644 benchmarks/bench1/bench1.cpp delete mode 100644 benchmarks/bench1/bench1.hpp delete mode 100644 benchmarks/bench1/bench11.cpp delete mode 100644 benchmarks/bench1/bench12.cpp delete mode 100644 benchmarks/bench1/bench13.cpp delete mode 100644 benchmarks/bench2/Jamfile.v2 delete mode 100644 benchmarks/bench2/bench2.cpp delete mode 100644 benchmarks/bench2/bench2.hpp delete mode 100644 benchmarks/bench2/bench21.cpp delete mode 100644 benchmarks/bench2/bench22.cpp delete mode 100644 benchmarks/bench2/bench23.cpp delete mode 100644 benchmarks/bench3/Jamfile.v2 delete mode 100644 benchmarks/bench3/bench3.cpp delete mode 100644 benchmarks/bench3/bench3.hpp delete mode 100644 benchmarks/bench3/bench31.cpp delete mode 100644 benchmarks/bench3/bench32.cpp delete mode 100644 benchmarks/bench3/bench33.cpp delete mode 100644 benchmarks/bench4/Jamfile.v2 delete mode 100644 benchmarks/bench4/bench4.cpp delete mode 100644 benchmarks/bench4/bench41.cpp delete mode 100644 benchmarks/bench4/bench42.cpp delete mode 100644 benchmarks/bench4/bench43.cpp delete mode 100644 benchmarks/bench5/Jamfile.v2 delete mode 100644 benchmarks/bench5/assignment_bench.cpp diff --git a/benchmarks/bench1/Jamfile.v2 b/benchmarks/bench1/Jamfile.v2 deleted file mode 100644 index 77b11c77e..000000000 --- a/benchmarks/bench1/Jamfile.v2 +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2004 Michael Stevens -# Use, modification and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# bench1 - measure the abstraction penalty of dense matrix and vector operations. - -exe bench1 - : bench1.cpp bench11.cpp bench12.cpp bench13.cpp - ; diff --git a/benchmarks/bench1/bench1.cpp b/benchmarks/bench1/bench1.cpp deleted file mode 100644 index 87478e139..000000000 --- a/benchmarks/bench1/bench1.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench1.hpp" - -void header (std::string text) { - std::cout << text << std::endl; -} - -template -struct peak_c_plus { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (0); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s += T (0); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct peak_c_multiplies { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s *= T (1); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -void peak::operator () (int runs) { - header ("peak"); - - header ("plus"); - peak_c_plus () (runs); - - header ("multiplies"); - peak_c_multiplies () (runs); -} - - -template -void do_bench (std::string type_string, int scale) -{ - header (type_string); - peak () (1000000 * scale); - - header (type_string + ", 3"); - bench_1 () (1000000 * scale); - bench_2 () (300000 * scale); - bench_3 () (100000 * scale); - - header (type_string + ", 10"); - bench_1 () (300000 * scale); - bench_2 () (30000 * scale); - bench_3 () (3000 * scale); - - header (type_string + ", 30"); - bench_1 () (100000 * scale); - bench_2 () (3000 * scale); - bench_3 () (100 * scale); - - header (type_string + ", 100"); - bench_1 () (30000 * scale); - bench_2 () (300 * scale); - bench_3 () (3 * scale); -} - -int main (int argc, char *argv []) { - - int scale = 1; - if (argc > 1) - scale = std::atoi (argv [1]); - -#ifdef USE_FLOAT - do_bench ("FLOAT", scale); -#endif - -#ifdef USE_DOUBLE - do_bench ("DOUBLE", scale); -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT - do_bench > ("COMPLEX", scale); -#endif - -#ifdef USE_DOUBLE - do_bench > ("COMPLEX", scale); -#endif -#endif - - return 0; -} diff --git a/benchmarks/bench1/bench1.hpp b/benchmarks/bench1/bench1.hpp deleted file mode 100644 index d799463d4..000000000 --- a/benchmarks/bench1/bench1.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#ifndef BENCH1_H -#define BENCH1_H - -#include -#include -#include - -#include -#include - -#include - - -#define BOOST_UBLAS_NOT_USED(x) (void)(x) - - -namespace ublas = boost::numeric::ublas; - -void header (std::string text); - -template -struct footer { - void operator () (int multiplies, int plus, int runs, double elapsed) { - std::cout << "elapsed: " << elapsed << " s, " - << (multiplies * ublas::type_traits::multiplies_complexity + - plus * ublas::type_traits::plus_complexity) * runs / - (1024 * 1024 * elapsed) << " Mflops" << std::endl; - } -}; - -template -struct c_vector_traits { - typedef T type [N]; -}; -template -struct c_matrix_traits { - typedef T type [N] [M]; -}; - -template -struct initialize_c_vector { - void operator () (typename c_vector_traits::type &v) { - for (int i = 0; i < N; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_vector (V &v) { - int size = v.size (); - for (int i = 0; i < size; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; -} - -template -struct initialize_c_matrix { - void operator () (typename c_matrix_traits::type &m) { - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - m [i] [j] = std::rand () * 1.f; -// m [i] [j] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_matrix (M &m) { - int size1 = m.size1 (); - int size2 = m.size2 (); - for (int i = 0; i < size1; ++ i) - for (int j = 0; j < size2; ++ j) - m (i, j) = std::rand () * 1.f; -// m (i, j) = 0.f; -} - -template -BOOST_UBLAS_INLINE -void sink_scalar (const T &s) { - static T g_s = s; -} - -template -struct sink_c_vector { - void operator () (const typename c_vector_traits::type &v) { - static typename c_vector_traits::type g_v; - for (int i = 0; i < N; ++ i) - g_v [i] = v [i]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_vector (const V &v) { - static V g_v (v); -} - -template -struct sink_c_matrix { - void operator () (const typename c_matrix_traits::type &m) { - static typename c_matrix_traits::type g_m; - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - g_m [i] [j] = m [i] [j]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_matrix (const M &m) { - static M g_m (m); -} - -template -struct peak { - void operator () (int runs); -}; - -template -struct bench_1 { - void operator () (int runs); -}; - -template -struct bench_2 { - void operator () (int runs); -}; - -template -struct bench_3 { - void operator () (int runs); -}; - -struct safe_tag {}; -struct fast_tag {}; - -//#define USE_FLOAT -#define USE_DOUBLE -// #define USE_STD_COMPLEX - -#define USE_C_ARRAY -// #define USE_BOUNDED_ARRAY -#define USE_UNBOUNDED_ARRAY -// #define USE_STD_VALARRAY -//#define USE_STD_VECTOR - -#endif - - diff --git a/benchmarks/bench1/bench11.cpp b/benchmarks/bench1/bench11.cpp deleted file mode 100644 index 806a422b0..000000000 --- a/benchmarks/bench1/bench11.cpp +++ /dev/null @@ -1,287 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench1.hpp" - -template -struct bench_c_inner_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - for (int j = 0; j < N; ++ j) { - s += v1 [j] * v2 [j]; - } -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = ublas::inner_prod (v1, v2); -// sink_scalar (s); - BOOST_UBLAS_NOT_USED(s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = (v1 * v2).sum (); -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_vector_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2, v3; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v3 [j] = - (v1 [j] + v2 [j]); - } -// sink_c_vector () (v3); - BOOST_UBLAS_NOT_USED(v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static V v1 (N), v2 (N), v3 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3 = - (v1 + v2); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static V v1 (N), v2 (N), v3 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3.assign (- (v1 + v2)); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N), v3 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3 = - (v1 + v2); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n) -template -void bench_1::operator () (int runs) { - header ("bench_1"); - - header ("inner_prod"); - - header ("C array"); - bench_c_inner_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_vector"); - bench_my_inner_prod, N> () (runs); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_STD_VALARRAY - header ("vector"); - bench_my_inner_prod >, N> () (); -#endif - -#ifdef USE_STD_VECTOR - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_inner_prod, N> () (runs); -#endif - - header ("vector + vector"); - - header ("C array"); - bench_c_vector_add () (runs); - -#ifdef USE_C_ARRAY - header ("c_vector safe"); - bench_my_vector_add, N> () (runs, safe_tag ()); - - header ("c_vector fast"); - bench_my_vector_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_vector_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_DOUBLE -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif -#endif diff --git a/benchmarks/bench1/bench12.cpp b/benchmarks/bench1/bench12.cpp deleted file mode 100644 index 439188f67..000000000 --- a/benchmarks/bench1/bench12.cpp +++ /dev/null @@ -1,491 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench1.hpp" - -template -struct bench_c_outer_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [j] [k] = - v1 [j] * v2 [k]; - } - } -// sink_c_matrix () (m); - } - BOOST_UBLAS_NOT_USED(m); - - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N); - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m = - ublas::outer_prod (v1, v2); -// sink_matrix (m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N); - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m.assign (- ublas::outer_prod (v1, v2)); -// sink_matrix (m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [N * j + k] = - v1 [j] * v2 [k]; - } - } -// sink_vector (m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_vector_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_matrix () (m); - initialize_c_vector () (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v2 [j] = 0; - for (int k = 0; k < N; ++ k) { - v2 [j] += m [j] [k] * v1 [k]; - } - } -// sink_c_vector () (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N); - static V v1 (N), v2 (N); - initialize_matrix (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v2 = ublas::prod (m, v1); -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N); - static V v1 (N), v2 (N); - initialize_matrix (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v2.assign (ublas::prod (m, v1)); -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m [std::slice (N * j, N, 1)]); - v2 [j] = (row * v1).sum (); - } -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = - (m1 [j] [k] + m2 [j] [k]); - } - } -// sink_c_matrix () (m3); - } - BOOST_UBLAS_NOT_USED(m3); - - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3.assign (- (m1 + m2)); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_vector (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 2) -template -void bench_2::operator () (int runs) { - header ("bench_2"); - - header ("outer_prod"); - - header ("C array"); - bench_c_outer_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix, c_vector safe"); - bench_my_outer_prod, - ublas::c_vector, N> () (runs, safe_tag ()); - - header ("c_matrix, c_vector fast"); - bench_my_outer_prod, - ublas::c_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_outer_prod, std::valarray, N> () (runs); -#endif - - header ("prod (matrix, vector)"); - - header ("C array"); - bench_c_matrix_vector_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix, c_vector safe"); - bench_my_matrix_vector_prod, - ublas::c_vector, N> () (runs, safe_tag ()); - - header ("c_matrix, c_vector fast"); - bench_my_matrix_vector_prod, - ublas::c_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_vector_prod, std::valarray, N> () (runs); -#endif - - header ("matrix + matrix"); - - header ("C array"); - bench_c_matrix_add () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix safe"); - bench_my_matrix_add, N> () (runs, safe_tag ()); - - header ("c_matrix fast"); - bench_my_matrix_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_DOUBLE -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif -#endif diff --git a/benchmarks/bench1/bench13.cpp b/benchmarks/bench1/bench13.cpp deleted file mode 100644 index fadb0b673..000000000 --- a/benchmarks/bench1/bench13.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench1.hpp" - -template -struct bench_c_matrix_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = 0; - for (int l = 0; l < N; ++ l) { - m3 [j] [k] += m1 [j] [l] * m2 [l] [k]; - } - } - } -// sink_c_matrix () (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = ublas::prod (m1, m2); -// sink_matrix (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3.assign (ublas::prod (m1, m2)); -// sink_matrix (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m1 [std::slice (N * j, N, 1)]); - for (int k = 0; k < N; ++ k) { - std::valarray column (m2 [std::slice (k, N, N)]); - m3 [N * j + k] = (row * column).sum (); - } - } -// sink_vector (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 3) -template -void bench_3::operator () (int runs) { - header ("bench_3"); - - header ("prod (matrix, matrix)"); - - header ("C array"); - bench_c_matrix_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix safe"); - bench_my_matrix_prod, N> () (runs, safe_tag ()); - - header ("c_matrix fast"); - bench_my_matrix_prod, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_prod, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_DOUBLE -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif -#endif diff --git a/benchmarks/bench2/Jamfile.v2 b/benchmarks/bench2/Jamfile.v2 deleted file mode 100644 index 4eb801591..000000000 --- a/benchmarks/bench2/Jamfile.v2 +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2004 Michael Stevens -# Use, modification and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# bench2 - measurs the performance of sparse matrix and vector operations. - -exe bench2 - : bench2.cpp bench21.cpp bench22.cpp bench23.cpp - ; diff --git a/benchmarks/bench2/bench2.cpp b/benchmarks/bench2/bench2.cpp deleted file mode 100644 index 43ba152f5..000000000 --- a/benchmarks/bench2/bench2.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench2.hpp" - -void header (std::string text) { - std::cout << text << std::endl; -} - -template -struct peak_c_plus { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (0); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s += T (0); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct peak_c_multiplies { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s *= T (1); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -void peak::operator () (int runs) { - header ("peak"); - - header ("plus"); - peak_c_plus () (runs); - - header ("multiplies"); - peak_c_multiplies () (runs); -} - - -template -void do_bench (std::string type_string, int scale) -{ - header (type_string); - peak () (1000000 * scale); - - header (type_string + ", 3"); - bench_1 () (1000000 * scale); - bench_2 () (300000 * scale); - bench_3 () (100000 * scale); - - header (type_string + ", 10"); - bench_1 () (300000 * scale); - bench_2 () (30000 * scale); - bench_3 () (3000 * scale); - - header (type_string + ", 30"); - bench_1 () (100000 * scale); - bench_2 () (3000 * scale); - bench_3 () (100 * scale); - - header (type_string + ", 100"); - bench_1 () (30000 * scale); - bench_2 () (300 * scale); - bench_3 () (3 * scale); -} - -int main (int argc, char *argv []) { - - int scale = 1; - if (argc > 1) - scale = std::atoi (argv [1]); - -#ifdef USE_FLOAT - do_bench ("FLOAT", scale); -#endif - -#ifdef USE_DOUBLE - do_bench ("DOUBLE", scale); -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT - do_bench > ("COMPLEX", scale); -#endif - -#ifdef USE_DOUBLE - do_bench > ("COMPLEX", scale); -#endif -#endif - - return 0; -} diff --git a/benchmarks/bench2/bench2.hpp b/benchmarks/bench2/bench2.hpp deleted file mode 100644 index efb20a27a..000000000 --- a/benchmarks/bench2/bench2.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#ifndef BENCH2_H -#define BENCH2_H - -#include -#include -#include - -#include -#include -#include -#include - -#include - - -#define BOOST_UBLAS_NOT_USED(x) (void)(x) - - -namespace ublas = boost::numeric::ublas; - -void header (std::string text); - -template -struct footer { - void operator () (int multiplies, int plus, int runs, double elapsed) { - std::cout << "elapsed: " << elapsed << " s, " - << (multiplies * ublas::type_traits::multiplies_complexity + - plus * ublas::type_traits::plus_complexity) * runs / - (1024 * 1024 * elapsed) << " Mflops" << std::endl; - } -}; - -template -struct c_vector_traits { - typedef T type [N]; -}; -template -struct c_matrix_traits { - typedef T type [N] [M]; -}; - -template -struct initialize_c_vector { - void operator () (typename c_vector_traits::type &v) { - for (int i = 0; i < N; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_vector (V &v) { - int size = v.size (); - for (int i = 0; i < size; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; -} - -template -struct initialize_c_matrix { - void operator () (typename c_matrix_traits::type &m) { - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - m [i] [j] = std::rand () * 1.f; -// m [i] [j] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_matrix (M &m, ublas::row_major_tag) { - int size1 = m.size1 (); - int size2 = m.size2 (); - for (int i = 0; i < size1; ++ i) - for (int j = 0; j < size2; ++ j) - m (i, j) = std::rand () * 1.f; -// m (i, j) = 0.f; -} -template -BOOST_UBLAS_INLINE -void initialize_matrix (M &m, ublas::column_major_tag) { - int size1 = m.size1 (); - int size2 = m.size2 (); - for (int j = 0; j < size2; ++ j) - for (int i = 0; i < size1; ++ i) - m (i, j) = std::rand () * 1.f; -// m (i, j) = 0.f; -} -template -BOOST_UBLAS_INLINE -void initialize_matrix (M &m) { - typedef typename M::orientation_category orientation_category; - initialize_matrix (m, orientation_category ()); -} - -template -BOOST_UBLAS_INLINE -void sink_scalar (const T &s) { - static T g_s = s; -} - -template -struct sink_c_vector { - void operator () (const typename c_vector_traits::type &v) { - static typename c_vector_traits::type g_v; - for (int i = 0; i < N; ++ i) - g_v [i] = v [i]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_vector (const V &v) { - static V g_v (v); -} - -template -struct sink_c_matrix { - void operator () (const typename c_matrix_traits::type &m) { - static typename c_matrix_traits::type g_m; - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - g_m [i] [j] = m [i] [j]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_matrix (const M &m) { - static M g_m (m); -} - -template -struct peak { - void operator () (int runs); -}; - -template -struct bench_1 { - void operator () (int runs); -}; - -template -struct bench_2 { - void operator () (int runs); -}; - -template -struct bench_3 { - void operator () (int runs); -}; - -struct safe_tag {}; -struct fast_tag {}; - -// #define USE_FLOAT -#define USE_DOUBLE -// #define USE_STD_COMPLEX - -#define USE_MAP_ARRAY -// #define USE_STD_MAP -// #define USE_STD_VALARRAY - -#define USE_MAPPED_VECTOR -#define USE_COMPRESSED_VECTOR -#define USE_COORDINATE_VECTOR - -#define USE_MAPPED_MATRIX -// #define USE_SPARSE_VECTOR_OF_SPARSE_VECTOR -#define USE_COMPRESSED_MATRIX -#define USE_COORDINATE_MATRIX - -#endif diff --git a/benchmarks/bench2/bench21.cpp b/benchmarks/bench2/bench21.cpp deleted file mode 100644 index 50d70a405..000000000 --- a/benchmarks/bench2/bench21.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench2.hpp" - -template -struct bench_c_inner_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - for (int j = 0; j < N; ++ j) { - s += v1 [j] * v2 [j]; - } -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N, N), v2 (N, N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = ublas::inner_prod (v1, v2); -// sink_scalar (s); - BOOST_UBLAS_NOT_USED(s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = (v1 * v2).sum (); -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_vector_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2, v3; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v3 [j] = - (v1 [j] + v2 [j]); - } -// sink_c_vector () (v3); - BOOST_UBLAS_NOT_USED(v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static V v1 (N, N), v2 (N, N), v3 (N, N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3 = - (v1 + v2); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static V v1 (N, N), v2 (N, N), v3 (N, N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3.assign (- (v1 + v2)); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N), v3 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3 = - (v1 + v2); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n) -template -void bench_1::operator () (int runs) { - header ("bench_1"); - - header ("inner_prod"); - - header ("C array"); - bench_c_inner_prod () (runs); - -#ifdef USE_MAPPED_VECTOR -#ifdef USE_MAP_ARRAY - header ("mapped_vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_STD_MAP - header ("mapped_vector"); - bench_my_inner_prod >, N> () (runs); -#endif -#endif - -#ifdef USE_COMPRESSED_VECTOR - header ("compressed_vector"); - bench_my_inner_prod, N> () (runs); -#endif - -#ifdef USE_COORDINATE_VECTOR - header ("coordinate_vector"); - bench_my_inner_prod, N> () (runs); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_inner_prod, N> () (runs); -#endif - - header ("vector + vector"); - - header ("C array"); - bench_c_vector_add () (runs); - -#ifdef USE_MAPPED_VECTOR -#ifdef USE_MAP_ARRAY - header ("mapped_vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("maped_vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_MAP - header ("mapped_vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("mapped_vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COMPRESSED_VECTOR -#ifdef USE_MAP_ARRAY - header ("compressed_vector safe"); - bench_my_vector_add, N> () (runs, safe_tag ()); - - header ("compressed_vector fast"); - bench_my_vector_add, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COORDINATE_VECTOR -#ifdef USE_MAP_ARRAY - header ("coordinate_vector safe"); - bench_my_vector_add, N> () (runs, safe_tag ()); - - header ("coordinate_vector fast"); - bench_my_vector_add, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_vector_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_DOUBLE -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif -#endif diff --git a/benchmarks/bench2/bench22.cpp b/benchmarks/bench2/bench22.cpp deleted file mode 100644 index f40df79ae..000000000 --- a/benchmarks/bench2/bench22.cpp +++ /dev/null @@ -1,469 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench2.hpp" - -template -struct bench_c_outer_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [j] [k] = - v1 [j] * v2 [k]; - } - } -// sink_c_matrix () (m); - BOOST_UBLAS_NOT_USED(m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N, N * N); - static V v1 (N, N), v2 (N, N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m = - ublas::outer_prod (v1, v2); -// sink_matrix (m); - BOOST_UBLAS_NOT_USED(m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N, N * N); - static V v1 (N, N), v2 (N, N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m.assign (- ublas::outer_prod (v1, v2)); -// sink_matrix (m); - BOOST_UBLAS_NOT_USED(m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [N * j + k] = - v1 [j] * v2 [k]; - } - } -// sink_vector (m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_vector_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_matrix () (m); - initialize_c_vector () (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v2 [j] = 0; - for (int k = 0; k < N; ++ k) { - v2 [j] += m [j] [k] * v1 [k]; - } - } -// sink_c_vector () (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N, N * N); - static V v1 (N, N), v2 (N, N); - initialize_matrix (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v2 = ublas::prod (m, v1); -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N, N * N); - static V v1 (N, N), v2 (N, N); - initialize_matrix (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v2.assign (ublas::prod (m, v1)); -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m [std::slice (N * j, N, 1)]); - v2 [j] = (row * v1).sum (); - } -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = - (m1 [j] [k] + m2 [j] [k]); - } - } -// sink_c_matrix () (m3); - BOOST_UBLAS_NOT_USED(m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m1 (N, N, N * N), m2 (N, N, N * N), m3 (N, N, N * N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m1 (N, N, N * N), m2 (N, N, N * N), m3 (N, N, N * N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3.assign (- (m1 + m2)); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_vector (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 2) -template -void bench_2::operator () (int runs) { - header ("bench_2"); - - header ("outer_prod"); - - header ("C array"); - bench_c_outer_prod () (runs); - -#ifdef USE_SPARSE_MATRIX -#ifdef USE_MAP_ARRAY - header ("sparse_matrix, sparse_vector safe"); - bench_my_outer_prod >, - ublas::sparse_vector >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_vector fast"); - bench_my_outer_prod >, - ublas::sparse_vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_MAP - header ("sparse_matrix, sparse_vector safe"); - bench_my_outer_prod >, - ublas::sparse_vector >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_vector fast"); - bench_my_outer_prod >, - ublas::sparse_vector >, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COMPRESSED_MATRIX - header ("compressed_matrix, compressed_vector safe"); - bench_my_outer_prod, - ublas::compressed_vector, N> () (runs, safe_tag ()); - - header ("compressed_matrix, compressed_vector fast"); - bench_my_outer_prod, - ublas::compressed_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_COORDINATE_MATRIX - header ("coordinate_matrix, coordinate_vector safe"); - bench_my_outer_prod, - ublas::coordinate_vector, N> () (runs, safe_tag ()); - - header ("coordinate_matrix, coordinate_vector fast"); - bench_my_outer_prod, - ublas::coordinate_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_outer_prod, std::valarray, N> () (runs); -#endif - - header ("prod (matrix, vector)"); - - header ("C array"); - bench_c_matrix_vector_prod () (runs); - -#ifdef USE_SPARSE_MATRIX -#ifdef USE_MAP_ARRAY - header ("sparse_matrix, sparse_vector safe"); - bench_my_matrix_vector_prod >, - ublas::sparse_vector >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_vector fast"); - bench_my_matrix_vector_prod >, - ublas::sparse_vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_MAP - header ("sparse_matrix, sparse_vector safe"); - bench_my_matrix_vector_prod >, - ublas::sparse_vector >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_vector fast"); - bench_my_matrix_vector_prod >, - ublas::sparse_vector >, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COMPRESSED_MATRIX - header ("compressed_matrix, compressed_vector safe"); - bench_my_matrix_vector_prod, - ublas::compressed_vector, N> () (runs, safe_tag ()); - - header ("compressed_matrix, compressed_vector fast"); - bench_my_matrix_vector_prod, - ublas::compressed_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_COORDINATE_MATRIX - header ("coordinate_matrix, coordinate_vector safe"); - bench_my_matrix_vector_prod, - ublas::coordinate_vector, N> () (runs, safe_tag ()); - - header ("coordinate_matrix, coordinate_vector fast"); - bench_my_matrix_vector_prod, - ublas::coordinate_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_vector_prod, std::valarray, N> () (runs); -#endif - - header ("matrix + matrix"); - - header ("C array"); - bench_c_matrix_add () (runs); - -#ifdef USE_SPARSE_MATRIX -#ifdef USE_MAP_ARRAY - header ("sparse_matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("sparse_matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_MAP - header ("sparse_matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("sparse_matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COMPRESSED_MATRIX - header ("compressed_matrix safe"); - bench_my_matrix_add, N> () (runs, safe_tag ()); - - header ("compressed_matrix fast"); - bench_my_matrix_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_COORDINATE_MATRIX - header ("coordinate_matrix safe"); - bench_my_matrix_add, N> () (runs, safe_tag ()); - - header ("coordinate_matrix fast"); - bench_my_matrix_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_DOUBLE -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif -#endif diff --git a/benchmarks/bench2/bench23.cpp b/benchmarks/bench2/bench23.cpp deleted file mode 100644 index bb363f537..000000000 --- a/benchmarks/bench2/bench23.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench2.hpp" - -template -struct bench_c_matrix_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = 0; - for (int l = 0; l < N; ++ l) { - m3 [j] [k] += m1 [j] [l] * m2 [l] [k]; - } - } - } -// sink_c_matrix () (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_prod { - typedef typename M1::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M1 m1 (N, N, N * N), m3 (N, N, N * N); - static M2 m2 (N, N, N * N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = ublas::prod (m1, m2); -// sink_matrix (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M1 m1 (N, N, N * N), m3 (N, N, N * N); - static M2 m2 (N, N, N * N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3.assign (ublas::prod (m1, m2)); -// sink_matrix (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m1 [std::slice (N * j, N, 1)]); - for (int k = 0; k < N; ++ k) { - std::valarray column (m2 [std::slice (k, N, N)]); - m3 [N * j + k] = (row * column).sum (); - } - } -// sink_vector (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 3) -template -void bench_3::operator () (int runs) { - header ("bench_3"); - - header ("prod (matrix, matrix)"); - - header ("C array"); - bench_c_matrix_prod () (runs); - -#ifdef USE_SPARSE_MATRIX -#ifdef USE_MAP_ARRAY - header ("sparse_matrix, sparse_matrix safe"); - bench_my_matrix_prod >, - ublas::sparse_matrix >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_matrix fast"); - bench_my_matrix_prod >, - ublas::sparse_matrix >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_MAP - header ("sparse_matrix, sparse_matrix safe"); - bench_my_matrix_prod >, - ublas::sparse_matrix >, N> () (runs, safe_tag ()); - - header ("sparse_matrix, sparse_matrix fast"); - bench_my_matrix_prod >, - ublas::sparse_matrix >, N> () (runs, fast_tag ()); -#endif -#endif - -#ifdef USE_COMPRESSED_MATRIX - header ("compressed_matrix, compressed_matrix safe"); - bench_my_matrix_prod, - ublas::compressed_matrix, N> () (runs, safe_tag ()); - - header ("compressed_matrix, compressed_matrix fast"); - bench_my_matrix_prod, - ublas::compressed_matrix, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_COORDINATE_MATRIX - header ("coordinate_matrix, coordinate_matrix safe"); - bench_my_matrix_prod, - ublas::coordinate_matrix, N> () (runs, safe_tag ()); - - header ("coordinate_matrix, coordinate_matrix fast"); - bench_my_matrix_prod, - ublas::coordinate_matrix, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_prod, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_DOUBLE -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif -#endif diff --git a/benchmarks/bench3/Jamfile.v2 b/benchmarks/bench3/Jamfile.v2 deleted file mode 100644 index 7ce9c9b85..000000000 --- a/benchmarks/bench3/Jamfile.v2 +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2004 Michael Stevens -# Use, modification and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# bench3 - measure the performance of vector and matrix proxy's operations. - -exe bench3 - : bench3.cpp bench31.cpp bench32.cpp bench33.cpp - ; diff --git a/benchmarks/bench3/bench3.cpp b/benchmarks/bench3/bench3.cpp deleted file mode 100644 index 390d226ca..000000000 --- a/benchmarks/bench3/bench3.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench3.hpp" - -void header (std::string text) { - std::cout << text << std::endl; -} - -template -struct peak_c_plus { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (0); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s += T (0); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct peak_c_multiplies { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s *= T (1); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -void peak::operator () (int runs) { - header ("peak"); - - header ("plus"); - peak_c_plus () (runs); - - header ("multiplies"); - peak_c_multiplies () (runs); -} - - -template -void do_bench (std::string type_string, int scale) -{ - header (type_string); - peak () (1000000 * scale); - - header (type_string + ", 3"); - bench_1 () (1000000 * scale); - bench_2 () (300000 * scale); - bench_3 () (100000 * scale); - - header (type_string + ", 10"); - bench_1 () (300000 * scale); - bench_2 () (30000 * scale); - bench_3 () (3000 * scale); - - header (type_string + ", 30"); - bench_1 () (100000 * scale); - bench_2 () (3000 * scale); - bench_3 () (100 * scale); - - header (type_string + ", 100"); - bench_1 () (30000 * scale); - bench_2 () (300 * scale); - bench_3 () (3 * scale); -} - -int main (int argc, char *argv []) { - - int scale = 1; - if (argc > 1) - scale = std::atoi (argv [1]); - -#ifdef USE_FLOAT - do_bench ("FLOAT", scale); -#endif - -#ifdef USE_DOUBLE - do_bench ("DOUBLE", scale); -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT - do_bench > ("COMPLEX", scale); -#endif - -#ifdef USE_DOUBLE - do_bench > ("COMPLEX", scale); -#endif -#endif - - return 0; -} diff --git a/benchmarks/bench3/bench3.hpp b/benchmarks/bench3/bench3.hpp deleted file mode 100644 index 5b64b59af..000000000 --- a/benchmarks/bench3/bench3.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#ifndef BENCH3_H -#define BENCH3_H - -#include -#include -#include - -#include -#include -#include -#include - -#include - - -#define BOOST_UBLAS_NOT_USED(x) (void)(x) - - -namespace ublas = boost::numeric::ublas; - -void header (std::string text); - -template -struct footer { - void operator () (int multiplies, int plus, int runs, double elapsed) { - std::cout << "elapsed: " << elapsed << " s, " - << (multiplies * ublas::type_traits::multiplies_complexity + - plus * ublas::type_traits::plus_complexity) * runs / - (1024 * 1024 * elapsed) << " Mflops" << std::endl; - } -}; - -template -struct c_vector_traits { - typedef T type [N]; -}; -template -struct c_matrix_traits { - typedef T type [N] [M]; -}; - -template -struct initialize_c_vector { - void operator () (typename c_vector_traits::type &v) { - for (int i = 0; i < N; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_vector (V &v) { - int size = v.size (); - for (int i = 0; i < size; ++ i) - v [i] = std::rand () * 1.f; -// v [i] = 0.f; -} - -template -struct initialize_c_matrix { - void operator () (typename c_matrix_traits::type &m) { - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - m [i] [j] = std::rand () * 1.f; -// m [i] [j] = 0.f; - } -}; -template -BOOST_UBLAS_INLINE -void initialize_matrix (M &m) { - int size1 = m.size1 (); - int size2 = m.size2 (); - for (int i = 0; i < size1; ++ i) - for (int j = 0; j < size2; ++ j) - m (i, j) = std::rand () * 1.f; -// m (i, j) = 0.f; -} - -template -BOOST_UBLAS_INLINE -void sink_scalar (const T &s) { - static T g_s = s; -} - -template -struct sink_c_vector { - void operator () (const typename c_vector_traits::type &v) { - static typename c_vector_traits::type g_v; - for (int i = 0; i < N; ++ i) - g_v [i] = v [i]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_vector (const V &v) { - static V g_v (v); -} - -template -struct sink_c_matrix { - void operator () (const typename c_matrix_traits::type &m) { - static typename c_matrix_traits::type g_m; - for (int i = 0; i < N; ++ i) - for (int j = 0; j < M; ++ j) - g_m [i] [j] = m [i] [j]; - } -}; -template -BOOST_UBLAS_INLINE -void sink_matrix (const M &m) { - static M g_m (m); -} - -template -struct peak { - void operator () (int runs); -}; - -template -struct bench_1 { - void operator () (int runs); -}; - -template -struct bench_2 { - void operator () (int runs); -}; - -template -struct bench_3 { - void operator () (int runs); -}; - -struct safe_tag {}; -struct fast_tag {}; - -// #define USE_FLOAT -#define USE_DOUBLE -// #define USE_STD_COMPLEX - -#define USE_C_ARRAY -// #define USE_BOUNDED_ARRAY -#define USE_UNBOUNDED_ARRAY -// #define USE_STD_VALARRAY -#define USE_STD_VECTOR - -#endif diff --git a/benchmarks/bench3/bench31.cpp b/benchmarks/bench3/bench31.cpp deleted file mode 100644 index 9181eb1cf..000000000 --- a/benchmarks/bench3/bench31.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench3.hpp" - -template -struct bench_c_inner_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - for (int j = 0; j < N; ++ j) { - s += v1 [j] * v2 [j]; - } -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)); - initialize_vector (vr1); - initialize_vector (vr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = ublas::inner_prod (vr1, vr2); -// sink_scalar (s); - BOOST_UBLAS_NOT_USED(s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_inner_prod { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - static value_type s (0); - s = (v1 * v2).sum (); -// sink_scalar (s); - } - footer () (N, N - 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_vector_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_vector_traits::type v1, v2, v3; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v3 [j] = - (v1 [j] + v2 [j]); - } -// sink_c_vector () (v3); - BOOST_UBLAS_NOT_USED(v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static V v1 (N), v2 (N), v3 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)), - vr3 (v2, ublas::range (0, N)); - initialize_vector (vr1); - initialize_vector (vr2); - initialize_vector (vr3); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - vr3 = - (vr1 + vr2); -// sink_vector (vr3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static V v1 (N), v2 (N), v3 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)), - vr3 (v2, ublas::range (0, N)); - initialize_vector (vr1); - initialize_vector (vr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - vr3.assign (- (vr1 + vr2)); -// sink_vector (vr3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_vector_add { - typedef typename V::value_type value_type; - - void operator () (int runs) const { - try { - static V v1 (N), v2 (N), v3 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - v3 = - (v1 + v2); -// sink_vector (v3); - } - footer () (0, 2 * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n) -template -void bench_1::operator () (int runs) { - header ("bench_1"); - - header ("inner_prod"); - - header ("C array"); - bench_c_inner_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_vector"); - bench_my_inner_prod, N> () (runs); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_STD_VALARRAY - header ("vector"); - bench_my_inner_prod >, N> () (); -#endif - -#ifdef USE_STD_VECTOR - header ("vector"); - bench_my_inner_prod >, N> () (runs); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_inner_prod, N> () (runs); -#endif - - header ("vector + vector"); - - header ("C array"); - bench_c_vector_add () (runs); - -#ifdef USE_C_ARRAY - header ("c_vector safe"); - bench_my_vector_add, N> () (runs, safe_tag ()); - - header ("c_vector fast"); - bench_my_vector_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("vector safe"); - bench_my_vector_add >, N> () (runs, safe_tag ()); - - header ("vector fast"); - bench_my_vector_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_vector_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_DOUBLE -template struct bench_1; -template struct bench_1; -template struct bench_1; -template struct bench_1; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif -#endif diff --git a/benchmarks/bench3/bench32.cpp b/benchmarks/bench3/bench32.cpp deleted file mode 100644 index 3819090bb..000000000 --- a/benchmarks/bench3/bench32.cpp +++ /dev/null @@ -1,501 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench3.hpp" - -template -struct bench_c_outer_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_vector () (v1); - initialize_c_vector () (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [j] [k] = - v1 [j] * v2 [k]; - } - } -// sink_c_matrix () (m); - BOOST_UBLAS_NOT_USED(m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N); - ublas::matrix_range mr (m, ublas::range (0, N), ublas::range (0, N)); - static V v1 (N), v2 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)); - initialize_vector (vr1); - initialize_vector (vr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - mr = - ublas::outer_prod (vr1, vr2); -// sink_matrix (mr); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N); - ublas::matrix_range mr (m, ublas::range (0, N), ublas::range (0, N)); - static V v1 (N), v2 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)); - initialize_vector (vr1); - initialize_vector (vr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - mr.assign (- ublas::outer_prod (vr1, vr2)); -// sink_matrix (mr); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_outer_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (v1); - initialize_vector (v2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m [N * j + k] = - v1 [j] * v2 [k]; - } - } -// sink_vector (m); - } - footer () (N * N, N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_vector_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m; - static typename c_vector_traits::type v1, v2; - initialize_c_matrix () (m); - initialize_c_vector () (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - v2 [j] = 0; - for (int k = 0; k < N; ++ k) { - v2 [j] += m [j] [k] * v1 [k]; - } - } -// sink_c_vector () (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m (N, N); - ublas::matrix_range mr (m, ublas::range (0, N), ublas::range (0, N)); - static V v1 (N), v2 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)); - initialize_matrix (mr); - initialize_vector (vr1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - vr2 = ublas::prod (mr, vr1); -// sink_vector (vr2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m (N, N); - ublas::matrix_range mr (m, ublas::range (0, N), ublas::range (0, N)); - static V v1 (N), v2 (N); - ublas::vector_range vr1 (v1, ublas::range (0, N)), - vr2 (v2, ublas::range (0, N)); - initialize_matrix (mr); - initialize_vector (vr1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - vr2.assign (ublas::prod (mr, vr1)); -// sink_vector (vr2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_vector_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m (N * N); - static V v1 (N), v2 (N); - initialize_vector (m); - initialize_vector (v1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m [std::slice (N * j, N, 1)]); - v2 [j] = (row * v1).sum (); - } -// sink_vector (v2); - } - footer () (N * N, N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -struct bench_c_matrix_add { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = - (m1 [j] [k] + m2 [j] [k]); - } - } -// sink_c_matrix () (m3); - BOOST_UBLAS_NOT_USED(m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - initialize_matrix (m1); - initialize_matrix (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3.assign (- (m1 + m2)); -// sink_matrix (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_add { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - m3 = - (m1 + m2); -// sink_vector (m3); - } - footer () (0, 2 * N * N, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 2) -template -void bench_2::operator () (int runs) { - header ("bench_2"); - - header ("outer_prod"); - - header ("C array"); - bench_c_outer_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix, c_vector safe"); - bench_my_outer_prod, - ublas::c_vector, N> () (runs, safe_tag ()); - - header ("c_matrix, c_vector fast"); - bench_my_outer_prod, - ublas::c_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix, vector safe"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_outer_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_outer_prod, std::valarray, N> () (runs); -#endif - - header ("prod (matrix, vector)"); - - header ("C array"); - bench_c_matrix_vector_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix, c_vector safe"); - bench_my_matrix_vector_prod, - ublas::c_vector, N> () (runs, safe_tag ()); - - header ("c_matrix, c_vector fast"); - bench_my_matrix_vector_prod, - ublas::c_vector, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix, vector safe"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, safe_tag ()); - - header ("matrix, vector fast"); - bench_my_matrix_vector_prod >, - ublas::vector >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_vector_prod, std::valarray, N> () (runs); -#endif - - header ("matrix + matrix"); - - header ("C array"); - bench_c_matrix_add () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix safe"); - bench_my_matrix_add, N> () (runs, safe_tag ()); - - header ("c_matrix fast"); - bench_my_matrix_add, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix safe"); - bench_my_matrix_add >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_add >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_add, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_DOUBLE -template struct bench_2; -template struct bench_2; -template struct bench_2; -template struct bench_2; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif -#endif diff --git a/benchmarks/bench3/bench33.cpp b/benchmarks/bench3/bench33.cpp deleted file mode 100644 index 9b8e1070e..000000000 --- a/benchmarks/bench3/bench33.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include "bench3.hpp" - -template -struct bench_c_matrix_prod { - typedef T value_type; - - void operator () (int runs) const { - try { - static typename c_matrix_traits::type m1, m2, m3; - initialize_c_matrix () (m1); - initialize_c_matrix () (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - for (int k = 0; k < N; ++ k) { - m3 [j] [k] = 0; - for (int l = 0; l < N; ++ l) { - m3 [j] [k] += m1 [j] [l] * m2 [l] [k]; - } - } - } -// sink_c_matrix () (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_my_matrix_prod { - typedef typename M::value_type value_type; - - void operator () (int runs, safe_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), - mr2 (m2, ublas::range (0, N), ublas::range (0, N)), - mr3 (m3, ublas::range (0, N), ublas::range (0, N)); - initialize_matrix (mr1); - initialize_matrix (mr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - mr3 = ublas::prod (mr1, mr2); -// sink_matrix (mr3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } - void operator () (int runs, fast_tag) const { - try { - static M m1 (N, N), m2 (N, N), m3 (N, N); - ublas::matrix_range mr1 (m1, ublas::range (0, N), ublas::range (0, N)), - mr2 (m2, ublas::range (0, N), ublas::range (0, N)), - mr3 (m3, ublas::range (0, N), ublas::range (0, N)); - initialize_matrix (mr1); - initialize_matrix (mr2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - mr3.assign (ublas::prod (mr1, mr2)); -// sink_matrix (mr3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct bench_cpp_matrix_prod { - typedef typename M::value_type value_type; - - void operator () (int runs) const { - try { - static M m1 (N * N), m2 (N * N), m3 (N * N); - initialize_vector (m1); - initialize_vector (m2); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - for (int j = 0; j < N; ++ j) { - std::valarray row (m1 [std::slice (N * j, N, 1)]); - for (int k = 0; k < N; ++ k) { - std::valarray column (m2 [std::slice (k, N, N)]); - m3 [N * j + k] = (row * column).sum (); - } - } -// sink_vector (m3); - } - footer () (N * N * N, N * N * (N - 1), runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -// Benchmark O (n ^ 3) -template -void bench_3::operator () (int runs) { - header ("bench_3"); - - header ("prod (matrix, matrix)"); - - header ("C array"); - bench_c_matrix_prod () (runs); - -#ifdef USE_C_ARRAY - header ("c_matrix safe"); - bench_my_matrix_prod, N> () (runs, safe_tag ()); - - header ("c_matrix fast"); - bench_my_matrix_prod, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_BOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_UNBOUNDED_ARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VECTOR - header ("matrix safe"); - bench_my_matrix_prod >, N> () (runs, safe_tag ()); - - header ("matrix fast"); - bench_my_matrix_prod >, N> () (runs, fast_tag ()); -#endif - -#ifdef USE_STD_VALARRAY - header ("std::valarray"); - bench_cpp_matrix_prod, N> () (runs); -#endif -} - -#ifdef USE_FLOAT -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_DOUBLE -template struct bench_3; -template struct bench_3; -template struct bench_3; -template struct bench_3; -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif -#endif diff --git a/benchmarks/bench4/Jamfile.v2 b/benchmarks/bench4/Jamfile.v2 deleted file mode 100644 index 94a9f0700..000000000 --- a/benchmarks/bench4/Jamfile.v2 +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2004 Michael Stevens -# Use, modification and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# bench4 measurs the abstraction penalty of dense matrix and vector -# operations with boost::numeric::interval(s). - -exe bench4 - : bench4.cpp bench41.cpp bench42.cpp bench43.cpp - : BOOST_UBLAS_USE_INTERVAL - ; diff --git a/benchmarks/bench4/bench4.cpp b/benchmarks/bench4/bench4.cpp deleted file mode 100644 index 6d460eb16..000000000 --- a/benchmarks/bench4/bench4.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include -#include -#include "../bench1/bench1.hpp" - -void header (std::string text) { - std::cout << text << std::endl; -} - -template -struct peak_c_plus { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (0); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s += T (0); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; -template -struct peak_c_multiplies { - typedef T value_type; - - void operator () (int runs) const { - try { - static T s (1); - boost::timer t; - for (int i = 0; i < runs; ++ i) { - s *= T (1); -// sink_scalar (s); - } - footer () (0, 1, runs, t.elapsed ()); - } - catch (std::exception &e) { - std::cout << e.what () << std::endl; - } - } -}; - -template -void peak::operator () (int runs) { - header ("peak"); - - header ("plus"); - peak_c_plus () (runs); - - header ("multiplies"); - peak_c_multiplies () (runs); -} - -template struct peak >; -template struct peak >; - -#ifdef USE_BOOST_COMPLEX - -template struct peak > >; -template struct peak > >; - -#endif - - - -template -void do_bench (std::string type_string, int scale) -{ - header (type_string); - peak () (1000000 * scale); - - header (type_string + ", 3"); - bench_1 () (1000000 * scale); - bench_2 () (300000 * scale); - bench_3 () (100000 * scale); - - header (type_string + ", 10"); - bench_1 () (300000 * scale); - bench_2 () (30000 * scale); - bench_3 () (3000 * scale); - - header (type_string + ", 30"); - bench_1 () (100000 * scale); - bench_2 () (3000 * scale); - bench_3 () (100 * scale); - - header (type_string + ", 100"); - bench_1 () (30000 * scale); - bench_2 () (300 * scale); - bench_3 () (3 * scale); -} - -int main (int argc, char *argv []) { - - int scale = 1; - if (argc > 1) - scale = std::atoi (argv [1]); - -#ifdef USE_FLOAT - do_bench > ("boost::numeric::interval", scale); -#endif - -#ifdef USE_DOUBLE - do_bench > ("boost::numeric::interval", scale); -#endif - -#ifdef USE_STD_COMPLEX -#ifdef USE_FLOAT - do_bench > > ("boost::numeric::interval>", scale); -#endif - -#ifdef USE_DOUBLE - do_bench > > ("boost::numeric::interval>", scale); -#endif -#endif - - return 0; -} diff --git a/benchmarks/bench4/bench41.cpp b/benchmarks/bench4/bench41.cpp deleted file mode 100644 index 2ef2d696f..000000000 --- a/benchmarks/bench4/bench41.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include -#include -#include "../bench1/bench11.cpp" - - -#ifdef USE_FLOAT -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_1, 3>; -template struct bench_1, 10>; -template struct bench_1, 30>; -template struct bench_1, 100>; -#endif - -#ifdef USE_BOOST_COMPLEX -#ifdef USE_FLOAT -template struct bench_1 >, 3>; -template struct bench_1 >, 10>; -template struct bench_1 >, 30>; -template struct bench_1 >, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_1 >, 3>; -template struct bench_1 >, 10>; -template struct bench_1 >, 30>; -template struct bench_1 >, 100>; -#endif -#endif diff --git a/benchmarks/bench4/bench42.cpp b/benchmarks/bench4/bench42.cpp deleted file mode 100644 index 55f9060bc..000000000 --- a/benchmarks/bench4/bench42.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include -#include -#include "../bench1/bench12.cpp" - - -#ifdef USE_FLOAT -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_2, 3>; -template struct bench_2, 10>; -template struct bench_2, 30>; -template struct bench_2, 100>; -#endif - -#ifdef USE_BOOST_COMPLEX -#ifdef USE_FLOAT -template struct bench_2 >, 3>; -template struct bench_2 >, 10>; -template struct bench_2 >, 30>; -template struct bench_2 >, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_2 >, 3>; -template struct bench_2 >, 10>; -template struct bench_2 >, 30>; -template struct bench_2 >, 100>; -#endif -#endif diff --git a/benchmarks/bench4/bench43.cpp b/benchmarks/bench4/bench43.cpp deleted file mode 100644 index c39655a43..000000000 --- a/benchmarks/bench4/bench43.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2000-2002 -// Joerg Walter, Mathias Koch -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// GeNeSys mbH & Co. KG in producing this work. -// - -#include -#include -#include "../bench1/bench13.cpp" - - -#ifdef USE_FLOAT -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_3, 3>; -template struct bench_3, 10>; -template struct bench_3, 30>; -template struct bench_3, 100>; -#endif - -#ifdef USE_BOOST_COMPLEX -#ifdef USE_FLOAT -template struct bench_3 >, 3>; -template struct bench_3 >, 10>; -template struct bench_3 >, 30>; -template struct bench_3 >, 100>; -#endif - -#ifdef USE_DOUBLE -template struct bench_3 >, 3>; -template struct bench_3 >, 10>; -template struct bench_3 >, 30>; -template struct bench_3 >, 100>; -#endif -#endif diff --git a/benchmarks/bench5/Jamfile.v2 b/benchmarks/bench5/Jamfile.v2 deleted file mode 100644 index d180f5c63..000000000 --- a/benchmarks/bench5/Jamfile.v2 +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2004-2010 Michael Stevens, David Bellot -# Use, modification and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# bench5 measures performance of the assignment operator - -exe bench5 - : assignment_bench.cpp - : BOOST_UBLAS_USE_INTERVAL - ; diff --git a/benchmarks/bench5/assignment_bench.cpp b/benchmarks/bench5/assignment_bench.cpp deleted file mode 100644 index 532f37911..000000000 --- a/benchmarks/bench5/assignment_bench.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// -// Copyright (c) 2010 Athanasios Iliopoulos -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include -#include -#include - -using namespace boost::numeric::ublas; - -int main() { - - boost::timer timer; - - unsigned int iterations = 1000000000; - double elapsed_exp, elapsed_assigner; - - std::cout << "Ublas vector Benchmarks------------------------ " << "\n"; - - { - std::cout << "Size 2 vector: " << "\n"; - vector a(2); - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) { - a(0)=0; a(1)=1; - } - elapsed_exp = timer.elapsed(); - std::cout << "Explicit element assign time: " << elapsed_exp << " secs" << "\n"; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= 0, 1; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time: " << elapsed_assigner << " secs" << "\n"; - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - } - - { - std::cout << "Size 3 vector: " << "\n"; - vector a(3); - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) { - a(0)=0; a(1)=1; a(2)=2; - } - elapsed_exp = timer.elapsed(); - std::cout << "Explicit element assign time: " << elapsed_exp << " secs" << "\n"; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= 0, 1, 2; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time: " << elapsed_assigner << " secs" << "\n"; - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - } - - iterations = 100000000; - - { - std::cout << "Size 8 vector: " << "\n"; - vector a(8); - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) { - a(0)=0; a(1)=1; a(2)=2; a(3)=3; a(4)=4; a(5)=5; a(6)=6; a(7)=7; - } - elapsed_exp = timer.elapsed(); - std::cout << "Explicit element assign time: " << elapsed_exp << " secs" << "\n"; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= 0, 1, 2, 3, 4, 5, 6, 7; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time: " << elapsed_assigner << " secs" << "\n"; - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - } - - - std::cout << "Ublas matrix Benchmarks------------------------ " << "\n"; - - iterations = 200000000; - { - std::cout << "Size 3x3 matrix: " << "\n"; - matrix a(3,3); - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) { - a(0,0)=0; a(0,1)=1; a(0,2)=2; - a(1,0)=3; a(1,1)=4; a(1,2)=5; - a(2,0)=6; a(2,1)=7; a(2,2)=8; - } - elapsed_exp = timer.elapsed(); - std::cout << "Explicit element assign time: " << elapsed_exp << " secs" << "\n"; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= 0, 1, 2, 3, 4, 5, 6, 7, 8; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time: " << elapsed_assigner << " secs" << "\n"; - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - } - - std::cout << "Size 2x2 matrix: " << "\n"; - iterations = 500000000; - { - matrix a(2,2); - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) { - a(0,0)=0; a(0,1)=1; - a(1,0)=3; a(1,1)=4; - } - elapsed_exp = timer.elapsed(); - std::cout << "Explicit element assign time: " << elapsed_exp << " secs" << "\n"; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= 0, 1, 3, 4; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time: " << elapsed_assigner << " secs" << "\n"; - - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - - timer.restart(); - for(unsigned int i=0; i!=iterations; i++) - a <<= traverse_policy::by_row_no_wrap(), 0, 1, next_row(), 3, 4; - elapsed_assigner = timer.elapsed(); - std::cout << "Assigner time no_wrap: " << elapsed_assigner << " secs" << "\n"; - std::cout << "Difference: " << (elapsed_assigner/elapsed_exp-1)*100 << "%" << std::endl; - } - - return 0; -} - From 7cc5d385d2f12a2d15a78b85679edf9ede8d7aa3 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 6 May 2018 20:54:33 -0400 Subject: [PATCH 64/73] First OpenCL support infrastructure. --- .appveyor.yml | 32 +++++++++- .ci/install-clblas.sh | 10 +++ .ci/install-ocl-ubuntu.sh | 67 ++++++++++++++++++++ .travis.yml | 45 +++++++++++--- clblas.jam | 114 +++++++++++++++++++++++++++++++++++ opencl.jam | 111 ++++++++++++++++++++++++++++++++++ test/{Jamfile.v2 => Jamfile} | 2 + test/opencl/Jamfile | 22 +++++++ test/opencl/test.cpp | 5 ++ 9 files changed, 396 insertions(+), 12 deletions(-) create mode 100755 .ci/install-clblas.sh create mode 100755 .ci/install-ocl-ubuntu.sh create mode 100644 clblas.jam create mode 100644 opencl.jam rename test/{Jamfile.v2 => Jamfile} (99%) create mode 100644 test/opencl/Jamfile create mode 100644 test/opencl/test.cpp diff --git a/.appveyor.yml b/.appveyor.yml index 332227375..1b5e98872 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,6 +10,7 @@ branches: only: - master - develop + - opencl - /feature\/.*/ environment: @@ -20,7 +21,21 @@ environment: TOOLSET: msvc-14.1 CXXSTD: 17 +cache: + - c:\tools\vcpkg\installed\ + install: + # Install OpenCL runtime (driver) for Intel / Xeon package + - appveyor DownloadFile "http://registrationcenter-download.intel.com/akdlm/irc_nas/9022/opencl_runtime_16.1.1_x64_setup.msi" + - start /wait msiexec /i opencl_runtime_16.1.1_x64_setup.msi /qn /l*v msiexec2.log + # FIXME: To be removed https://help.appveyor.com/discussions/problems/13000-cmake_toolchain_filevcpkgcmake-conflicts-with-cmake-native-findboostcmake" + - ps: 'Write-Host "Installing latest vcpkg.cmake module" -ForegroundColor Magenta' + - appveyor DownloadFile https://raw.githubusercontent.com/Microsoft/vcpkg/master/scripts/buildsystems/vcpkg.cmake -FileName "c:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake" + - set "TRIPLET=x64-windows" + - vcpkg --triplet %TRIPLET% install opencl clblas + - set PATH=C:\Tools\vcpkg\installed\%TRIPLET%\bin;%PATH% + - set VCPKG_I=C:\Tools\vcpkg\installed\%TRIPLET%\include + - set VCPKG_L=C:\Tools\vcpkg\installed\%TRIPLET%\lib - set BOOST_BRANCH=develop - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master - cd .. @@ -31,14 +46,27 @@ install: - git submodule update --init tools/boostdep - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\numeric\ublas - python tools/boostdep/depinst/depinst.py -I benchmarks numeric/ublas + - xcopy %APPVEYOR_BUILD_FOLDER%\opencl.jam %USERPROFILE% + - xcopy %APPVEYOR_BUILD_FOLDER%\clblas.jam %USERPROFILE% + - ps: | + # Creating %USERPROFILE%/user-config.jam file + @' + import os regex toolset ; + local toolset = [ regex.split [ os.environ TOOLSET ] "-" ] ; + local vcpkg_i = [ os.environ VCPKG_I ] ; + local vcpkg_l = [ os.environ VCPKG_L ] ; + using $(toolset[1]) : $(toolset[2-]:J="-") : ; + using opencl : : $(vcpkg_i) $(vcpkg_l) ; + using clblas : : $(vcpkg_i) $(vcpkg_l) ; + '@ | sc "$env:USERPROFILE/user-config.jam" - cmd /c bootstrap - b2 -d0 headers build: off test_script: - - PATH=%ADDPATH%%PATH% + #- PATH=%ADDPATH%%PATH% - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% - - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - set ADDRMD=address-model=64 - b2 -j3 libs/numeric/ublas/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% - b2 -j3 libs/numeric/ublas/benchmarks toolset=%TOOLSET% %CXXSTD% %ADDRMD% diff --git a/.ci/install-clblas.sh b/.ci/install-clblas.sh new file mode 100755 index 000000000..f8d9a6cc7 --- /dev/null +++ b/.ci/install-clblas.sh @@ -0,0 +1,10 @@ +#! /bin/bash -e + +wget https://github.com/clMathLibraries/clBLAS/releases/download/v2.12/clBLAS-2.12.0-Linux-x64.tar.gz +tar xvf clBLAS-2.12.0-Linux-x64.tar.gz +if [ ${CLBLAS_PREFIX} ]; then + mkdir -p ${CLBLAS_PREFIX}/lib/ + cp -r clBLAS-2.12.0-Linux-x64/include ${CLBLAS_PREFIX}/include + cp -r clBLAS-2.12.0-Linux-x64/lib64/* ${CLBLAS_PREFIX}/lib/ + cp -r clBLAS-2.12.0-Linux-x64/bin ${CLBLAS_PREFIX}/bin +fi diff --git a/.ci/install-ocl-ubuntu.sh b/.ci/install-ocl-ubuntu.sh new file mode 100755 index 000000000..ef503a6a8 --- /dev/null +++ b/.ci/install-ocl-ubuntu.sh @@ -0,0 +1,67 @@ +#!/bin/bash +#this might work on other DEB based distros, YMMV +#prereqs: wget, rpm2cpio, cpio, clinfo (for testing), and no other conflicting OpenCL drivers +#Get this file +#https://software.intel.com/en-us/articles/opencl-drivers#philinux +#http://registrationcenter.intel.com/irc_nas/4181/opencl_runtime_14.2_x64_4.5.0.8.tgz +#or this one http://registrationcenter.intel.com/irc_nas/5193/opencl_runtime_15.1_x64_5.0.0.57.tgz +#wget http://registrationcenter.intel.com/irc_nas/4181/opencl_runtime_14.2_x64_4.5.0.8.tgz +wget http://registrationcenter.intel.com/irc_nas/5193/opencl_runtime_15.1_x64_5.0.0.57.tgz + +#unpack the tarball +tar xvf opencl_runtime_15.1_x64_5.0.0.57.tgz + +#unpack the rpms +#according to http://mhr3.blogspot.com/2013/06/opencl-on-ubuntu-1304.html, we don't need all of them unpacked +#basically, just the ICD itself +rpm2cpio opencl_runtime_15.1_x64_5.0.0.57/rpm/opencl-1.2-intel-cpu-5.0.0.57-1.x86_64.rpm | cpio -idmv + +#stub out the directory structure for the deb package as a staging area +#some of these steps are from here http://mhr3.blogspot.com/2013/06/opencl-on-ubuntu-1304.html +mkdir opencl-driver-intel-cpu +cd opencl-driver-intel-cpu +mkdir DEBIAN +mkdir -p etc/OpenCL/vendors +mkdir -p usr/lib/x86_64-linux-gnu/OpenCL/vendors/intel +mkdir -p usr/share/doc/opencl-driver-intel-cpu +cd .. + +#put the right description of the package in the right place +#from the blog post with my modifications +#version number is from the filename +cat <<'EOF' >> opencl-driver-intel-cpu/DEBIAN/control +Package: opencl-driver-intel-cpu +Version: 5.0.0.57 +Section: libs +Priority: optional +Architecture: amd64 +Depends: ocl-icd-libopencl1 (>= 2.0), libnuma1 +Maintainer: Your Name +Description: Intel OpenCL CPU implementation + This package provides Intel OpenCL implementation which can utilize Intel Core processors. +EOF + +#copy over the documentation into the deb staging area +cp opt/intel/opencl-1.2-5.0.0.57/doc/* opencl-driver-intel-cpu/usr/share/doc/opencl-driver-intel-cpu/ + +#the icd registry could be copied from opt/intel/opencl-1.2-5.0.0.57/etc/intel64.icd +#but it's wrong anyway and we'd have to change it, handle this later + +#now put the libs where they go in the staging area +cp opt/intel/opencl-1.2-5.0.0.57/lib64/* opencl-driver-intel-cpu/usr/lib/x86_64-linux-gnu/OpenCL/vendors/intel/ + +#now deal with that icd registry +cat <<'EOF' >> opencl-driver-intel-cpu/etc/OpenCL/vendors/intel64.icd +/usr/lib/x86_64-linux-gnu/OpenCL/vendors/intel/libintelocl.so +EOF + +#finally build the deb package +dpkg-deb --build opencl-driver-intel-cpu + +#and install it +sudo dpkg --install opencl-driver-intel-cpu.deb +sudo apt-get install -f +sudo ldconfig +clinfo #this verifies it installed correctly +#cleanup +rm -rf opencl-driver-intel-cpu opencl_runtime_15.1_x64_5.0.0.57* diff --git a/.travis.yml b/.travis.yml index dea6389b4..933a22cb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) language: cpp -sudo: false +sudo: required branches: only: @@ -11,21 +11,39 @@ branches: - develop - doc - ci + - opencl + +# env: specifies additional global variables to define per row in build matrix +env: + global: + - CLBLAS_PREFIX=${TRAVIS_BUILD_DIR}/CLBLAS/ + - PATH=${CLBLAS_PREFIX}/bin:$PATH + - LD_LIBRARY_PATH=${CLBLAS_PREFIX}/lib:$LD_LIBRARY_PATH matrix: include: - os: linux env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11 - addons: - apt: - packages: - - g++-7 - sources: - - ubuntu-toolchain-r-test - - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + - libopenblas-base + - rpm2cpio + - cpio + - clinfo + - opencl-headers + - ocl-icd-opencl-dev +before_install: + - if [ ${TRAVIS_OS_NAME} == "linux" ]; then .ci/install-ocl-ubuntu.sh; fi + - .ci/install-clblas.sh + - cmake --version; + - ${CC} --version; + - ${CXX} --version; install: - cd .. @@ -40,9 +58,16 @@ install: - ./bootstrap.sh - ./b2 headers +# Use before_script: to run configure steps +before_script: + +# use script: to execute build steps script: - |- - echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" > ~/user-config.jam + echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" >> ~/user-config.jam; + echo "using clblas : : ${CLBLAS_PREFIX}/include ${CLBLAS_PREFIX}/lib ;" >> ~/user-config.jam; + cp $TRAVIS_BUILD_DIR/opencl.jam ~/ + cp $TRAVIS_BUILD_DIR/clblas.jam ~/ - ./b2 libs/numeric/ublas/test toolset=$TOOLSET - ./b2 libs/numeric/ublas/benchmarks toolset=$TOOLSET diff --git a/clblas.jam b/clblas.jam new file mode 100644 index 000000000..d4fa247e3 --- /dev/null +++ b/clblas.jam @@ -0,0 +1,114 @@ +# Copyright (c) 2018 Stefan Seefeld +# +# Use, modification and distribution is subject to the Boost Software +# License Version 1.0. (See accompanying file LICENSE_1_0.txt or +# http://www.boost.org/LICENSE_1_0.txt) + +# Supports the clblas library +# +# After 'using clblas', the following targets are available: +# +# /clblas//clblas -- The clblas library + +import project ; +import ac ; +import errors ; +import feature ; +import "class" : new ; +import targets ; +import modules ; +import property-set ; +import toolset : using ; + +using opencl ; + +header = clBLAS.h ; +names = clBLAS ; + +library-id = 0 ; + +if --debug-configuration in [ modules.peek : ARGV ] +{ + .debug = true ; +} + +# Initializes the clblas library. +# +# Options for configuring clblas:: +# +# +# The directory containing the clblas library. +# +# Overrides the default library name. +# +# The directory containing the clblas headers. +# +# Examples:: +# +# # Find clblas in the default system location +# using clblas ; +# # Find clblas in /usr/local +# using clblas : 1.2.7 +# : /usr/local/include /usr/local/lib ; +# +rule init ( version ? : # The clblas version (currently ignored) + options * : # A list of the options to use + requirements * ) # The requirements for the clblas target +{ + local caller = [ project.current ] ; + + if ! $(.initialized) + { + .initialized = true ; + + project.initialize $(__name__) ; + .project = [ project.current ] ; + project clblas ; + } + + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + + if ! $(library-path) && ! $(include-path) && ! $(library-name) + { + is-default = true ; + } + + condition = [ property-set.create $(requirements) ] ; + condition = [ property-set.create [ $(condition).base ] ] ; + + if $(.configured.$(condition)) + { + if $(is-default) + { + if $(.debug) + { + ECHO "notice: [clblas] clblas is already configured" ; + } + } + else + { + errors.user-error "clblas is already configured" ; + } + return ; + } + else + { + if $(.debug) + { + ECHO "notice: [clblas] Using pre-installed library" ; + if $(condition) + { + ECHO "notice: [clblas] Condition" [ $(condition).raw ] ; + } + } + + local mt = [ new ac-library clblas : $(.project) : $(condition) : + $(include-path) : $(library-path) : $(library-name) ] ; + $(mt).set-header $(header) ; + $(mt).set-default-names $(names) ; + targets.main-target-alternative $(mt) ; + } + .configured.$(condition) = true ; +} diff --git a/opencl.jam b/opencl.jam new file mode 100644 index 000000000..f16193a92 --- /dev/null +++ b/opencl.jam @@ -0,0 +1,111 @@ +# Copyright (c) 2018 Stefan Seefeld +# +# Use, modification and distribution is subject to the Boost Software +# License Version 1.0. (See accompanying file LICENSE_1_0.txt or +# http://www.boost.org/LICENSE_1_0.txt) + +# Supports the opencl library +# +# After 'using opencl', the following targets are available: +# +# /opencl//opencl -- The OpenCL library + +import project ; +import ac ; +import errors ; +import feature ; +import "class" : new ; +import targets ; +import modules ; +import property-set ; + +header = CL/cl.h ; +names = OpenCL ; + +library-id = 0 ; + +if --debug-configuration in [ modules.peek : ARGV ] +{ + .debug = true ; +} + +# Initializes the opencl library. +# +# Options for configuring opencl:: +# +# +# The directory containing the OpenCL library. +# +# Overrides the default library name. +# +# The directory containing the OpenCL headers. +# +# Examples:: +# +# # Find OpenCL in the default system location +# using opencl ; +# # Find opencl in /usr/local +# using opencl : 1.2.7 +# : /usr/local/include /usr/local/lib ; +# +rule init ( version ? : # The opencl version (currently ignored) + options * : # A list of the options to use + requirements * ) # The requirements for the opencl target +{ + local caller = [ project.current ] ; + + if ! $(.initialized) + { + .initialized = true ; + + project.initialize $(__name__) ; + .project = [ project.current ] ; + project opencl ; + } + + local library-path = [ feature.get-values : $(options) ] ; + local include-path = [ feature.get-values : $(options) ] ; + local library-name = [ feature.get-values : $(options) ] ; + + if ! $(library-path) && ! $(include-path) && ! $(library-name) + { + is-default = true ; + } + + condition = [ property-set.create $(requirements) ] ; + condition = [ property-set.create [ $(condition).base ] ] ; + + if $(.configured.$(condition)) + { + if $(is-default) + { + if $(.debug) + { + ECHO "notice: [opencl] opencl is already configured" ; + } + } + else + { + errors.user-error "opencl is already configured" ; + } + return ; + } + else + { + if $(.debug) + { + ECHO "notice: [opencl] Using pre-installed library" ; + if $(condition) + { + ECHO "notice: [opencl] Condition" [ $(condition).raw ] ; + } + } + + local mt = [ new ac-library opencl : $(.project) : $(condition) : + $(include-path) : $(library-path) : $(library-name) ] ; + $(mt).set-header $(header) ; + $(mt).set-default-names $(names) ; + targets.main-target-alternative $(mt) ; + } + .configured.$(condition) = true ; +} diff --git a/test/Jamfile.v2 b/test/Jamfile similarity index 99% rename from test/Jamfile.v2 rename to test/Jamfile index f990b76b9..c87596a82 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile @@ -250,3 +250,5 @@ test-suite numeric/uBLAS [ run test_matrix_vector.cpp ] ; + +build-project opencl ; diff --git a/test/opencl/Jamfile b/test/opencl/Jamfile new file mode 100644 index 000000000..7cc7fccf4 --- /dev/null +++ b/test/opencl/Jamfile @@ -0,0 +1,22 @@ +# Boost.uBLAS +# +# Copyright (c) 2018 Stefan Seefeld +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or +# copy at http://www.boost.org/LICENSE_1_0.txt) + +import ac ; + +using opencl ; +using clblas ; + +project boost/ublas/test/opencl + : requirements + gcc:-Wno-ignored-attributes + [ ac.check-library /clblas//clblas : /clblas//clblas /opencl//opencl : no ] + ; + +test-suite ocl + : [ run test.cpp ] + ; diff --git a/test/opencl/test.cpp b/test/opencl/test.cpp new file mode 100644 index 000000000..c7fdda328 --- /dev/null +++ b/test/opencl/test.cpp @@ -0,0 +1,5 @@ +#include + +int main() +{ +} From 9ae62f58d87483ef47bda2d66d15f22efcc98bc2 Mon Sep 17 00:00:00 2001 From: Fady Essam Date: Sun, 28 Oct 2018 20:50:31 +0200 Subject: [PATCH 65/73] Add OpenCL API. --- include/boost/numeric/ublas/opencl.hpp | 17 + .../numeric/ublas/opencl/elementwise.hpp | 508 ++++++++++++++++++ .../boost/numeric/ublas/opencl/library.hpp | 38 ++ include/boost/numeric/ublas/opencl/matrix.hpp | 123 +++++ include/boost/numeric/ublas/opencl/misc.hpp | 182 +++++++ .../boost/numeric/ublas/opencl/operations.hpp | 18 + include/boost/numeric/ublas/opencl/prod.hpp | 364 +++++++++++++ .../boost/numeric/ublas/opencl/transpose.hpp | 142 +++++ include/boost/numeric/ublas/opencl/vector.hpp | 90 ++++ test/Jamfile | 1 + test/opencl/Jamfile | 9 +- test/opencl/elementwise_operations_test.cpp | 44 ++ test/opencl/elementwise_operations_test.hpp | 114 ++++ ...entwise_operations_with_constants_test.cpp | 48 ++ ...entwise_operations_with_constants_test.hpp | 86 +++ test/opencl/inner_prod_test.cpp | 23 + test/opencl/inner_prod_test.hpp | 64 +++ test/opencl/norm2_test.cpp | 32 ++ test/opencl/norm2_test.hpp | 59 ++ test/opencl/norm_test.cpp | 22 + test/opencl/norm_test.hpp | 59 ++ test/opencl/outer_prod_test.cpp | 31 ++ test/opencl/outer_prod_test.hpp | 65 +++ test/opencl/prod_test.cpp | 48 ++ test/opencl/prod_test.hpp | 88 +++ test/opencl/test.cpp | 5 - test/opencl/test_opencl.hpp | 84 +++ test/opencl/transposition_test.cpp | 33 ++ test/opencl/transposition_test.hpp | 61 +++ 29 files changed, 2452 insertions(+), 6 deletions(-) create mode 100644 include/boost/numeric/ublas/opencl.hpp create mode 100644 include/boost/numeric/ublas/opencl/elementwise.hpp create mode 100644 include/boost/numeric/ublas/opencl/library.hpp create mode 100644 include/boost/numeric/ublas/opencl/matrix.hpp create mode 100644 include/boost/numeric/ublas/opencl/misc.hpp create mode 100644 include/boost/numeric/ublas/opencl/operations.hpp create mode 100644 include/boost/numeric/ublas/opencl/prod.hpp create mode 100644 include/boost/numeric/ublas/opencl/transpose.hpp create mode 100644 include/boost/numeric/ublas/opencl/vector.hpp create mode 100644 test/opencl/elementwise_operations_test.cpp create mode 100644 test/opencl/elementwise_operations_test.hpp create mode 100644 test/opencl/elementwise_operations_with_constants_test.cpp create mode 100644 test/opencl/elementwise_operations_with_constants_test.hpp create mode 100644 test/opencl/inner_prod_test.cpp create mode 100644 test/opencl/inner_prod_test.hpp create mode 100644 test/opencl/norm2_test.cpp create mode 100644 test/opencl/norm2_test.hpp create mode 100644 test/opencl/norm_test.cpp create mode 100644 test/opencl/norm_test.hpp create mode 100644 test/opencl/outer_prod_test.cpp create mode 100644 test/opencl/outer_prod_test.hpp create mode 100644 test/opencl/prod_test.cpp create mode 100644 test/opencl/prod_test.hpp delete mode 100644 test/opencl/test.cpp create mode 100644 test/opencl/test_opencl.hpp create mode 100644 test/opencl/transposition_test.cpp create mode 100644 test/opencl/transposition_test.hpp diff --git a/include/boost/numeric/ublas/opencl.hpp b/include/boost/numeric/ublas/opencl.hpp new file mode 100644 index 000000000..bf8101254 --- /dev/null +++ b/include/boost/numeric/ublas/opencl.hpp @@ -0,0 +1,17 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_hpp_ +#define boost_numeric_ublas_opencl_hpp_ + +#include +#include +#include +#include + +#endif diff --git a/include/boost/numeric/ublas/opencl/elementwise.hpp b/include/boost/numeric/ublas/opencl/elementwise.hpp new file mode 100644 index 000000000..72da6a0de --- /dev/null +++ b/include/boost/numeric/ublas/opencl/elementwise.hpp @@ -0,0 +1,508 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_elementwise_hpp_ +#define boost_numeric_ublas_opencl_elementwise_hpp_ + +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +namespace compute = boost::compute; +namespace lambda = boost::compute::lambda; + +template +void element_wise(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + O op, compute::command_queue& queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + assert(a.size1() == b.size1() && a.size2() == b.size2()); + + compute::transform(a.begin(), + a.end(), + b.begin(), + result.begin(), + op, + queue); + queue.finish(); +} + +template +void element_wise(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + O op, + compute::command_queue &queue) +{ + ublas::matrix adev(a, queue); + ublas::matrix bdev(b, queue); + ublas::matrix rdev(a.size1(), b.size2(), queue.get_context()); + element_wise(adev, bdev, rdev, op, queue); + rdev.to_host(result, queue); +} + +template +ublas::matrix element_wise(ublas::matrix const &a, + ublas::matrix const &b, + O op, + compute::command_queue &queue) +{ + ublas::matrix result(a.size1(), b.size2()); + element_wise(a, b, result, op, queue); + return result; +} + +template +void element_wise(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + O op, + compute::command_queue& queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + assert(a.size() == b.size()); + compute::transform(a.begin(), + a.end(), + b.begin(), + result.begin(), + op, + queue); + queue.finish(); +} + +template +void element_wise(ublas::vector const &a, + ublas::vector const &b, + ublas::vector& result, + O op, + compute::command_queue &queue) +{ + ublas::vector adev(a, queue); + ublas::vector bdev(b, queue); + ublas::vector rdev(a.size(), queue.get_context()); + element_wise(adev, bdev, rdev, op, queue); + rdev.to_host(result, queue); +} + +template +ublas::vector element_wise(ublas::vector const &a, + ublas::vector const &b, + O op, + compute::command_queue &queue) +{ + ublas::vector result(a.size()); + element_wise(a, b, result, op, queue); + return result; +} + +template +void element_add(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::plus(), queue); +} + +template +void element_add(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::plus(), queue); +} + +template +ublas::matrix element_add(ublas::matrix const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::plus(), queue); +} + +template +void element_add(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::plus(), queue); +} + +template +void element_add(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::plus(), queue); +} + +template +ublas::vector element_add(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::plus(), queue); +} + +template +void element_add(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + assert(m.device() == result.device() && m.device() == queue.get_device()); + assert(m.size1() == result.size1() && m.size2() == result.size2()); + compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 + value, queue); + queue.finish(); +} + +template +void element_add(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + ublas::matrix mdev(m, queue); + ublas::matrix rdev(result.size1(), result.size2(), queue.get_context()); + element_add(mdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::matrix element_add(ublas::matrix const &m, T value, + compute::command_queue& queue) +{ + ublas::matrix result(m.size1(), m.size2()); + element_add(m, value, result, queue); + return result; +} + +template +void element_add(ublas::vector const &v, T value, + ublas::vector &result, + compute::command_queue& queue) +{ + assert(v.device() == result.device() && v.device() == queue.get_device()); + assert(v.size() == result.size()); + compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 + value, queue); + queue.finish(); +} + +template +void element_add(ublas::vector const &v, T value, + ublas::vector &result, + compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + ublas::vector rdev(v.size(), queue.get_context()); + element_add(vdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::vector element_add(ublas::vector const &v, T value, + compute::command_queue& queue) +{ + ublas::vector result(v.size()); + element_add(v, value, result, queue); + return result; +} + +template +void element_sub(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue& queue) +{ + element_wise(a, b, compute::minus(), result, queue); +} + +template +void element_sub(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::minus(), queue); +} + +template +ublas::matrix element_sub(ublas::matrix const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::minus(), queue); +} + +template +void element_sub(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::minus(), queue); +} + +template +void element_sub(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::minus(), queue); +} + +template +ublas::vector element_sub(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::minus(), queue); +} + +template +void element_sub(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + assert(m.device() == result.device() && m.device() == queue.get_device()); + assert(m.size1() == result.size1() && m.size2() == result.size2()); + compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 - value, queue); + queue.finish(); +} + +template +void element_sub(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + ublas::matrix mdev(m, queue); + ublas::matrix rdev(result.size1(), result.size2(), queue.get_context()); + element_sub(mdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::matrix element_sub(ublas::matrix const &m, T value, + compute::command_queue& queue) +{ + ublas::matrix result(m.size1(), m.size2()); + element_sub(m, value, result, queue); + return result; +} + +template +void element_sub(ublas::vector const &v, T value, + ublas::vector &result, + compute::command_queue& queue) +{ + assert(v.device() == result.device() && v.device() == queue.get_device()); + assert(v.size() == result.size()); + compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 - value, queue); + queue.finish(); +} + +template +void element_sub(ublas::vector const &v, T value, + ublas::vector &result, + compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + ublas::vector rdev(v.size(), queue.get_context()); + element_sub(vdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::vector element_sub(ublas::vector const &v, T value, + compute::command_queue& queue) +{ + ublas::vector result(v.size()); + element_sub(v, value, result, queue); + return result; +} + +template +void element_prod(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::multiplies(), queue); +} + +template +void element_prod(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::multiplies(), queue); +} + +template +ublas::matrix element_prod(ublas::matrix const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::multiplies(), queue); +} + +template +void element_prod(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::multiplies(), queue); +} + +template +void element_prod(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::multiplies(), queue); +} + +template +ublas::vector element_prod(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::multiplies(), queue); +} + +template +void element_scale(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + assert(m.device() == result.device() && m.device() == queue.get_device()); + assert(m.size1() == result.size1() && m.size2() == result.size2()); + compute::transform(m.begin(), m.end(), result.begin(), lambda::_1 * value, queue); + queue.finish(); +} + +template +void element_scale(ublas::matrix const &m, T value, + ublas::matrix &result, + compute::command_queue& queue) +{ + ublas::matrix mdev(m, queue); + ublas::matrix rdev(result.size1(), result.size2(), queue.get_context()); + element_scale(mdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::matrix element_scale(ublas::matrix const &m, T value, + compute::command_queue& queue) +{ + ublas::matrix result(m.size1(), m.size2()); + element_scale(m, value, result, queue); + return result; +} + +template +void element_scale(ublas::vector const &v, T value, + ublas::vector &result, + compute::command_queue& queue) +{ + assert(v.device() == result.device() && v.device() == queue.get_device()); + assert(v.size() == result.size()); + compute::transform(v.begin(), v.end(), result.begin(), lambda::_1 * value, queue); + queue.finish(); +} + +template +void element_scale(ublas::vector const &v, T value, + ublas::vector & result, + compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + ublas::vector rdev(v.size(), queue.get_context()); + element_scale(vdev, value, rdev, queue); + rdev.to_host(result, queue); +} + +template +ublas::vector element_scale(ublas::vector const &v, T value, + compute::command_queue& queue) +{ + ublas::vector result(v.size()); + element_scale(v, value, result, queue); + return result; +} + +template +void element_div(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::divides(), queue); +} + +template +void element_div(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::divides(), queue); +} + +template +ublas::matrix element_div(ublas::matrix const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::divides(), queue); +} + +template +void element_div(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue& queue) +{ + element_wise(a, b, result, compute::divides(), queue); +} + +template +void element_div(ublas::vector const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + element_wise(a, b, result, compute::divides(), queue); +} + +template +ublas::vector element_div(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + return element_wise(a, b, compute::divides(), queue); +} + +}}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/library.hpp b/include/boost/numeric/ublas/opencl/library.hpp new file mode 100644 index 000000000..badee4d2e --- /dev/null +++ b/include/boost/numeric/ublas/opencl/library.hpp @@ -0,0 +1,38 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_library_hpp_ +#define boost_numeric_ublas_opencl_library_hpp_ + +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +class library +{ +public: + library() { clblasSetup();} + ~library() { clblasTeardown();} +}; + +template +struct is_numeric +{ + static bool const value = + std::is_same::value | + std::is_same::value | + std::is_same>::value | + std::is_same>::value; +}; + +}}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/matrix.hpp b/include/boost/numeric/ublas/opencl/matrix.hpp new file mode 100644 index 000000000..d8b400d54 --- /dev/null +++ b/include/boost/numeric/ublas/opencl/matrix.hpp @@ -0,0 +1,123 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_matrix_hpp_ +#define boost_numeric_ublas_opencl_matrix_hpp_ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +class storage; + +namespace compute = boost::compute; + +} // namespace opencl + +template +class matrix : public matrix_container > +{ + typedef typename boost::compute::buffer_allocator::size_type size_type; + typedef L layout_type; + typedef matrix self_type; +public: + matrix() + : matrix_container(), + size1_(0), size2_(0), data_() , device_() + {} + + matrix(size_type size1, size_type size2, compute::context c) + : matrix_container(), + size1_(size1), size2_(size2), device_(c.get_device()) + { + compute::buffer_allocator allocator(c); + data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer(); + } + + matrix(size_type size1, size_type size2, T const &value, compute::command_queue &q) + : matrix_container(), + size1_(size1), size2_(size2), device_(q.get_device()) + { + compute::buffer_allocator allocator(q.get_context()); + data_ = allocator.allocate(layout_type::storage_size(size1, size2)).get_buffer(); + compute::fill(this->begin(), this->end(), value, q); + q.finish(); + } + + template + matrix(matrix const &m, compute::command_queue &queue) + : matrix(m.size1(), m.size2(), queue.get_context()) + { + this->from_host(m, queue); + } + + size_type size1() const { return size1_;} + size_type size2() const { return size2_;} + + const compute::buffer_iterator begin() const { return compute::make_buffer_iterator(data_);} + compute::buffer_iterator begin() { return compute::make_buffer_iterator(data_);} + + compute::buffer_iterator end() { return compute::make_buffer_iterator(data_, layout_type::storage_size(size1_, size2_));} + const compute::buffer_iterator end() const { return compute::make_buffer_iterator(data_, layout_type::storage_size(size1_, size2_));} + + const compute::device &device() const { return device_;} + compute::device &device() { return device_;} + + void fill(T value, compute::command_queue &queue) + { + assert(device_ == queue.get_device()); + compute::fill(this->begin(), this->end(), value, queue); + queue.finish(); + } + + /** Copies a matrix to a device + * \param m is a matrix that is not on the device _device and it is copied to it + * \param queue is the command queue that will execute the operation + */ + template + void from_host(ublas::matrix const &m, compute::command_queue &queue) + { + assert(device_ == queue.get_device()); + compute::copy(m.data().begin(), + m.data().end(), + this->begin(), + queue); + queue.finish(); + } + + /** Copies a matrix from a device + * \param m is a matrix that will be reized to (size1_,size2) and the values of (*this) will be copied in it + * \param queue is the command queue that will execute the operation + */ + template + void to_host(ublas::matrix &m, compute::command_queue &queue) const + { + assert(device_ == queue.get_device()); + compute::copy(this->begin(), + this->end(), + m.data().begin(), + queue); + queue.finish(); + } + +private: + size_type size1_; + size_type size2_; + compute::buffer data_; + compute::device device_; +}; + +}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/misc.hpp b/include/boost/numeric/ublas/opencl/misc.hpp new file mode 100644 index 000000000..5ed48f47f --- /dev/null +++ b/include/boost/numeric/ublas/opencl/misc.hpp @@ -0,0 +1,182 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_misc_hpp_ +#define boost_numeric_ublas_opencl_misc_hpp_ + +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +template +typename std::enable_if::value, T>::type +a_sum(ublas::vector const &v, compute::command_queue& queue) +{ + compute::vector scratch_buffer(v.size(), queue.get_context()); + compute::vector result_buffer(1, queue.get_context()); + cl_event event; + if (std::is_same::value) + clblasSasum(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same::value) + clblasDasum(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same>::value) + clblasScasum(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same>::value) + clblasDzasum(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + clWaitForEvents(1, &event); + return result_buffer[0]; +} + +template +typename std::enable_if::value, T>::type +a_sum(ublas::vector const &v, compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + return a_sum(vdev, queue); +} + +template +typename std::enable_if::value | + std::is_same::value, + T>::type +norm_1(ublas::vector const &v, compute::command_queue& queue) +{ + return a_sum(v, queue); +} + +template +typename std::enable_if::value | + std::is_same::value, + T>::type +norm_1(ublas::vector const &v, compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + return norm_1(vdev, queue); +} + +template +typename std::enable_if::value, T>::type +norm_2(ublas::vector const &v, compute::command_queue& queue) +{ + compute::vector scratch_buffer(2*v.size(), queue.get_context()); + compute::vector result_buffer(1, queue.get_context()); + cl_event event; + if (std::is_same::value) + clblasSnrm2(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same::value) + clblasDnrm2(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same>::value) + clblasScnrm2(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + else if (std::is_same>::value) + clblasDznrm2(v.size(), + result_buffer.begin().get_buffer().get(), //result buffer + 0, //offset in result buffer + v.begin().get_buffer().get(), //input buffer + 0, //offset in input buffer + 1, //increment in input buffer + scratch_buffer.begin().get_buffer().get(), + 1, //number of command queues + &(queue.get()), //queue + 0, // number of events waiting list + NULL, //event waiting list + &event); //event + clWaitForEvents(1, &event); + return result_buffer[0]; +} + +template +typename std::enable_if::value, T>::type +norm_2(ublas::vector const &v, compute::command_queue& queue) +{ + ublas::vector vdev(v, queue); + return norm_2(vdev, queue); +} + +}}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/operations.hpp b/include/boost/numeric/ublas/opencl/operations.hpp new file mode 100644 index 000000000..2c9e7348d --- /dev/null +++ b/include/boost/numeric/ublas/opencl/operations.hpp @@ -0,0 +1,18 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_operations_hpp_ +#define boost_numeric_ublas_opencl_operations_hpp_ + +#include +#include +#include +#include + +#endif diff --git a/include/boost/numeric/ublas/opencl/prod.hpp b/include/boost/numeric/ublas/opencl/prod.hpp new file mode 100644 index 000000000..4318eff00 --- /dev/null +++ b/include/boost/numeric/ublas/opencl/prod.hpp @@ -0,0 +1,364 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_prod_hpp_ +#define boost_numeric_ublas_opencl_prod_hpp_ + +#include +#include +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +#define ONE_DOUBLE_COMPLEX {{1.0, 00.0}} +#define ONE_FLOAT_COMPLEX {{1.0f, 00.0f}} + +template +typename std::enable_if::value>::type +prod(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + assert(a.size2() == b.size1()); + + result.fill(0, queue); + + //to hold matrix b with layout 1 if the b has different layout + std::unique_ptr> bl1; + + cl_event event = NULL; + + cl_mem buffer_a = a.begin().get_buffer().get(); + cl_mem buffer_b = b.begin().get_buffer().get(); + cl_mem buffer_result = result.begin().get_buffer().get(); + + if (!(std::is_same::value)) + { + bl1.reset(new ublas::matrix(b.size1(), b.size2(), queue.get_context())); + change_layout(b, *bl1, queue); + buffer_b = bl1->begin().get_buffer().get(); + } + + clblasOrder Order = std::is_same >::value ? clblasRowMajor : clblasColumnMajor; + size_t lda = Order == clblasRowMajor ? a.size2() : a.size1(); + size_t ldb = Order == clblasRowMajor ? b.size2() : a.size2(); + size_t ldc = Order == clblasRowMajor ? b.size2() : a.size1(); + + if (std::is_same::value) + clblasSgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), b.size2(), a.size2(), + 1, buffer_a, 0, lda, + buffer_b, 0, ldb, 1, + buffer_result, 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same::value) + clblasDgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), b.size2(), a.size2(), + 1, buffer_a, 0, lda, + buffer_b, 0, ldb, 1, + buffer_result, 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasCgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), b.size2(), a.size2(), + ONE_FLOAT_COMPLEX, buffer_a, 0, lda, + buffer_b, 0, ldb, ONE_FLOAT_COMPLEX, + buffer_result, 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasZgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), b.size2(), a.size2(), + ONE_DOUBLE_COMPLEX, buffer_a, 0, lda, + buffer_b, 0, ldb, ONE_DOUBLE_COMPLEX, + buffer_result, 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +prod(ublas::matrix const &a, + ublas::matrix const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + ublas::matrix adev(a, queue); + ublas::matrix bdev(b, queue); + ublas::matrix rdev(a.size1(), b.size2(), queue.get_context()); + prod(adev, bdev, rdev, queue); + rdev.to_host(result,queue); +} + +template +typename std::enable_if::value, ublas::matrix>::type +prod(ublas::matrix const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + ublas::matrix result(a.size1(), b.size2()); + prod(a, b, result, queue); + return result; +} + +template +typename std::enable_if::value>::type +prod(ublas::matrix const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + assert(a.size2() == b.size()); + result.fill(0, queue); + + cl_event event = NULL; + clblasOrder Order = std::is_same >::value ? clblasRowMajor : clblasColumnMajor; + int lda = Order == clblasRowMajor ? a.size2() : a.size1(); + int ldb = Order == clblasRowMajor ? 1 : a.size2(); + int ldc = Order == clblasRowMajor ? 1 : a.size1(); + + if (std::is_same::value) + clblasSgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), 1, a.size2(), + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same::value) + clblasDgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), 1, a.size2(), + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasCgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), 1, a.size2(), + ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasZgemm(Order, clblasNoTrans, clblasNoTrans, + a.size1(), 1, a.size2(), + ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +prod(ublas::matrix const &a, + ublas::vector const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + ublas::matrix adev(a, queue); + ublas::vector bdev(b, queue); + ublas::vector rdev(a.size1(), queue.get_context()); + prod(adev, bdev, rdev, queue); + rdev.to_host(result, queue); +} + +template +typename std::enable_if::value, ublas::vector>::type +prod(ublas::matrix const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + ublas::vector result(a.size1()); + prod(a, b, result, queue); + return result; +} + +template +typename std::enable_if::value>::type +prod(ublas::vector const &a, + ublas::matrix const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + assert(a.size() == b.size1()); + result.fill(0, queue); + cl_event event = NULL; + clblasOrder Order = std::is_same >::value ? clblasRowMajor : clblasColumnMajor; + size_t lda = Order == clblasRowMajor ? a.size() : 1; + size_t ldb = Order == clblasRowMajor ? b.size2() : a.size(); + size_t ldc = Order == clblasRowMajor ? b.size2() : 1; + + if (std::is_same::value) + clblasSgemm(Order, clblasNoTrans, clblasNoTrans, + 1, b.size2(), a.size(), + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same::value) + clblasDgemm(Order, clblasNoTrans, clblasNoTrans, + 1, b.size2(), a.size(), + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasCgemm(Order, clblasNoTrans, clblasNoTrans, + 1, b.size2(), a.size(), + ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasZgemm(Order, clblasNoTrans, clblasNoTrans, + 1, b.size2(), a.size(), + ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +prod(ublas::vector const &a, + ublas::matrix const &b, + ublas::vector &result, + compute::command_queue &queue) +{ + ublas::vector adev(a, queue); + ublas::matrix bdev(b, queue); + ublas::vector rdev(b.size2(), queue.get_context()); + prod(adev, bdev, rdev, queue); + rdev.to_host(result, queue); +} + +template +typename std::enable_if::value, ublas::vector>::type +prod(ublas::vector const &a, + ublas::matrix const &b, + compute::command_queue &queue) +{ + ublas::vector result(b.size2()); + prod(a, b, result, queue); + return result; +} + +template +typename std::enable_if::value, T>::type +inner_prod(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + assert(a.device() == b.device() && a.device() == queue.get_device()); + assert(a.size() == b.size()); + return compute::inner_product(a.begin(), a.end(), b.begin(), T(0), queue); +} + +template +typename std::enable_if::value, T>::type +inner_prod(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue& queue) +{ + ublas::vector adev(a, queue); + ublas::vector bdev(b, queue); + return inner_prod(adev, bdev, queue); +} + +template +typename std::enable_if::value>::type +outer_prod(ublas::vector const &a, + ublas::vector const &b, + ublas::matrix &result, + compute::command_queue & queue) +{ + assert(a.device() == b.device() && + a.device() == result.device() && + a.device() == queue.get_device()); + result.fill(0, queue); + cl_event event = NULL; + clblasOrder Order = std::is_same >::value ? clblasRowMajor : clblasColumnMajor; + size_t lda = Order == clblasRowMajor ? 1 : a.size(); + size_t ldb = Order == clblasRowMajor ? b.size() : 1; + size_t ldc = Order == clblasRowMajor ? b.size() : a.size(); + + if (std::is_same::value) + clblasSgemm(Order, clblasNoTrans, clblasNoTrans, + a.size(), b.size(), 1, + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same::value) + clblasDgemm(Order, clblasNoTrans, clblasNoTrans, + a.size(), b.size(), 1, + 1, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, 1, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasCgemm(Order, clblasNoTrans, clblasNoTrans, + a.size(), b.size(), 1, + ONE_FLOAT_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_FLOAT_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + else if (std::is_same>::value) + clblasZgemm(Order, clblasNoTrans, clblasNoTrans, + a.size(), b.size(), 1, + ONE_DOUBLE_COMPLEX, a.begin().get_buffer().get(), 0, lda, + b.begin().get_buffer().get(), 0, ldb, ONE_DOUBLE_COMPLEX, + result.begin().get_buffer().get(), 0, ldc, + 1, &(queue.get()), 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +outer_prod(ublas::vector const &a, + ublas::vector const &b, + ublas::matrix &result, + compute::command_queue &queue) +{ + ublas::vector adev(a, queue); + ublas::vector bdev(b, queue); + ublas::matrix rdev(a.size(), b.size(), queue.get_context()); + outer_prod(adev, bdev, rdev, queue); + rdev.to_host(result, queue); +} + +template , class A> +typename std::enable_if::value, ublas::matrix>::type +outer_prod(ublas::vector const &a, + ublas::vector const &b, + compute::command_queue &queue) +{ + ublas::matrix result(a.size(), b.size()); + outer_prod(a, b, result, queue); + return result; +} + +#undef ONE_DOUBLE_COMPLEX +#undef ONE_FLOAT_COMPLEX + +}}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/transpose.hpp b/include/boost/numeric/ublas/opencl/transpose.hpp new file mode 100644 index 000000000..93508c897 --- /dev/null +++ b/include/boost/numeric/ublas/opencl/transpose.hpp @@ -0,0 +1,142 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_transpose_hpp_ +#define boost_numeric_ublas_opencl_transpose_hpp_ + +#include +#include +#include + +// Kernel for transposition of various data types +#define OPENCL_TRANSPOSITION_KERNEL(DATA_TYPE) \ +"__kernel void transpose(__global " #DATA_TYPE "* in, __global " #DATA_TYPE "* result, unsigned int width, unsigned int height) \n" \ +"{ \n" \ +" unsigned int column_index = get_global_id(0); \n" \ +" unsigned int row_index = get_global_id(1); \n" \ +" if (column_index < width && row_index < height) \n" \ +" { \n" \ +" unsigned int index_in = column_index + width * row_index; \n" \ +" unsigned int index_result = row_index + height * column_index; \n" \ +" result[index_result] = in[index_in]; \n" \ +" } \n" \ +"} \n" + + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +template +typename std::enable_if::value>::type +change_layout(ublas::matrix const &m, + ublas::matrix &result, + compute::command_queue& queue) +{ + assert(m.size1() == result.size1() && m.size2() == result.size2()); + assert(m.device() == result.device() && m.device() == queue.get_device()); + assert(!(std::is_same::value)); + char const *kernel; + if (std::is_same::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(float); + else if (std::is_same::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(double); + else if (std::is_same>::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(float2); + else if (std::is_same>::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(double2); + size_t len = strlen(kernel); + cl_int err; + cl_context c_context = queue.get_context().get(); + cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err); + clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL); + cl_kernel c_kernel = clCreateKernel(program, "transpose", &err); + size_t width = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size2() : m.size1(); + size_t height = std::is_same < L1, ublas::basic_row_major<>>::value ? m.size1() : m.size2(); + size_t global_size[2] = { width , height }; + clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get()); + clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get()); + clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width); + clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height); + cl_command_queue c_queue = queue.get(); + cl_event event = NULL; + clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +change_layout(ublas::matrix const &m, + ublas::matrix &result, + compute::command_queue& queue) +{ + ublas::matrix mdev(m, queue); + ublas::matrix rdev(result.size1(), result.size2(), queue.get_context()); + change_layout(mdev, rdev, queue); + rdev.to_host(result, queue); +} + +template +typename std::enable_if::value>::type +trans(ublas::matrix const &m, + ublas::matrix &result, + compute::command_queue& queue) +{ + assert(m.size1() == result.size2() && m.size2() == result.size1()); + assert(m.device() == result.device() && m.device() == queue.get_device()); + char const *kernel; + if (std::is_same::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(float); + else if (std::is_same::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(double); + else if (std::is_same>::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(float2); + else if (std::is_same>::value) + kernel = OPENCL_TRANSPOSITION_KERNEL(double2); + size_t len = strlen(kernel); + cl_int err; + cl_context c_context = queue.get_context().get(); + cl_program program = clCreateProgramWithSource(c_context, 1, &kernel, &len, &err); + clBuildProgram(program, 1, &queue.get_device().get(), NULL, NULL, NULL); + cl_kernel c_kernel = clCreateKernel(program, "transpose", &err); + size_t width = std::is_same >::value ? m.size2() : m.size1(); + size_t height = std::is_same >::value ? m.size1() : m.size2(); + size_t global_size[2] = { width , height }; + clSetKernelArg(c_kernel, 0, sizeof(T*), &m.begin().get_buffer().get()); + clSetKernelArg(c_kernel, 1, sizeof(T*), &result.begin().get_buffer().get()); + clSetKernelArg(c_kernel, 2, sizeof(unsigned int), &width); + clSetKernelArg(c_kernel, 3, sizeof(unsigned int), &height); + cl_command_queue c_queue = queue.get(); + cl_event event = NULL; + clEnqueueNDRangeKernel(c_queue, c_kernel, 2, NULL, global_size, NULL, 0, NULL, &event); + clWaitForEvents(1, &event); +} + +template +typename std::enable_if::value>::type +trans(ublas::matrix const &m, + ublas::matrix &result, + compute::command_queue& queue) +{ + ublas::matrix mdev(m, queue); + ublas::matrix rdev(result.size1(), result.size2(), queue.get_context()); + trans(mdev, rdev, queue); + rdev.to_host(result, queue); +} + +template +typename std::enable_if::value, ublas::matrix>::type +trans(ublas::matrix& m, compute::command_queue& queue) +{ + ublas::matrix result(m.size2(), m.size1()); + trans(m, result, queue); + return result; +} + +}}}} + +#endif diff --git a/include/boost/numeric/ublas/opencl/vector.hpp b/include/boost/numeric/ublas/opencl/vector.hpp new file mode 100644 index 000000000..1defa8046 --- /dev/null +++ b/include/boost/numeric/ublas/opencl/vector.hpp @@ -0,0 +1,90 @@ +// Boost.uBLAS +// +// Copyright (c) 2018 Fady Essam +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef boost_numeric_ublas_opencl_vector_hpp_ +#define boost_numeric_ublas_opencl_vector_hpp_ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric { namespace ublas { namespace opencl { + +class storage; + +namespace compute = boost::compute; + +} // namespace opencl + +template +class vector : public boost::compute::vector +{ + typedef std::size_t size_type; +public: + vector() : compute::vector() {} + vector(size_type size, compute::context context) + : compute::vector(size, context) + { device_ = context.get_device();} + vector(size_type size, T value, compute::command_queue queue) + : compute::vector(size, value, queue.get_context()) + { + queue.finish(); + device_ = queue.get_device(); + } + + template + vector(vector const &v, compute::command_queue &queue) + : vector(v.size(), queue.get_context()) + { + this->from_host(v, queue); + } + + + const compute::device device() const { return device_;} + compute::device device() { return device_;} + + template + void from_host(ublas::vector const &v, compute::command_queue & queue) + { + assert(this->device() == queue.get_device()); + compute::copy(v.begin(), + v.end(), + this->begin(), + queue); + queue.finish(); + } + + template + void to_host(ublas::vector& v, compute::command_queue& queue) const + { + assert(this->device() == queue.get_device()); + compute::copy(this->begin(), + this->end(), + v.begin(), + queue); + queue.finish(); + } + + void fill(T value, compute::command_queue & queue) + { + assert(this->device() == queue.get_device()); + compute::fill(this->begin(), this->end(), value, queue); + queue.finish(); + } + +private: + compute::device device_; +}; + +}}} + +#endif diff --git a/test/Jamfile b/test/Jamfile index c87596a82..4ecadbad5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -52,6 +52,7 @@ project BOOST_UBLAS_NO_EXCEPTIONS vacpp:"BOOST_UBLAS_NO_ELEMENT_PROXIES" gcc:"-Wall -pedantic -Wextra" + msvc:/bigobj msvc:"/W4" # == all # The define of macros below prevent warnings about the checked versions of SCL and CRT libraries. # Most Boost code does not need these versions (as they are markedly slower). diff --git a/test/opencl/Jamfile b/test/opencl/Jamfile index 7cc7fccf4..a2f851ef9 100644 --- a/test/opencl/Jamfile +++ b/test/opencl/Jamfile @@ -18,5 +18,12 @@ project boost/ublas/test/opencl ; test-suite ocl - : [ run test.cpp ] + : [ run prod_test.cpp ] + [ run elementwise_operations_test.cpp ] + [ run inner_prod_test.cpp ] + [ run outer_prod_test.cpp ] + [ run transposition_test.cpp ] + [ run norm_test.cpp ] + [ run norm2_test.cpp ] + [ run elementwise_operations_with_constants_test.cpp ] ; diff --git a/test/opencl/elementwise_operations_test.cpp b/test/opencl/elementwise_operations_test.cpp new file mode 100644 index 000000000..60c76e74d --- /dev/null +++ b/test/opencl/elementwise_operations_test.cpp @@ -0,0 +1,44 @@ +#include "elementwise_operations_test.hpp" + +int main() +{ + + ///testing row major flaot elementwise operations + bench_elementwise , 10, 10> b1; + + ///testing row major complex float elementwise operations + bench_elementwise , ublas::basic_row_major<>, 10, 10> b2; + + ///testing row major double elementwise operations + bench_elementwise , 10, 10> b5; + + ///testing row major complex double elementwise operations + bench_elementwise , ublas::basic_row_major<>, 10, 10> b6; + + ///testing column major flaot elementwise operations + bench_elementwise , 10, 10> b3; + + ///testing column major complex float elementwise operations + bench_elementwise , ublas::basic_column_major<>, 10, 10> b4; + + ///testing column major double elementwise operations + bench_elementwise , 10, 10> b7; + + ///testing column major complex double elementwise operations + bench_elementwise , ublas::basic_column_major<>, 10, 10> b8; + + + std::cout << "row major:" << std::endl; + b1.run(); + b2.run(); + b5.run(); + b6.run(); + + + std::cout << "column major:" << std::endl; + b3.run(); + b4.run(); + b7.run(); + b8.run(); + +} diff --git a/test/opencl/elementwise_operations_test.hpp b/test/opencl/elementwise_operations_test.hpp new file mode 100644 index 000000000..2fe2e571a --- /dev/null +++ b/test/opencl/elementwise_operations_test.hpp @@ -0,0 +1,114 @@ +#ifndef ELEMENT_OPENCL_HH +#define ELEMENT_OPENCL_HH +#include "test_opencl.hpp" + +template +class bench_elementwise +{ +public: + typedef test_opencl test; + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::matrix a; + ublas::matrix b; + + //matrix-matrix operations of cpu + ublas::matrix result_m_add; + ublas::matrix result_m_sub; + ublas::matrix result_m_mul; + + //matrix-matrix operations of gpu + ublas::matrix result_m_add_cl; + ublas::matrix result_m_sub_cl; + ublas::matrix result_m_mul_cl; + + + ublas::vector va; + ublas::vector vb; + + //vector-vector operations of cpu + ublas::vector result_v_add; + ublas::vector result_v_sub; + ublas::vector result_v_mul; + + //vector-vector operations of gpu + ublas::vector result_v_add_cl; + ublas::vector result_v_sub_cl; + ublas::vector result_v_mul_cl; + + + for (int i = 0; i + +int main() +{ + + ///testing row major flaot prod + bench_elementwise_constant, 10, 10> b1; + + ///testing row major complex float prod + bench_elementwise_constant, ublas::basic_row_major<>, 10, 10> b2; + + + ///testing row major double prod + bench_elementwise_constant, 10, 10> b3; + + ///testing row major complex float elementwise operations with constants + bench_elementwise_constant, ublas::basic_row_major<>, 10, 10> b4; + + + ///testing column major flaot elementwise operations with constants + bench_elementwise_constant, 10, 10> b5; + + ///testing column major complex float elementwise operations with constants + bench_elementwise_constant, ublas::basic_column_major<>, 10, 10> b6; + + ///testing column major double elementwise operations with constants + bench_elementwise_constant, 10, 10> b7; + + ///testing column major complex double elementwise operations with constants + bench_elementwise_constant, ublas::basic_column_major<>, 10, 10> b8; + + + std::cout << "Row major:" << std::endl; + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + std::cout << "Column major:" << std::endl; + b5.run(); + b6.run(); + b7.run(); + b8.run(); + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/elementwise_operations_with_constants_test.hpp b/test/opencl/elementwise_operations_with_constants_test.hpp new file mode 100644 index 000000000..f78a73827 --- /dev/null +++ b/test/opencl/elementwise_operations_with_constants_test.hpp @@ -0,0 +1,86 @@ +#ifndef TEST_ELEMENT_CONSTANT_OPENCL_HH +#define TEST_ELEMENT_CONSTANT_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_elementwise_constant +{ +public: + + typedef test_opencl test; + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::matrix m; + ublas::matrix m_result_add_ublas; + ublas::matrix m_result_sub_ublas; + ublas::matrix m_result_add_opencl; + ublas::matrix m_result_sub_opencl; + ublas::vector v; + ublas::vector v_result_add_ublas; + ublas::vector v_result_sub_ublas; + ublas::vector v_result_add_opencl; + ublas::vector v_result_sub_opencl; + + + + for (int i = 0; i m_constant_holder(rows, cols, constant); + ublas::vector v_constant_holder(rows, constant); + + m_result_add_ublas = m + m_constant_holder; + m_result_sub_ublas = m - m_constant_holder; + m_result_add_opencl = opencl::element_add(m, constant, queue); + m_result_sub_opencl = opencl::element_sub(m, constant, queue); + + v_result_add_ublas = v + v_constant_holder; + v_result_sub_ublas = v - v_constant_holder; + v_result_add_opencl = opencl::element_add(v, constant, queue); + v_result_sub_opencl = opencl::element_sub(v, constant, queue); + + + + if ((!test::compare(m_result_add_ublas, m_result_add_opencl)) + || (!test::compare(m_result_sub_ublas, m_result_sub_opencl)) || + (!test::compare(v_result_add_ublas, v_result_add_opencl)) + || (!test::compare(v_result_sub_ublas, v_result_sub_opencl))) + { + std::cout << "Error in calculations" << std::endl; + + std::cout << "passed: " << passedOperations << std::endl; + return; + } + + passedOperations++; + + } + std::cout << "All is well (matrix opencl elementwise operations with constants) of " << typeid(T).name() << std::endl; + + + + } + +}; + +#endif \ No newline at end of file diff --git a/test/opencl/inner_prod_test.cpp b/test/opencl/inner_prod_test.cpp new file mode 100644 index 000000000..3f1480e06 --- /dev/null +++ b/test/opencl/inner_prod_test.cpp @@ -0,0 +1,23 @@ +#include "inner_prod_test.hpp" +#include + +int main() +{ + ///testing row major int inner prod + bench_inner_prod b1; + + ///testing row major float inner prod + bench_inner_prod b2; + + + ///testing row major double inner prod + bench_inner_prod b3; + + + b1.run(); + b2.run(); + b3.run(); + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/inner_prod_test.hpp b/test/opencl/inner_prod_test.hpp new file mode 100644 index 000000000..cf9dc6465 --- /dev/null +++ b/test/opencl/inner_prod_test.hpp @@ -0,0 +1,64 @@ +#ifndef TEST_INNER_PROD_HH +#define TEST_INNER_PROD_HH +#include "test_opencl.hpp" + + +template +class bench_inner_prod +{ +public: + + typedef test_opencl test; + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::vector va; + ublas::vector vb; + T result_inner_prod_ublas; + T result_inner_prod_opencl; + + + for (int i = 0; i + +int main() +{ + + ///testing float norm2 + bench_norm2 b1; + + + ///testing double norm2 + bench_norm2 b2; + + + ///testing float norm2 + bench_norm2, 10, 10> b3; + + + ///testing double norm2 + bench_norm2, 10, 10> b4; + + + + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/norm2_test.hpp b/test/opencl/norm2_test.hpp new file mode 100644 index 000000000..8a7d6919c --- /dev/null +++ b/test/opencl/norm2_test.hpp @@ -0,0 +1,59 @@ +#ifndef TEST_NORM2_OPENCL_HH +#define TEST_NORM2_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_norm2 +{ +public: + + typedef test_opencl> test; + + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::vector v; + + + for (int i = 0; i 1e-6) //precision of float + { + std::cout << "Error in calculations" << std::endl; + + std::cout << "passed: " << passedOperations << std::endl; + return; + } + + passedOperations++; + + } + std::cout << "All is well (vector opencl a_sum) of " << typeid(T).name() << std::endl; + + + + } + +}; + +#endif \ No newline at end of file diff --git a/test/opencl/norm_test.cpp b/test/opencl/norm_test.cpp new file mode 100644 index 000000000..79d6eabff --- /dev/null +++ b/test/opencl/norm_test.cpp @@ -0,0 +1,22 @@ +#include "norm_test.hpp" +#include + +int main() +{ + + ///testing float norm1 + bench_norm b1; + + + ///testing double norm1 + bench_norm b2; + + + + b1.run(); + b2.run(); + + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/norm_test.hpp b/test/opencl/norm_test.hpp new file mode 100644 index 000000000..9623de908 --- /dev/null +++ b/test/opencl/norm_test.hpp @@ -0,0 +1,59 @@ +#ifndef TEST_NORM_OPENCL_HH +#define TEST_NORM_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_norm +{ +public: + + typedef test_opencl> test; + + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::vector v; + + + for (int i = 0; i b1; + + + ///testing double outer prod + bench_outer_prod b2; + + + ///testing complex of float outer prod + bench_outer_prod, 10, 10> b3; + + + ///testing complex of double outer prod + bench_outer_prod, 10, 10> b4; + + + + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/outer_prod_test.hpp b/test/opencl/outer_prod_test.hpp new file mode 100644 index 000000000..348d0b1d6 --- /dev/null +++ b/test/opencl/outer_prod_test.hpp @@ -0,0 +1,65 @@ +#ifndef TEST_PROD_OPENCL_HH +#define TEST_PROD_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_outer_prod +{ +public: + + typedef test_opencl test; + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::vector va; + ublas::vector vb; + ublas::matrix resultUBLAS; + ublas::matrix resultOPENCL; + + + for (int i = 0; i + +int main() +{ + + ///testing row major flaot prod + bench_prod, 10, 10> b1; + + ///testing row major complex float prod + bench_prod, ublas::basic_row_major<>, 10, 10> b2; + + + ///testing row major double prod + bench_prod, 10, 10> b3; + + ///testing row major complex float prod + bench_prod, ublas::basic_row_major<>, 10, 10> b4; + + + ///testing column major flaot prod + bench_prod, 10, 10> b5; + + ///testing column major complex float prod + bench_prod, ublas::basic_column_major<>, 10, 10> b6; + + ///testing column major double prod + bench_prod, 10, 10> b7; + + ///testing column major complex double prod + bench_prod, ublas::basic_column_major<>, 10, 10> b8; + + + std::cout << "Row major:" << std::endl; + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + std::cout << "Column major:" << std::endl; + b5.run(); + b6.run(); + b7.run(); + b8.run(); + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/prod_test.hpp b/test/opencl/prod_test.hpp new file mode 100644 index 000000000..e760a842c --- /dev/null +++ b/test/opencl/prod_test.hpp @@ -0,0 +1,88 @@ +#ifndef TEST_PROD_OPENCL_HH +#define TEST_PROD_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_prod +{ +public: + + typedef test_opencl test; + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::matrix a; + ublas::matrix b; + ublas::matrix resultUBLAS; + ublas::matrix resultOPENCL; + ublas::vector va; + ublas::vector vb; + ublas::vector result_vector_ublas_mv; + ublas::vector result_vector_ublas_vm; + ublas::vector result_vector_opencl_mv; + ublas::vector result_vector_opencl_vm; + + + + for (int i = 0; i - -int main() -{ -} diff --git a/test/opencl/test_opencl.hpp b/test/opencl/test_opencl.hpp new file mode 100644 index 000000000..fe1af32ef --- /dev/null +++ b/test/opencl/test_opencl.hpp @@ -0,0 +1,84 @@ +#ifndef TEST_OPENCL_HEADER_HH +#define TEST_OPENCL_HEADER_HH +#include + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include +#include + + + + +namespace ublas = boost::numeric::ublas; +namespace opencl = boost::numeric::ublas::opencl; +namespace compute = boost::compute; + +template > +class test_opencl +{ +public: + static bool compare(ublas::matrix& a, ublas::matrix& b) + { + typedef typename ublas::matrix::size_type size_type; + if ((a.size1() != b.size1()) || (a.size2() != b.size2())) + return false; + + for (size_type i = 0; i& a, ublas::vector& b) + { + typedef typename ublas::vector::size_type size_type; + if (a.size() != b.size()) + return false; + + for (size_type i = 0; i& m, int max_value) + { + typedef typename ublas::matrix::size_type size_type; + for (size_type i = 0; i < m.size1(); i++) + { + for (size_type j = 0; j& v, int max_value) + { + typedef typename ublas::vector::size_type size_type; + for (size_type i = 0; i , 10, 10> b1; + bench_trans, 10, 10> b2; + bench_trans, ublas::basic_row_major<>, 10, 10> b3; + bench_trans, ublas::basic_row_major<>, 10, 10> b4; + + //Column-major + bench_trans, 10, 10> b5; + bench_trans, 10, 10> b6; + bench_trans, ublas::basic_column_major<>, 10, 10> b7; + bench_trans, ublas::basic_column_major<>, 10, 10> b8; + + std::cout << "Row-major:" << std::endl; + b1.run(); + b2.run(); + b3.run(); + b4.run(); + + std::cout << std::endl << "Column-major:" << std::endl; + + b5.run(); + b6.run(); + b7.run(); + b8.run(); + + return 0; + +} \ No newline at end of file diff --git a/test/opencl/transposition_test.hpp b/test/opencl/transposition_test.hpp new file mode 100644 index 000000000..eca469f92 --- /dev/null +++ b/test/opencl/transposition_test.hpp @@ -0,0 +1,61 @@ +#ifndef TEST_TRANS_OPENCL_HH +#define TEST_TRANS_OPENCL_HH +#include "test_opencl.hpp" + + +template +class bench_trans +{ +public: + + typedef test_opencl test; + + void run() + { + opencl::library lib; + int passedOperations = 0; + // get default device and setup context + compute::device device = compute::system::default_device(); + compute::context context(device); + compute::command_queue queue(context, device); + + std::srand(time(0)); + + ublas::matrix a; + ublas::matrix resultUBLAS; + ublas::matrix resultOPENCL; + + + for (int i = 0; i Date: Sun, 28 Oct 2018 18:16:25 -0400 Subject: [PATCH 66/73] Add benchmarks for OpenCL API. --- .appveyor.yml | 1 - .travis.yml | 1 - benchmarks/Jamfile | 3 + benchmarks/opencl/Jamfile | 24 +++ benchmarks/opencl/add.cpp | 93 +++++++++++ benchmarks/opencl/benchmark.hpp | 214 +++++++++++++++++++++++++ benchmarks/opencl/init.hpp | 40 +++++ benchmarks/opencl/inner_prod.cpp | 94 +++++++++++ benchmarks/opencl/mm_prod.cpp | 94 +++++++++++ benchmarks/opencl/mv_prod.cpp | 95 +++++++++++ benchmarks/opencl/outer_prod.cpp | 95 +++++++++++ include/boost/numeric/ublas/opencl.hpp | 1 - 12 files changed, 752 insertions(+), 3 deletions(-) create mode 100644 benchmarks/opencl/Jamfile create mode 100644 benchmarks/opencl/add.cpp create mode 100644 benchmarks/opencl/benchmark.hpp create mode 100644 benchmarks/opencl/init.hpp create mode 100644 benchmarks/opencl/inner_prod.cpp create mode 100644 benchmarks/opencl/mm_prod.cpp create mode 100644 benchmarks/opencl/mv_prod.cpp create mode 100644 benchmarks/opencl/outer_prod.cpp diff --git a/.appveyor.yml b/.appveyor.yml index 1b5e98872..adaf5c2e8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,7 +10,6 @@ branches: only: - master - develop - - opencl - /feature\/.*/ environment: diff --git a/.travis.yml b/.travis.yml index 933a22cb2..dc878626a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ branches: - develop - doc - ci - - opencl # env: specifies additional global variables to define per row in build matrix env: diff --git a/benchmarks/Jamfile b/benchmarks/Jamfile index 2e24c4a9d..ab2f77e82 100644 --- a/benchmarks/Jamfile +++ b/benchmarks/Jamfile @@ -1,3 +1,4 @@ +# # Copyright (c) 2018 Stefan Seefeld # Use, modification and distribution are subject to the # Boost Software License, Version 1.0. (See accompanying file @@ -18,3 +19,5 @@ exe reference/mm_prod : reference/mm_prod.cpp ; exe reference/mv_prod : reference/mv_prod.cpp ; exe reference/inner_prod : reference/inner_prod.cpp ; exe reference/outer_prod : reference/outer_prod.cpp ; + +build-project opencl ; diff --git a/benchmarks/opencl/Jamfile b/benchmarks/opencl/Jamfile new file mode 100644 index 000000000..93cdff1f8 --- /dev/null +++ b/benchmarks/opencl/Jamfile @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018 Stefan Seefeld +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or +# copy at http://www.boost.org/LICENSE_1_0.txt) + +import ac ; + +using opencl ; +using clblas ; + +project boost/ublas/benchmarks/opencl + : requirements + /boost/program_options//boost_program_options + gcc:-Wno-ignored-attributes + [ ac.check-library /clblas//clblas : /clblas//clblas /opencl//opencl : no ] + ; + +exe add : add.cpp ; +exe mm_prod : mm_prod.cpp ; +exe mv_prod : mv_prod.cpp ; +exe inner_prod : inner_prod.cpp ; +exe outer_prod : outer_prod.cpp ; diff --git a/benchmarks/opencl/add.cpp b/benchmarks/opencl/add.cpp new file mode 100644 index 000000000..b998cd2c0 --- /dev/null +++ b/benchmarks/opencl/add.cpp @@ -0,0 +1,93 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include "benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; +namespace opencl = boost::numeric::ublas::opencl; + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl { + +template class add; + +template +class add : public benchmark +{ +public: + add(std::string const &name) : benchmark(name) {} + virtual void operation(long l) + { + ublas::opencl::element_add(*this->a, *this->b, *this->c, this->queue); + } +}; + +}}}}} + +template +void benchmark(std::string const &type, bool copy) +{ + using vector = ublas::vector; + std::string name = "opencl::elementwise_add(vector<" + type + ">)"; + std::vector sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}); + if (copy) + { + bm::opencl::add p(name); + p.run(sizes); + } + else + { + bm::opencl::add p(name); + p.run(sizes); + } +} + +int main(int argc, char **argv) +{ + opencl::library lib; + po::variables_map vm; + try + { + po::options_description desc("Matrix-vector product (OpenCL)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + desc.add_options()("copy,c", po::value(), "include host<->device copy in timing"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + bool copy = vm.count("copy") ? vm["copy"].as() : false; + if (type == "float") + benchmark("float", copy); + else if (type == "double") + benchmark("double", copy); + else if (type == "fcomplex") + benchmark>("std::complex", copy); + else if (type == "dcomplex") + benchmark>("std::complex", copy); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/opencl/benchmark.hpp b/benchmarks/opencl/benchmark.hpp new file mode 100644 index 000000000..fb6075992 --- /dev/null +++ b/benchmarks/opencl/benchmark.hpp @@ -0,0 +1,214 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef opencl_benchmark_hpp_ +#define opencl_benchmark_hpp_ +#define BOOST_UBLAS_ENABLE_OPENCL + +#include +#include "../benchmark.hpp" +#include "init.hpp" +#include + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { +namespace opencl { + +struct base +{ + base(compute::device d = compute::system::default_device()) + : context(d), + queue(context, d) + {} + compute::context context; + compute::command_queue queue; +}; + +template struct data_factory; +template +struct data_factory +{ + typedef T type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long) { return ptr_type(new T());} +}; +template +struct data_factory +{ + typedef T type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long, compute::context) { return ptr_type(new T());} +}; +template <> +struct data_factory +{ + typedef void type; + typedef void *ptr_type; + static ptr_type create(long) { return 0;} +}; +template <> +struct data_factory +{ + typedef void type; + typedef void *ptr_type; + static ptr_type create(long, compute::context) { return 0;} +}; +template +struct data_factory, true> +{ + typedef ublas::vector type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long l) { return ptr_type(new type(l));} +}; +template +struct data_factory, false> +{ + typedef ublas::vector type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long l, compute::context c) + { return ptr_type(new type(l, c));} +}; +template +struct data_factory, true> +{ + typedef ublas::matrix type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long l) + { return ptr_type(new type(l, l));} +}; +template +struct data_factory, false> +{ + typedef ublas::matrix type; + typedef std::unique_ptr ptr_type; + static ptr_type create(long l, compute::context c) + { return ptr_type(new type(l, l, c));} +}; + +template class benchmark; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) + : base(), + ublas::benchmark::benchmark(name + " with copy") + {} + virtual void setup(long l) + { + r = data_factory::create(l); + a = data_factory::create(l); + init(*a, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; +}; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) + : base(), + ublas::benchmark::benchmark(name + " with copy") + {} + virtual void setup(long l) + { + r = data_factory::create(l); + a = data_factory::create(l); + init(*a, l, 200); + b = data_factory::create(l); + init(*b, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; + typename data_factory::ptr_type b; +}; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) + : base(), + ublas::benchmark::benchmark(name + " with copy") + {} + virtual void setup(long l) + { + r = data_factory::create(l); + a = data_factory::create(l); + init(*a, l, 200); + b = data_factory::create(l); + init(*b, l, 200); + c = data_factory::create(l); + init(*c, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; + typename data_factory::ptr_type b; + typename data_factory::ptr_type c; +}; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) + : base(), + ublas::benchmark::benchmark(name + " w/o copy") + {} + virtual void setup(long l) + { + r = data_factory::create(l, context); + a = data_factory::create(l, context); + init(*a, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; +}; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) : base(), ublas::benchmark::benchmark(name + " w/o copy") {} + virtual void setup(long l) + { + r = data_factory::create(l, context); + a = data_factory::create(l, context); + init(*a, l, 200); + b = data_factory::create(l, context); + init(*b, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; + typename data_factory::ptr_type b; +}; + +template +class benchmark : public base, public ublas::benchmark::benchmark +{ +public: + benchmark(std::string const &name) : base(), ublas::benchmark::benchmark(name + " w/o copy") {} + virtual void setup(long l) + { + r = data_factory::create(l, context); + a = data_factory::create(l, context); + init(*a, l, 200); + b = data_factory::create(l, context); + init(*b, l, 200); + c = data_factory::create(l, context); + init(*c, l, 200); + } + typename data_factory::ptr_type r; + typename data_factory::ptr_type a; + typename data_factory::ptr_type b; + typename data_factory::ptr_type c; +}; +}}}}} + +#endif diff --git a/benchmarks/opencl/init.hpp b/benchmarks/opencl/init.hpp new file mode 100644 index 000000000..a11410283 --- /dev/null +++ b/benchmarks/opencl/init.hpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include "../init.hpp" + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { + +template +void init(T &v, unsigned long size, int max_value) +{ + // TBD +} + +template +void init(vector &v, unsigned long size, int max_value) +{ + // TBD +} + +template +void init(matrix &m, unsigned long size1, unsigned long size2, int max_value) +{ + // TBD +} + +template +void init(matrix &m, unsigned long size, int max_value) +{ + init(m, size, size, max_value); +} + +}}}} diff --git a/benchmarks/opencl/inner_prod.cpp b/benchmarks/opencl/inner_prod.cpp new file mode 100644 index 000000000..a25664cbf --- /dev/null +++ b/benchmarks/opencl/inner_prod.cpp @@ -0,0 +1,94 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include "benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; +namespace opencl = boost::numeric::ublas::opencl; + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl { + +template class inner_prod; + +template +class inner_prod : public benchmark +{ +public: + inner_prod(std::string const &name) : benchmark(name) {} + virtual void operation(long l) + { + ublas::opencl::inner_prod(*this->a, *this->b, this->queue); + } +}; + +}}}}} + +template +void benchmark(std::string const &type, bool copy) +{ + using vector = ublas::vector; + std::string name = "opencl::inner_prod(vector<" + type + ">)"; + std::vector sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}); + if (copy) + { + bm::opencl::inner_prod p(name); + p.run(sizes); + } + else + { + bm::opencl::inner_prod p(name); + p.run(sizes); + } +} + +int main(int argc, char **argv) +{ + opencl::library lib; + po::variables_map vm; + try + { + po::options_description desc("Inner product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + desc.add_options()("copy,c", po::value(), "include host<->device copy in timing"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + bool copy = vm.count("copy") ? vm["copy"].as() : false; + if (type == "float") + benchmark("float", copy); + else if (type == "double") + benchmark("double", copy); + // else if (type == "fcomplex") + // benchmark>("std::complex", copy); + // else if (type == "dcomplex") + // benchmark>("std::complex", copy); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/opencl/mm_prod.cpp b/benchmarks/opencl/mm_prod.cpp new file mode 100644 index 000000000..e306031fe --- /dev/null +++ b/benchmarks/opencl/mm_prod.cpp @@ -0,0 +1,94 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include "benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; +namespace opencl = boost::numeric::ublas::opencl; + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl { + +template class prod; + +template +class prod : public benchmark +{ +public: + prod(std::string const &name) : benchmark(name) {} + virtual void operation(long l) + { + ublas::opencl::prod(*this->a, *this->b, *this->c, this->queue); + } +}; + +}}}}} + +template +void benchmark(std::string const &type, bool copy) +{ + using matrix = ublas::matrix; + std::string name = "opencl::prod(matrix<" + type + ">)"; + std::vector sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}); + if (copy) + { + bm::opencl::prod p(name); + p.run(sizes); + } + else + { + bm::opencl::prod p(name); + p.run(sizes); + } +} + +int main(int argc, char **argv) +{ + opencl::library lib; + po::variables_map vm; + try + { + po::options_description desc("Matrix product (OpenCL)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + desc.add_options()("copy,c", po::value(), "include host<->device copy in timing"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + bool copy = vm.count("copy") ? vm["copy"].as() : false; + if (type == "float") + benchmark("float", copy); + else if (type == "double") + benchmark("double", copy); + else if (type == "fcomplex") + benchmark>("std::complex", copy); + else if (type == "dcomplex") + benchmark>("std::complex", copy); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/opencl/mv_prod.cpp b/benchmarks/opencl/mv_prod.cpp new file mode 100644 index 000000000..70344a4b6 --- /dev/null +++ b/benchmarks/opencl/mv_prod.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include "benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; +namespace opencl = boost::numeric::ublas::opencl; + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl { + +template class prod; + +template +class prod : public benchmark +{ +public: + prod(std::string const &name) : benchmark(name) {} + virtual void operation(long l) + { + ublas::opencl::prod(*this->a, *this->b, *this->c, this->queue); + } +}; + +}}}}} + +template +void benchmark(std::string const &type, bool copy) +{ + using vector = ublas::vector; + using matrix = ublas::matrix; + std::string name = "opencl::prod(matrix<" + type + ", vector<" + type + ">)"; + std::vector sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}); + if (copy) + { + bm::opencl::prod p(name); + p.run(sizes); + } + else + { + bm::opencl::prod p(name); + p.run(sizes); + } +} + +int main(int argc, char **argv) +{ + opencl::library lib; + po::variables_map vm; + try + { + po::options_description desc("Matrix-vector product (OpenCL)\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + desc.add_options()("copy,c", po::value(), "include host<->device copy in timing"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + bool copy = vm.count("copy") ? vm["copy"].as() : false; + if (type == "float") + benchmark("float", copy); + else if (type == "double") + benchmark("double", copy); + else if (type == "fcomplex") + benchmark>("std::complex", copy); + else if (type == "dcomplex") + benchmark>("std::complex", copy); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/benchmarks/opencl/outer_prod.cpp b/benchmarks/opencl/outer_prod.cpp new file mode 100644 index 000000000..b00bb840c --- /dev/null +++ b/benchmarks/opencl/outer_prod.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2018 Stefan Seefeld +// All rights reserved. +// +// This file is part of Boost.uBLAS. It is made available under the +// Boost Software License, Version 1.0. +// (Consult LICENSE or http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_UBLAS_ENABLE_OPENCL +#include +#include +#include "benchmark.hpp" +#include +#include + +namespace po = boost::program_options; +namespace ublas = boost::numeric::ublas; +namespace bm = boost::numeric::ublas::benchmark; +namespace opencl = boost::numeric::ublas::opencl; + +namespace boost { namespace numeric { namespace ublas { namespace benchmark { namespace opencl { + +template class outer_prod; + +template +class outer_prod : public benchmark +{ +public: + outer_prod(std::string const &name) : benchmark(name) {} + virtual void operation(long l) + { + ublas::opencl::outer_prod(*this->a, *this->b, *this->c, this->queue); + } +}; + +}}}}} + +template +void benchmark(std::string const &type, bool copy) +{ + using vector = ublas::vector; + using matrix = ublas::matrix; + std::string name = "opencl::outer_prod(vector<" + type + ">)"; + std::vector sizes({1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}); + if (copy) + { + bm::opencl::outer_prod p(name); + p.run(sizes); + } + else + { + bm::opencl::outer_prod p(name); + p.run(sizes); + } +} + +int main(int argc, char **argv) +{ + opencl::library lib; + po::variables_map vm; + try + { + po::options_description desc("Outer product\n" + "Allowed options"); + desc.add_options()("help,h", "produce help message"); + desc.add_options()("type,t", po::value(), "select value-type (float, double, fcomplex, dcomplex)"); + desc.add_options()("copy,c", po::value(), "include host<->device copy in timing"); + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return 0; + } + } + catch(std::exception &e) + { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + std::string type = vm.count("type") ? vm["type"].as() : "float"; + bool copy = vm.count("copy") ? vm["copy"].as() : false; + if (type == "float") + benchmark("float", copy); + else if (type == "double") + benchmark("double", copy); + else if (type == "fcomplex") + benchmark>("std::complex", copy); + else if (type == "dcomplex") + benchmark>("std::complex", copy); + else + std::cerr << "unsupported value-type \"" << vm["type"].as() << '\"' << std::endl; +} diff --git a/include/boost/numeric/ublas/opencl.hpp b/include/boost/numeric/ublas/opencl.hpp index bf8101254..925804610 100644 --- a/include/boost/numeric/ublas/opencl.hpp +++ b/include/boost/numeric/ublas/opencl.hpp @@ -1,4 +1,3 @@ -// Boost.uBLAS // // Copyright (c) 2018 Stefan Seefeld // From 48ad2104dd52feb5e1cedfbaf811afad8889a41f Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 30 Oct 2018 00:21:56 -0400 Subject: [PATCH 67/73] Fix extension module lookup. --- benchmarks/opencl/Jamfile | 5 ++++- test/opencl/Jamfile | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/benchmarks/opencl/Jamfile b/benchmarks/opencl/Jamfile index 93cdff1f8..670ec66b8 100644 --- a/benchmarks/opencl/Jamfile +++ b/benchmarks/opencl/Jamfile @@ -1,5 +1,5 @@ # -# Copyright (c) 2018 Stefan Seefeld +# Copyright (c) 2018 Stefan Seefeld # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or @@ -7,6 +7,9 @@ import ac ; +# work around a bug in Boost.Build +import ../../opencl ; +import ../../clblas ; using opencl ; using clblas ; diff --git a/test/opencl/Jamfile b/test/opencl/Jamfile index a2f851ef9..51c74675e 100644 --- a/test/opencl/Jamfile +++ b/test/opencl/Jamfile @@ -1,6 +1,5 @@ -# Boost.uBLAS # -# Copyright (c) 2018 Stefan Seefeld +# Copyright (c) 2018 Stefan Seefeld # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or @@ -8,6 +7,9 @@ import ac ; +# work around a bug in Boost.Build +import ../../opencl ; +import ../../clblas ; using opencl ; using clblas ; From 675db26b4df211e5edd886e306aec2fc5932fab0 Mon Sep 17 00:00:00 2001 From: Cem Bassoy Date: Fri, 4 May 2018 16:08:30 +0200 Subject: [PATCH 68/73] tensor gsoc 2018. tensor and auxiliary template classes added. --- CHANGES.md | 32 + IDEs/qtcreator/include/include.pro | 7 +- IDEs/qtcreator/include/tensor/tensor.pri | 4 + IDEs/qtcreator/test/test_tensor.pro | 17 + IDEs/qtcreator/tests.pri | 4 +- IDEs/qtcreator/ublas_develop.pro | 6 +- README.md | 38 +- doc/index.html | 10 + doc/tensor.html | 491 ++++++++++ include/boost/numeric/ublas/storage.hpp | 10 + include/boost/numeric/ublas/tensor.hpp | 876 ++++++++++++++++++ .../boost/numeric/ublas/tensor/extents.hpp | 313 +++++++ .../boost/numeric/ublas/tensor/strides.hpp | 183 ++++ test/tensor/test_extents.cpp | 122 +++ test/tensor/test_strides.cpp | 184 ++++ test/tensor/test_tensor.cpp | 470 ++++++++++ 16 files changed, 2753 insertions(+), 14 deletions(-) create mode 100644 CHANGES.md create mode 100644 IDEs/qtcreator/include/tensor/tensor.pri create mode 100644 IDEs/qtcreator/test/test_tensor.pro create mode 100644 doc/tensor.html create mode 100644 include/boost/numeric/ublas/tensor.hpp create mode 100644 include/boost/numeric/ublas/tensor/extents.hpp create mode 100644 include/boost/numeric/ublas/tensor/strides.hpp create mode 100644 test/tensor/test_extents.cpp create mode 100644 test/tensor/test_strides.cpp create mode 100644 test/tensor/test_tensor.cpp diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 000000000..162b673c2 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,32 @@ +Changes +===== +While the tensor template class and its auxiliary classes inherits the implementation style of the matrix and vector template class, they deviate in some points. This document shall give an overview of the changes. + + +## Implementation [Tensor] + +* The current implementation of the tensor template class __only compiles with compilers supporting C++17__ mostly because `constexpr if` is used. +* Function `max_size()` in vector and matrix class is removed. It can still be queried through the underlying storage array. Note that `max_size()` is depcretated since C++17 for the std::vector. +* Functions like `find_element()` are put outside the tensor template class as free functions. +* Iterator structures are removed. +* Member functions `data()` return a pointer instead of an `array_type` instance. +* Data access functions are implemented with `operator[]` and function `at()`. +* Function `operator()` will be used to select/project sections of tensors. +* Functions `insert_element()` and `erase_element()` will not be used. +* Function `resize()` will be renamed to `reshape()` using extents. +* Proxy shortcuts for tensor expressions will not be used. It does not make user code more readible or convenient. + + + +## Implementation [Unbounded Array] +* Included move copy constructor. + +## Unit-Testing [Tensor] + +* The boost unit-test framework is dynamically linked. +* Unit-Tests are not executed when compiled. +* Renamed unit test folder according to the tested template classes and functions. +* Utilized some of the latest features of the boost unit-test framework version 1.67 such as fixtures and templates. +* Pragmas not included for unit testing. + +## Documentation [Tensor] diff --git a/IDEs/qtcreator/include/include.pro b/IDEs/qtcreator/include/include.pro index 5815a01fe..185254103 100644 --- a/IDEs/qtcreator/include/include.pro +++ b/IDEs/qtcreator/include/include.pro @@ -13,6 +13,10 @@ include(experimental/experimental.pri) include(operation/operation.pri) include(traits/traits.pri) +include(tensor/tensor.pri) + +INCLUDEPATH += $${INCLUDE_DIR} + HEADERS += \ $${INCLUDE_DIR}/boost/numeric/ublas/vector_sparse.hpp \ $${INCLUDE_DIR}/boost/numeric/ublas/vector_proxy.hpp \ @@ -44,4 +48,5 @@ HEADERS += \ $${INCLUDE_DIR}/boost/numeric/ublas/blas.hpp \ $${INCLUDE_DIR}/boost/numeric/ublas/banded.hpp \ $${INCLUDE_DIR}/boost/numeric/ublas/assignment.hpp \ - $${INCLUDE_DIR}/boost/numeric/ublas/matrix_vector.hpp + $${INCLUDE_DIR}/boost/numeric/ublas/matrix_vector.hpp \ + $${INCLUDE_DIR}/boost/numeric/ublas/tensor.hpp diff --git a/IDEs/qtcreator/include/tensor/tensor.pri b/IDEs/qtcreator/include/tensor/tensor.pri new file mode 100644 index 000000000..4ad81d97a --- /dev/null +++ b/IDEs/qtcreator/include/tensor/tensor.pri @@ -0,0 +1,4 @@ +HEADERS += \ + $${INCLUDE_DIR}/boost/numeric/ublas/tensor/extents.hpp \ + $${INCLUDE_DIR}/boost/numeric/ublas/tensor/strides.hpp +# $${INCLUDE_DIR}/boost/numeric/ublas/tensor/layout.hpp diff --git a/IDEs/qtcreator/test/test_tensor.pro b/IDEs/qtcreator/test/test_tensor.pro new file mode 100644 index 000000000..0100061ab --- /dev/null +++ b/IDEs/qtcreator/test/test_tensor.pro @@ -0,0 +1,17 @@ +TEMPLATE = app +TARGET = test + +#include (configuration.pri) + +QMAKE_CXXFLAGS += -std=c++17 + +LIBS +=-lboost_unit_test_framework + +SOURCES += \ + ../../../test/tensor/test_tensor.cpp \ + ../../../test/tensor/test_extents.cpp \ + ../../../test/tensor/test_strides.cpp + + +INCLUDEPATH += \ + ../../../include diff --git a/IDEs/qtcreator/tests.pri b/IDEs/qtcreator/tests.pri index 6ece4acd5..2234436a7 100644 --- a/IDEs/qtcreator/tests.pri +++ b/IDEs/qtcreator/tests.pri @@ -36,7 +36,8 @@ SUBDIRS += \ test_ticket7296 \ test_triangular \ triangular_access \ - triangular_layout + triangular_layout \ + test_tensor begin_end.file = test/begin_end.pro comp_mat_erase.file = test/comp_mat_erase.pro @@ -72,3 +73,4 @@ test_ticket7296.file = test/test_ticket7296.pro test_triangular.file = test/test_triangular.pro triangular_access.file = test/triangular_access.pro triangular_layout.file = test/triangular_layout.pro +test_tensor.file = test/test_tensor.pro diff --git a/IDEs/qtcreator/ublas_develop.pro b/IDEs/qtcreator/ublas_develop.pro index 7364283a9..25db0d574 100644 --- a/IDEs/qtcreator/ublas_develop.pro +++ b/IDEs/qtcreator/ublas_develop.pro @@ -3,4 +3,8 @@ CONFIG += ordered SUBDIRS = include benchmarks OTHER_FILES += ../../changelog.txt -include (tests.pri) + +SUBDIRS += test_tensor +test_tensor.file = test/test_tensor.pro + +#include (tests.pri) diff --git a/README.md b/README.md index c027ee79f..154e8160d 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,34 @@ -ublas +Boost.uBLAS Linear Algebra Library ===== +Boost.uBLAS is part of the [Boost C++ Libraries](http://github.com/boostorg). It is directed towards scientific computing on the level of basic linear algebra constructions with matrices and vectors and their corresponding abstract operations. -# Building [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=develop)](https://travis-ci.org/boostorg/ublas) [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/develop) +### License -The Boost.uBLAS Linear Algebra Library v1.0 +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). -- To follow development and test experimental features, you can clone the Github project uBLAS/ublas -at https://github.com/uBLAS/ublas -- A development wiki is available at https://github.com/uBLAS/ublas/wiki -- A mailing-list is available at http://lists.boost.org/ublas/ -- For any other questions, you can contact David at david.bellot@gmail.com +### Properties -- version numbers have never been used for this library until 02 March 2014. - So we start at v1.0 on that day. +* Header-only -last update: 1 April 2014 +### Build Status + +Branch | Travis | Appveyor | codecov.io | Docs | +:-------------: | ------ | -------- | ---------- | ---- | +[`develop`](https://travis-ci.org/boostorg/ublas.svg?branch=develop) | [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=develop)](https://travis-ci.org/boostorg/ublas) | [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/uuid/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/uuid/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/numeric) + +### Directories + +| Name | Purpose | +| ----------- | ------------------------------ | +| `doc` | documentation | +| `include` | headers | +| `test` | unit tests | + +### More information + +* Ask questions in [stackoverflow](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-ublas) with `boost-ublas` or `ublas` tags. +* Report [bugs](https://github.com/boostorg/ublas/issues) and be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). +* Developer discussions about the library are held on the [Boost developers mailing list](https://lists.boost.org/mailman/listinfo.cgi/ublas). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[ublas]` tag at the beginning of the subject line +* For any other questions, you can contact David at david.bellot@gmail.com diff --git a/doc/index.html b/doc/index.html index 6a3a15dfd..ec32f6b86 100644 --- a/doc/index.html +++ b/doc/index.html @@ -216,6 +216,16 @@

Documentation

+ +
  • Tensor + +
  • +
  • Storage and special containers
  • diff --git a/doc/operations_overview.html b/doc/operations_overview.html index 212fcbebf..442048e98 100644 --- a/doc/operations_overview.html +++ b/doc/operations_overview.html @@ -14,7 +14,7 @@ uBLAS operations overview -

    Overview of Matrix and Vector Operations

    +

    Overview of Tensor, Matrix and Vector Operations

    @@ -28,6 +28,8 @@

    Overview of Matrix and Vec

    Definitions

    + + @@ -46,25 +48,26 @@

    Basic Linear Algebra

    standard operations: addition, subtraction, multiplication by a scalar

    -
    
    +X = Y + Z; X = Y - Z; X = -Y;
     C = A + B; C = A - B; C = -A;
     w = u + v; w = u - v; w = -u;
    +X = t * Y; Y = X * t; X = Y / t;
     C = t * A; C = A * t; C = A / t;
     w = t * u; w = u * t; w = u / t;
     

    computed assignments

    -
    
    +X += Y; X -= Y; 
     C += A; C -= A; 
     w += u; w -= u; 
    +X *= t; X /= t; 
     C *= t; C /= t; 
     w *= t; w /= t;
     

    inner, outer and other products

    -
    
     t = inner_prod(u, v);
     C = outer_prod(u, v);
    @@ -74,13 +77,24 @@ 

    inner, outer and other products

    C = element_prod(A, B); C = element_div(A, B);
    -

    transformations

    +

    tensor products

    +
    
    +Z = prod(X, v, t);
    +Z = prod(X, A, t);
    +Z = prod(X, Y, p);
    +Z = prod(X, Y, pa, pb);
    +t = inner_prod(X, Y);
    +Z = outer_prod(X, Y);
    +
    +

    transformations

    
     w = conj(u); w = real(u); w = imag(u);
     C = trans(A); C = conj(A); C = herm(A); C = real(A); C = imag(A);
    +Z = trans(X); Z = conj(X); Z = real(X); Z = imag(X);
     
    +

    Advanced functions

    norms

    @@ -91,6 +105,7 @@

    norms

    t = norm_2_square(v); t = norm_inf(A); i = index_norm_inf(A); t = norm_1(A); t = norm_frobenius(A); +t = norm(X);

    products

    diff --git a/doc/tensor.html b/doc/tensor.html index e0d97bd8e..8b08a2fb8 100644 --- a/doc/tensor.html +++ b/doc/tensor.html @@ -9,6 +9,23 @@ + + + + Tensor @@ -16,30 +33,38 @@

    Tensor

    Tensor

    Description

    -

    The templated class tensor<T, F, A> is the -base container adaptor for dense tensors. Every element ti1,i2,...,ip of a p-order (n1 x -n2 x ... x np )-dimensional tensor is mapped to -(i1 x w1 + i2 x w1 + ... + ip x wp )-th element of the container -where 0 <= i1 < n2, 0 <= i2 < n2, ..., 0 <= ip < np. -For first-order orientation wk = nk-1 x wk-1 with w1 = 1 and for last-order orientation wk = nk+1 x wk+1 with wp=1. +

    The templated class tensor<value_t,format_t,storage_t> is the base container adaptor for dense tensors. +Every element $t_{i_1,i_2,\dots,i_p}$ of a $p$-order $(n_1 \times n_2 \times \cdots \times n_p)$-dimensional tensor $T$ is mapped to $j$-th element of a one-dimensional container where $j = \sum_{r=1}^p i_r \cdot w_r$ with $1 \leq i_r \leq n_r $ for $1 \leq r \leq p$. +For the first-order orientation $w_1 = 1$ and $w_k = n_{k-1} \cdot w_{k-1}$ for $k > 1$. For last-order orientation $w_p = 1$ and $ w_k = n_{k+1} \cdot w_{k+1}$ for $k < p$.

    Example

     #include <boost/numeric/ublas/tensor.hpp>
    -#include <boost/numeric/ublas/io.hpp>
     
     int main () {
       using namespace boost::numeric::ublas;
       tensor<double> t{4,2,3};
    -  for (auto k = 0ul; k < t.size (2); ++ k)
    +  for (auto k = 0ul; k < t.size (2); ++ k)
         for (auto j = 0ul; j < t.size (1); ++ j)
           for (auto i = 0ul; i < t.size (0); ++ i)
             t.at(i,j,k) = 3*i + 2*j + 5*k;
    +        
       std::cout << t << std::endl;
     }
     
    +

    Definition

    -

    Defined in the header tensor.hpp.

    +

    Defined in the header file tensor/tensor.hpp.

    + +

    Model of

    +

    Tensor

    + +

    Type requirements

    +

    None, except for those imposed by the requirements of Tensor .

    + +

    Public base classes

    +

    tensor_container<tensor<value_t,format_t,storage_t> >

    +

    Template parameters

    X, Y, Z are tensors
    A, B, C are matrices
    u, v, w
    @@ -49,277 +74,413 @@

    Template parameters

    - + - - + - - - + + +
    Default
    Tvalue_t The type of object stored in the tensor.
    FFunctor describing the storage organization. format_tStorage organization. [1] first_order
    AThe type of the Storage array. [2]unbounded_array<T>storage_tThe type of the Storage array. [2]std::vector<value_t>
    -

    Model of

    -

    Tensor .

    -

    Type requirements

    -

    None, except for those imposed by the requirements of Tensor .

    -

    Public base classes

    -

    tensor_container<tensor<T, F, A> >

    -

    Members

    - - + +

    Member types

    +
    + - + - - + + - - + + - - + + + - - + + - + +

    Assignment

    + + +
    MemberMember type Description
    tensor ()Allocates an uninitialized tensor that holds zero elements.value_typeType value_t of the tensor elements.
    tensor (std::initializer_list list) Allocates an uninitialized tensor where initializer list -list specifies the dimension extents.layout_typeFormat of the tensor which is either first_order or last_order.
    tensor (const extents& e) Allocates an uninitialized tensor where -e specifies the dimension extents.array_typeSequence container type that stores all tensor elements and is accessible with a single index.
    tensor (const extents& e, const array_type& a) Allocates an uninitialized tensor where -e specifies the dimension extents and a the data elements of the tensor.strides_typeType of the strides vector basic_strides<std::size_t,layout_type> that stores all tensor elements and is accessible with a single index.
    + - - + + - - + + + - - + + + - - + + + +
    const_reverse_iterator1 rbegin1 () constReturns a const_reverse_iterator1 pointing to the -beginning of the reversed tensor.Member functionDescription
    const_reverse_iterator1 rend1 () constReturns a const_reverse_iterator1 pointing to the -end of the reversed tensor.tensor& operator=(tensor_expression_type<derived_type> const& expr)Evaluates the tensor expression expr and copyies all elements of the result.
    reverse_iterator1 rbegin1 ()Returns a reverse_iterator1 pointing to the -beginning of the reversed tensor.tensor& operator=(tensor other)Copies or moves elements of other.
    reverse_iterator1 rend1 ()Returns a reverse_iterator1 pointing to the end of -the reversed tensor.tensor& operator=(const_reference v)Initialiates all elements of a tensor with v.
    + + +

    Capacity

    + + + - - + + - - + + + + + + + + - - + + + - - + + ----------------------------------------------------- ---> + + + + + + + +
    const_reverse_iterator2 rbegin2 () constReturns a const_reverse_iterator2 pointing to the -beginning of the reversed tensor.Member functionDescription
    const_reverse_iterator2 rend2 () constReturns a const_reverse_iterator2 pointing to the -end of the reversed tensor.bool empty() constReturns true if a tensor has zero elements.
    size_type size() constReturns the number of elements of the tensor.
    reverse_iterator2 rbegin2 ()Returns a reverse_iterator2 pointing to the -beginning of the reversed tensor.size_type rank() constReturns the number of dimensions of the tensor.
    reverse_iterator2 rend2 ()Returns a reverse_iterator2 pointing to the end of -the reversed tensor.size_type order() constReturns the number of dimensions of the tensor.
    strides_type const& strides() constReturns a constant reference to the strides of the tensor.
    extents_type const& extents() constReturns a constant reference to the extents of the tensor.
    + + + +

    Element access

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Member functionDescription
    pointer data()Returns a pointer the first element of the tensor.
    const_pointer data() constReturns a const_pointer the first element of the tensor.
    reference operator[](size_type j)Returns a reference to the j-th element of the storage array of the tensor. Corresponds to the function call tensor::data()+j
    const_reference operator[](size_type j) constReturns a const_reference to the j-th element of the storage array of the tensor. Corresponds to the function call tensor::data()+j.
    template<class ... size_types>
    reference at(size_type i, size_types ... is)
    Returns a reference to the (i,is...)-th element of the tensor where (i,is...) denotes a multi-index with tensor::order() elements. If sizeof...(is)==0, tensor::operator[i] is called.
    template<class ... size_types>
    const_reference at(size_type i, size_types ... is)
    Returns a const_reference to the (i,is...)-th element of the tensor where (i,is...) denotes a multi-index with tensor::order() elements. If sizeof...(is)==0, tensor::operator[i] is called.
    + + + + +

    Proxy Generation

    + + + + + + + + + + + + + + +
    Member functionDescription
    template<std::size_t I, class ... index_types>
    tensor_index operator()(indices::Index<I> p, index_types ... ps)
    Returns a tensor index instance with index objects (p,ps...) for a tensor contraction where sizeof...(ps)+1 must be equal to tensor::order().
    + + +

    Iterators

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Member functionDescription
    const_iterator begin() constReturns a const_iterator pointing to the first element of the tensor.
    const_iterator cbegin() constReturns a const_iterator pointing to the first element of the tensor.
    iterator begin()Returns an iterator pointing to the first element of the tensor.
    const_iterator end() constReturns a const_iterator pointing to the position after the last element of the tensor.
    const_iterator cend() constReturns a const_iterator pointing to the position after the last element of the tensor.
    iterator begin()Returns an iterator pointing to the position after the last element of the tensor.
    + + +

    Modifiers

    + + + + + + + + + + + + + + +
    Member functionDescription
    void reshape(extents_type const& e, value_type v = value_type{})Reshapes the tensor according to the extents e. If e.product() is greater than tensor::size(), the tensor is resized with v.
    + +

    Notes

    [1] Supported parameters for the storage organization are first_order and last_order.

    [2] Common parameters -for the storage array are unbounded_array<T> , -bounded_array<T> and -std::vector<T> .

    +for the storage array are std::array<N,T> and +std::vector<T>.

    +
    +
    + +

    Entrywise Tensor Operations

    + + +

    Binary Tensor Expression

    + +

    Description

    +

    The templated class binary_tensor_expression<T,EL,ER,OP> contains a constant reference to a left and right expression that can be evaluated by using the access operator.

    +

    Definition

    +

    Defined in the header tensor/expression.hpp.

    +

    Model of

    +

    Tensor Expression

    + + +

    Type requirements

    +

    None.

    + +

    Public base classes

    +

    tensor_expression<T,binary_tensor_expression<T,EL,ER,OP>>

    + +

    Template parameters

    + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterDescription
    TType of the tensor.
    ELType of the left binary tensor expression.
    ERType of the right binary tensor expression.
    OPType of the binary operation.
    + +

    Member types

    + + + + + + + + + + + + + + + + + + + + + + + +
    Member typeDescription
    expression_type_leftType of the left expression which is EL.
    expression_type_rightType of the right expression which is ER.
    tensor_typeReference type which is T.
    binary_operationType of the binary operation which is OP.
    + +

    Public Member Functions

    + + + + + + + + + + + +
    MemberDescription
    decltype(auto) operator()(std::size_t i) const Returns a const reference to the i-th element of the expression.
    +
    + + + +

    Unary Tensor Expression

    + + +

    Description

    +

    The templated class unary_tensor_expression<T,E,OP> contains a constant reference to an expression that can be evaluated by using the access operator.

    +

    Definition

    +

    Defined in the header tensor/expression.hpp.

    +

    Model of

    +

    Tensor Expression

    + +

    Type requirements

    +

    None.

    + +

    Public base classes

    +

    tensor_expression<T,unary_tensor_expression<T,E,OP>>

    + +

    Template parameters

    + + + + + + + + + + + + + + + + + + + +
    ParameterDescription
    TType of the tensor.
    EType of the unary tensor expression.
    OPType of the unary operation.
    + +

    Member types

    + + + + + + + + + + + + + + + + + + + +
    Member typeDescription
    expression_typeType of the expression which is E.
    tensor_typeReference type which is T.
    unary_operationType of the unary operation which is OP.
    + +

    Public Member Functions

    + + + + + + + + + + + +
    MemberDescription
    decltype(auto) operator()(std::size_t i) const Returns a const reference to the i-th element of the expression.
    + +
    +

    Copyright (©) 2018 Cem Bassoy
    + Use, modification and distribution are subject to the + Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt + or copy at + http://www.boost.org/LICENSE_1_0.txt + ). +

    + + + diff --git a/doc/tensor/tensor_index.html b/doc/tensor/tensor_index.html new file mode 100644 index 000000000..1e4ec4cd7 --- /dev/null +++ b/doc/tensor/tensor_index.html @@ -0,0 +1,262 @@ + + + + + + + + + + + +Shape + + +

    Tensor Index

    +
    +

    tensor_index<value_t, storage_t, array_t, N>

    +

    Description

    +

    The template class tensor_index decorates the tensor template class with indices for tensor contraction.

    + +

    Example

    +
    +#include <boost/numeric/ublas/tensor/einstein.hpp>
    +
    +int main () {
    +    using namespace boost::numeric::ublas;
    +    shape s{4,3,2};
    +    for (auto i = 0u; i < s.size(); ++i) {
    +        std::cout << s.at(i) << std::endl;
    +    }
    +}
    +
    +

    Definition

    +

    Defined in the header tensor/tensor_einstein.hpp.

    + +

    Public base classes

    +

    None.

    + + + +

    Template parameters

    + + + + + + + + + + + + + + + + + + + + + + + + +
    ParameterDescription
    value_tThe type of object stored in the tensor.
    format_tStorage organization of the tensor.
    storage_tThe type of the storage array of the tensor.
    NNumber of indices provided.
    + + + + + +
    +

    +Copyright (©) 2018 Cem Bassoy
    + Use, modification and distribution are subject to the + Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt + or copy at + http://www.boost.org/LICENSE_1_0.txt + ). +

    + + + diff --git a/doc/types_overview.html b/doc/types_overview.html index b68a7ce05..770a139bd 100644 --- a/doc/types_overview.html +++ b/doc/types_overview.html @@ -12,7 +12,7 @@ Types Overview -

    Overview of Matrix- and Vector-Types

    +

    Overview of Tensor, Matrix- and Vector Types

    @@ -21,6 +21,7 @@

    Overview of Matrix- and Ve
    Vector Proxies
    Matrices
    Matrix Proxies
    +
    Tensors
    Special Storage Layouts

    @@ -31,15 +32,15 @@

    Notation

    T is the data type. For general linear algebra operations this will be a real type e.g. double, ... F -is the orientation type (functor), either -row_major or column_major +is the orientation type, either +row_major or column_major for matrices and first_order or last_order for tensors A, IA, TA is an array storage type, e.g. std::vector, bounded_array, unbounded_array, ... TRI is a triangular functor: lower, unit_lower, strict_lower, upper, unit_upper, strict_upper -M, N +M, N, K are unsigned integer sizes (std::size_t) IB @@ -49,6 +50,8 @@

    Notation

    is any vector type MAT is any matrix type +TEN +is any tensor type [...] denote optional arguments - for more details look at the section "storage layout". @@ -334,6 +337,31 @@

    Matrix Proxies

    +

    Tensors

    + + + + + + + + + + + + + + +
    DefinitionDescription
    tensor<T [, F, A]>
       t(size1, size2, ... );
    a dense matrix of values of type T of variable +size. A storage type A can be specified +which defaults to std::vector<T>. +The orientation type F defaults to +first_order. +Elements are constructed by A, which need not initialise their value.
    + + + +

    Special Storage Layouts

    diff --git a/examples/tensor/Jamfile.v2 b/examples/tensor/Jamfile.v2 index 652250041..35c006815 100644 --- a/examples/tensor/Jamfile.v2 +++ b/examples/tensor/Jamfile.v2 @@ -17,6 +17,7 @@ project boost-ublas-tensor-example msvc:"/W4" # == all ; -exe example01 : example01.cpp ; -exe example02 : example02.cpp ; -exe example03 : example03.cpp ; \ No newline at end of file +exe example_construction_access : example_construction_access.cpp ; +exe example_simple_expressions : example_simple_expressions.cpp ; +exe example_prod_expressions : example_prod_expressions.cpp ; +exe example_einstein_notation : example_einstein_notation.cpp ; \ No newline at end of file diff --git a/examples/tensor/example01.cpp b/examples/tensor/example_construction_access.cpp similarity index 100% rename from examples/tensor/example01.cpp rename to examples/tensor/example_construction_access.cpp diff --git a/examples/tensor/example_einstein_notation.cpp b/examples/tensor/example_einstein_notation.cpp new file mode 100644 index 000000000..0eed3f094 --- /dev/null +++ b/examples/tensor/example_einstein_notation.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + + +#include +#include +#include +#include + +int main() +{ + using namespace boost::numeric::ublas; + + using format_t = column_major; + using value_t = float; + using tensor_t = tensor; + using matrix_t = matrix; + using namespace boost::numeric::ublas::index; + + // Tensor-Vector-Multiplications - Including Transposition + { + + auto n = shape{3,4,2}; + auto A = tensor_t(n,1); + auto B1 = matrix_t(n[1],n[2],2); + auto v1 = tensor_t(shape{n[0],1},2); + auto v2 = tensor_t(shape{n[1],1},2); +// auto v3 = tensor_t(shape{n[2],1},2); + + // C1(j,k) = B1(j,k) + A(i,j,k)*v1(i); + // tensor_t C1 = B1 + prod(A,vector_t(n[0],1),1); +// tensor_t C1 = B1 + A(_i,_,_) * v1(_i,_); + + // C2(i,k) = A(i,j,k)*v2(j) + 4; + //tensor_t C2 = prod(A,vector_t(n[1],1),2) + 4; +// tensor_t C2 = A(_,_i,_) * v2(_i,_) + 4; + + // not yet implemented! + // C3() = A(i,j,k)*T1(i)*T2(j)*T2(k); + // tensor_t C3 = prod(prod(prod(A,v1,1),v2,1),v3,1); + // tensor_t C3 = A(_i,_j,_k) * v1(_i,_) * v2(_j,_) * v3(_k,_); + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C1(j,k) = B1(j,k) + A(i,j,k)*v1(i);" << std::endl << std::endl; +// std::cout << "C1=" << C1 << ";" << std::endl << std::endl; + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C2(i,k) = A(i,j,k)*v2(j) + 4;" << std::endl << std::endl; +// std::cout << "C2=" << C2 << ";" << std::endl << std::endl; + + } + + + // Tensor-Matrix-Multiplications - Including Transposition + { + auto n = shape{3,4,2}; + auto m = 5u; + auto A = tensor_t(n,2); + auto B = tensor_t(shape{n[1],n[2],m},2); + auto B1 = tensor_t(shape{m,n[0]},1); + auto B2 = tensor_t(shape{m,n[1]},1); + + + // C1(l,j,k) = B(j,k,l) + A(i,j,k)*B1(l,i); + // tensor_t C1 = B + prod(A,B1,1); +// tensor_t C1 = B + A(_i,_,_) * B1(_,_i); + + // C2(i,l,k) = A(i,j,k)*B2(l,j) + 4; + // tensor_t C2 = prod(A,B2) + 4; +// tensor_t C2 = A(_,_j,_) * B2(_,_j) + 4; + + // C3(i,l1,l2) = A(i,j,k)*T1(l1,j)*T2(l2,k); + // not yet implemented. + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C1(l,j,k) = B(j,k,l) + A(i,j,k)*B1(l,i);" << std::endl << std::endl; +// std::cout << "C1=" << C1 << ";" << std::endl << std::endl; + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C2(i,l,k) = A(i,j,k)*B2(l,j) + 4;" << std::endl << std::endl; +// std::cout << "C2=" << C2 << ";" << std::endl << std::endl; + +// // formatted output +// std::cout << "% --------------------------- " << std::endl; +// std::cout << "% --------------------------- " << std::endl << std::endl; +// std::cout << "% C3(i,l1,l2) = A(i,j,k)*T1(l1,j)*T2(l2,k);" << std::endl << std::endl; +// std::cout << "C3=" << C3 << ";" << std::endl << std::endl; + } + + + // Tensor-Tensor-Multiplications Including Transposition + { + auto na = shape{3,4,5}; + auto nb = shape{4,6,3,2}; + auto A = tensor_t(na,2); + auto B = tensor_t(nb,3); + auto T1 = tensor_t(shape{na[2],na[2]},2); + auto T2 = tensor_t(shape{na[2],nb[1],nb[3]},2); + + + // C1(j,l) = T1(j,l) + A(i,j,k)*A(i,j,l) + 5; + // tensor_t C1 = T1 + prod(A,A,perm_t{1,2}) + 5; +// tensor_t C1 = T1 + A(_i,_j,_m)*A(_i,_j,_l) + 5; + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C1(k,l) = T1(k,l) + A(i,j,k)*A(i,j,l) + 5;" << std::endl << std::endl; +// std::cout << "C1=" << C1 << ";" << std::endl << std::endl; + + + // C2(k,l,m) = T2(k,l,m) + A(i,j,k)*B(j,l,i,m) + 5; + //tensor_t C2 = T2 + prod(A,B,perm_t{1,2},perm_t{3,1}) + 5; +// tensor_t C2 = T2 + A(_i,_j,_k)*B(_j,_l,_i,_m) + 5; + + // formatted output + std::cout << "% --------------------------- " << std::endl; + std::cout << "% --------------------------- " << std::endl << std::endl; + std::cout << "% C2(k,l,m) = T2(k,l,m) + A(i,j,k)*B(j,l,i,m) + 5;" << std::endl << std::endl; +// std::cout << "C2=" << C2 << ";" << std::endl << std::endl; + + } +} diff --git a/examples/tensor/example03.cpp b/examples/tensor/example_prod_expressions.cpp similarity index 100% rename from examples/tensor/example03.cpp rename to examples/tensor/example_prod_expressions.cpp diff --git a/examples/tensor/example02.cpp b/examples/tensor/example_simple_expressions.cpp similarity index 100% rename from examples/tensor/example02.cpp rename to examples/tensor/example_simple_expressions.cpp diff --git a/include/boost/numeric/ublas/tensor.hpp b/include/boost/numeric/ublas/tensor.hpp index 06aaf6966..d3d38cf77 100644 --- a/include/boost/numeric/ublas/tensor.hpp +++ b/include/boost/numeric/ublas/tensor.hpp @@ -1,4 +1,3 @@ -// // Copyright (c) 2018 // Cem Bassoy // @@ -7,15 +6,16 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. /// \file tensor.hpp Definition for the class vector and its derivative -#ifndef _BOOST_UBLAS_TENSOR_ -#define _BOOST_UBLAS_TENSOR_ +#ifndef BOOST_NUMERIC_UBLAS_TENSOR +#define BOOST_NUMERIC_UBLAS_TENSOR +#if __cplusplus >= 201703L #include "tensor/functions.hpp" #include "tensor/operators_arithmetic.hpp" @@ -25,5 +25,6 @@ #include "tensor/ostream.hpp" #include "tensor/tensor.hpp" +#endif #endif diff --git a/include/boost/numeric/ublas/tensor/algorithm.hpp b/include/boost/numeric/ublas/tensor/algorithm.hpp new file mode 100644 index 000000000..8eea14135 --- /dev/null +++ b/include/boost/numeric/ublas/tensor/algorithm.hpp @@ -0,0 +1,680 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + + + +#ifndef _BOOST_UBLAS_TENSOR_ALGORITHM_ +#define _BOOST_UBLAS_TENSOR_ALGORITHM_ + +#include + +namespace boost { namespace numeric { namespace ublas { +struct first_order; +}}} + + +namespace boost { namespace numeric { namespace ublas { namespace detail { + +template +struct recursion +{ + static constexpr bool is_first_order = std::is_same_v; + + static constexpr inline auto cmpr(const std::size_t r, const std::size_t p) + { + if constexpr (is_first_order) return r > 0; + else return r < p; + } + + + static constexpr inline auto nextr(const std::size_t r) + { + if constexpr (is_first_order) return r - 1; + else return r + 1; + } + + static constexpr inline auto lastr(const std::size_t p) + { + if constexpr (is_first_order) return 0; + else return p-1; + } + + + template + static void run (const std::size_t p, + const std::size_t r, + const size_type *const n, + const size_type *const wa, + const size_type *const wc, + const value_type* a, + value_type *c, + unary_op op) + { + if(cmpr(r,p)) + for(auto i = 0ul; i < n[r]; ++i, a+=wa[r], c+=wc[r] ) + run(p, nextr(r), n, wa, wc, a, c, op); + else + for(auto i = 0ul; i < n[0]; ++i, ++a, ++c ) + op(*c,*a); + } +}; + +}}}} + + + +namespace boost { namespace numeric { namespace ublas { + +template +void copy(size_type const p, + size_type const*const n, + size_type const*const wa, + size_type const*const wc, + value_type const* a, + value_type * c, + layout_type l = layout_type() ) +{ + detail::recursion::run( p, p-1, n, wa, wc, a, c, [](value_type& c, value_type const& a){c = a;}); +} + +}}} + + + + + + +template +void +ttm_recursion_notzero( + const size_t m, size_t r, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + + if(r == m) { + ttm_recursion_notzero(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); + } + + + else if(r == 0){ + for(size_t i0 = 0u; i0 < nc[0]; c += wc[0], a += wa[0], ++i0) { + + auto cm = c; + auto b0 = b; + + // r == m + for(size_t i0 = 0u; i0 < nc[m]; cm += wc[m], b0 += wb[0], ++i0){ + + auto am = a; + auto b1 = b0; + + for(size_t i1 = 0u; i1 < nb[1]; am += wa[m], b1 += wb[1], ++i1){ + *cm += *am * *b1; + } + } + } + } + + else{ + for(size_t i = 0u; i < na[r]; c += wc[r], a += wa[r], ++i) + ttm_recursion_notzero(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); + } +} + + + + + + + + +template +void +ttm_recursion_zero( + size_t r, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + + if(r > 1){ + for(size_t i = 0u; i < na[r]; c += wc[r], a += wa[r], ++i) + ttm_recursion_zero(r-1, c, nc, wc, a, na, wa, b, nb, wb); + } + else{ + for(size_t i1 = 0u; i1 < nc[1]; c += wc[1], a += wa[1], ++i1) { + auto cm = c; + auto b0 = b; + // r == m == 0 + for(size_t i0 = 0u; i0 < nc[0]; cm += wc[0], b0 += wb[0], ++i0){ + + auto am = a; + auto b1 = b0; + for(size_t i1 = 0u; i1 < nb[1]; am += wa[0], b1 += wb[1], ++i1){ + + *cm += *am * *b1; + } + } + } + } +} + + +template +typename std::remove_cv::type>::type +inner_recursive( const size_t r, const size_t* n, pointer_t_a a, const size_t* wa, pointer_t_b b, const size_t* wb) +{ + using value_t = typename std::remove_cv::type>::type; + using value_t_b = typename std::remove_cv::type>::type; + static_assert(std::is_same::value, "static assert in inner_recursive: both pointer types must point to the same type."); + + value_t sum = value_t(); + + if(r == 0){ + for(size_t i0 = 0u; i0 < n[0]; a += wa[0], b += wb[0], ++i0) + sum += *a * *b; + } + else{ + for(size_t ir = 0u; ir < n[r]; a += wa[r], b += wb[r], ++ir) + sum += inner_recursive(r-1, n, a, wa, b, wb); + } + return sum; +} + + +template +void +outer_2x2( + size_t const pa, + size_t const rc, pointer_t_c c, const size_t* , const size_t* wc, + size_t const ra, pointer_t_a a, const size_t* na, const size_t* wa, + size_t const rb, pointer_t_b b, const size_t* nb, const size_t* wb) +{ + assert(rc == 3); + assert(ra == 1); + assert(rb == 1); + + for(size_t ib1 = 0u; ib1 < nb[1]; b += wb[1], c += wc[pa+1], ++ib1) + { + auto c2 = c; + auto b0 = b; + for(size_t ib0 = 0u; ib0 < nb[0]; b0 += wb[0], c2 += wc[pa], ++ib0) + { + const auto b = *b0; + auto c1 = c2; + auto a1 = a; + for(size_t ia1 = 0u; ia1 < na[1]; a1 += wa[1], c1 += wc[1], ++ia1) + { + auto a0 = a1; + auto c0 = c1; + for(size_t ia0 = 0u; ia0 < na[0]; a0 += wa[0], c0 += wc[0], ++ia0){ + *c0 = *a0 * b; + } + } + } + } +} + +template +void +outer_recursion( + size_t const pa, + size_t const rc, pointer_t_c c, const size_t* nc, const size_t* wc, + size_t const ra, pointer_t_a a, const size_t* na, const size_t* wa, + size_t const rb, pointer_t_b b, const size_t* nb, const size_t* wb) +{ + if(rb > 1) // ra > 1 && + { + for(size_t ib = 0u; ib < nb[rb]; b += wb[rb], c += wc[rc], ++ib) + outer_recursion(pa, rc-1, c, nc, wc, ra, a, na, wa, rb-1, b, nb, wb); + } + else if(ra > 1) // && rb == 1 + { + for(size_t ia = 0u; ia < na[ra]; a += wa[ra], c += wc[ra], ++ia) + outer_recursion(pa, rc-1, c, nc, wc, ra-1, a, na, wa, rb, b, nb, wb); + } + else + { + assert(ra == 1 && rb == 1 && rc == 3); + outer_2x2(pa, rc, c, nc, wc, ra, a, na, wa, rb, b, nb, wb); + } +} + + +template +void +ttt_recursion( + size_t k, size_t const ar, size_t br, size_t const m, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + if(k < ar) + { + assert(nc[k] == na[k]); + for(size_t ic = 0u; ic < nc[k]; a += wa[k], c += wc[k], ++ic) + ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); + } + else if(k < ar+br) + { + assert(nc[k] == nb[k-ar]); + for(size_t ic = 0u; ic < nc[k]; b += wb[k-ar], c += wc[k], ++ic) + ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); + } + else if(k < ar+br+m-1) + { + assert(na[k-br] == nb[k-ar]); + for(size_t ia = 0u; ia < na[k-br]; a += wa[k-br], b += wb[k-ar], ++ia) + ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); + } + else + { + assert(na[k-br] == nb[k-ar]); + for(size_t ia = 0u; ia < na[k-br]; a += wa[k-br], b += wb[k-ar], ++ia) + *c += *a * *b; + } +} + + +} // namespace detail +} // namespace ublas +} // namespace numeric +} // namespace boost + + +namespace boost { +namespace numeric { +namespace ublas { + +/* +template +void +transpose(size_t p, const size_t* tau, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa) +{ + if(c == nullptr || a == nullptr) + throw std::length_error("Error in fhg::transpose(...) : data pointers shall not be null pointers."); + + if(nc == nullptr || na == nullptr) + throw std::length_error("Error in fhg::transpose(...) : extent pointers shall not be null pointers."); + + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in fhg::transpose(...) : stride pointers shall not be null pointers."); + + if(tau == nullptr) + throw std::length_error("Error in fhg::transpose(...) : transpose permutation pointer shall not be a null pointer."); + + if(p < 2) + throw std::length_error("Error in fhg::transpose(...) : rank cannot be less than 2."); + + + // compute extents of C + for(size_t i = 0u; i < p; ++i) + if( nc[i] != na[tau[i]-1] ) + throw std::length_error("Error in fhg::transpose(...) : extents of left and right hand side tensor do not match."); + + size_t* vc = new size_t[p]; + for(size_t i = 0u; i < p; ++i) + vc[tau[i]-1] = wc[i]; + + if( std::equal(vc, vc+p, wa) ){ + const size_t nna = std::accumulate(na, na+p, 1ul, std::multiplies()); + std::copy(a,a+nna,c); + } + else{ + ::fhg::copy_pointer(p, na, c, vc, a, wa); + } + + + delete[] vc; +} +*/ + + + +/* +template +void +transpose(size_t p, const size_t* tau, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa) +{ + if(c == nullptr || a == nullptr) + throw std::length_error("Error in fhg::transpose(...) : data pointers shall not be null pointers."); + + if(nc == nullptr || na == nullptr) + throw std::length_error("Error in fhg::transpose(...) : extent pointers shall not be null pointers."); + + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in fhg::transpose(...) : stride pointers shall not be null pointers."); + + if(tau == nullptr) + throw std::length_error("Error in fhg::transpose(...) : transpose permutation pointer shall not be a null pointer."); + + if(p < 2) + throw std::length_error("Error in fhg::transpose(...) : rank cannot be less than 2."); + + + // compute extents of C + for(size_t i = 0u; i < p; ++i) + if( nc[i] != na[tau[i]-1] ) + throw std::length_error("Error in fhg::transpose(...) : extents of left and right hand side tensor do not match."); + + size_t* vc = new size_t[p]; + for(size_t i = 0u; i < p; ++i) + vc[tau[i]-1] = wc[i]; + + if( std::equal(vc, vc+p, wa) ){ + const size_t nna = std::accumulate(na, na+p, 1ul, std::multiplies()); + std::copy(a,a+nna,c); + } + else{ + ::fhg::copy_pointer(p, na, c, vc, a, wa); + } + + + delete[] vc; +} +*/ + + +template +void +tensor_times_vector(size_t m, size_t p, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* /*wb*/) +{ + + if( p < m ) + throw std::length_error("pointer_t_cError in tensor times vector function. Rank must be greater equal the modus."); + + if( p == 0) + throw std::length_error("Error intensor times vector function. Rank must be greater than zero."); + + if(c == nullptr || a == nullptr || b == nullptr) + throw std::length_error("Error in tensor times vector function. Pointers shall not be null pointers."); + + for(size_t i = 0; i < m-1; ++i){ + if(na[i] != nc[i]) + throw std::length_error("Error in tensor times vector function. Extents (except of dimension mode) of A and C must be equal."); + } + + for(size_t i = m; i < p; ++i){ + if(na[i] != nc[i-1]) + throw std::length_error("Error in tensor times vector function. Extents (except of dimension mode) of A and C must be equal."); + } + + const auto max = std::max(nb[0], nb[1]); + if( na[m-1] != max) + throw std::length_error("Error in tensor times vector function. Extent of dimension mode of A and b must be equal."); + + + if((m != 1) && (p > 2)) + detail::ttv_recursion_notzero(m-1, p-1, p-2, c, nc, wc, a, na, wa, b); + else if ((m == 1) && (p > 2)) + detail::ttv_recursion_zero(p-1, c, nc, wc, a, na, wa, b); + else + detail::mtv(m-1, c, nc, wc, a, na, wa, b); + +} + +template +void +tensor_times_matrix(const size_t m, const size_t p, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, const size_t* taua, + pointer_t_b b, const size_t* nb, const size_t* wb, const size_t* taub) +{ + if( p < m ) + throw std::length_error("Error in tensor times matrix function. Rank must be greater equal the modus."); + + if( p == 0) + throw std::length_error("Error in tensor times matrix function. Rank must be greater than zero."); + + if(c == nullptr || a == nullptr || b == nullptr) + throw std::length_error("Error in tensor times matrix function. Pointers shall not be null pointers."); + + for(size_t i = 0; i < m-1; ++i){ + if(na[taua[i]-1] != nc[i]) + throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); + } + + for(size_t i = m; i < p; ++i){ + if(na[taua[i]-1] != nc[i]) + throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); + } + + if(na[taua[m-1]-1] != nb[taub[1]-1]) + throw std::length_error("Error in tensor times matrix function. 2nd Extent of B and M-th Extent of A must be the equal."); + + if(nc[m-1] != nb[taub[0]-1]) + throw std::length_error("Error in tensor times matrix function. 1nd Extent of B and M-th Extent of C must be the equal."); + + + // need to compute the inverse of the transposition tuple tau + size_t* taua_1 = new size_t[p]; + size_t* taub_1 = new size_t[2]; + for(auto i = 0u; i < p; ++i){ + taua_1[taua[i]-1] = i+1; + } + for(auto i = 0u; i < 2; ++i){ + taub_1[taub[i]-1] = i+1; + } + + //compute v_a from w_a directly + size_t* va = new size_t[p]; + size_t* vb = new size_t[2]; +// size_t va[p], vb[2]; + for(size_t i = 0u; i < p; ++i){ + va[taua_1[i]-1] = wa[i]; + } + for(size_t i = 0u; i < 2; ++i){ + vb[taub_1[i]-1] = wb[i]; + } + + delete[] taua_1; + delete[] taub_1; + + if(m != 1) { + detail::ttm_recursion_notzero(m-1, p-1, c, nc, wc, a, na, va, b, nb, vb); + } + else { + detail::ttm_recursion_zero(p-1, c, nc, wc, a, na, va, b, nb, vb); + } + + delete[] va; + delete[] vb; +} + + + + +template +void +tensor_times_matrix(const size_t m, const size_t p, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + + static_assert( (std::is_pointer::value && std::is_pointer::value) && std::is_pointer::value, + "Static error at tensor_times_matrix function: argument types for pointers must be pointer types."); + + if( p < m ) + throw std::length_error("Error in tensor times matrix function. Rank must be greater equal the modus."); + + if( p == 0) + throw std::length_error("Error in tensor times matrix function. Rank must be greater than zero."); + + if(c == nullptr || a == nullptr || b == nullptr) + throw std::length_error("Error in tensor times matrix function. Pointers shall not be null pointers."); + + for(size_t i = 0; i < m-1; ++i){ + if(na[i] != nc[i]) + throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); + } + + for(size_t i = m; i < p; ++i){ + if(na[i] != nc[i]) + throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); + } + + if(na[m-1] != nb[1]) + throw std::length_error("Error in tensor times matrix function. 2nd Extent of B and M-th Extent of A must be the equal."); + + if(nc[m-1] != nb[0]) + throw std::length_error("Error in tensor times matrix function. 1nd Extent of B and M-th Extent of C must be the equal."); + + if(m != 1) + detail::ttm_recursion_notzero(m-1, p-1, c, nc, wc, a, na, wa, b, nb, wb); + else + detail::ttm_recursion_zero(p-1, c, nc, wc, a, na, wa, b, nb, wb); + +} + + + + + +template +typename std::remove_cv::type>::type +inner(const size_t p, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* /*nb*/, const size_t* wb) +{ + static_assert( std::is_pointer::value && std::is_pointer::value, + "Static error at inner function: argument types for pointers must be pointer types."); + + if(p<2) + throw std::length_error("Error when performing inner product: Rank must be greater than zero."); + + if(a == nullptr || b == nullptr) + throw std::length_error("Error when performing inner product: Pointers shall not be null pointers."); + + return detail::inner_recursive(p-1, na, a, wa, b, wb); + +} + + + + +template +void +outer(size_t pc, size_t pa, size_t pb, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + + if(pa < 2 || pb < 2) + throw std::length_error("Error when performing outer product: number of extents of A and B must be equal or greater than two."); + + if((pa + pb) != pc) + throw std::length_error("Error when performing outer product: number of extents of A plus B must be equal to the number of extents of C."); + + if(a == nullptr || b == nullptr || c == nullptr) + { + throw std::length_error("Error when performing outer product: Pointers shall not be null pointers."); + } + + + detail::outer_recursion(pa, pc-1, c, nc, wc, pa-1, a, na, wa, pb-1, b, nb, wb); + +} + + +template +void +tensor_times_tensor( + const size_t pc, const size_t pa, const size_t pb, + const size_t m, const size_t ar, const size_t br, + const size_t* phia, const size_t* phib, + pointer_t_c c, const size_t* nc, const size_t* wc, + pointer_t_a a, const size_t* na, const size_t* wa, + pointer_t_b b, const size_t* nb, const size_t* wb) +{ + +// const auto pc = nc.size(); +// const auto pa = na.size(); +// const auto pb = nb.size(); + + if(pa < 2 || pb < 2 || pc < 2) + throw std::length_error("Error when performing tensor tensor product: number of extents of A, B and C must be equal or greater than two."); + +// if(ar+m != phia.size()) +// throw std::length_error("Error when performing tensor tensor product: length of permutation tuple of A must be equal to r + m."); + +// if(ar+m != na.size()) +// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of A must be equal to r + m."); + +// if(ar+m != wa.size()) +// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of A must be equal to r + m."); + +// if(br+m != phib.size()) +// throw std::length_error("Error when performing tensor tensor product: length of permutation tuple of B must be equal to s + m."); + +// if(br+m != nb.size()) +// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of B must be equal to s + m."); + +// if(br+m != wb.size()) +// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of B must be equal to s + m."); + +// if(ar+br != nc.size() && ar!=0 && br!=0) +// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of C must be equal to r + s."); + +// if(ar+br != wc.size() && ar!=0 && br!=0) +// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of C must be equal to r + s."); + + if(a == nullptr || b == nullptr || c == nullptr) + {throw std::length_error("Error when performing tensor tensor product: Pointers shall not be null pointers.");} + + size_t* na_ = new size_t[pa]; + size_t* nb_ = new size_t[pb]; + size_t* wa_ = new size_t[pa]; + size_t* wb_ = new size_t[pb]; +// size_t na_[pa], nb_[pb]; +// size_t wa_[pa], wb_[pb]; + + for(size_t k = 0; k < ar; ++k){ + na_[k] = na[phia[k]-1]; + wa_[k] = wa[phia[k]-1]; + } + + for(size_t k = 0; k < br; ++k){ + nb_[k] = nb[phib[k]-1]; + wb_[k] = wb[phib[k]-1]; + } + + for(size_t k = 0; k < m; ++k){ + na_[k+ar] = na[phia[k+ar]-1]; + wa_[k+ar] = wa[phia[k+ar]-1]; + nb_[k+br] = nb[phib[k+br]-1]; + wb_[k+br] = wb[phib[k+br]-1]; + } + + detail::ttt_recursion(0, ar, br, m, c, nc, wc, a, na_, wa_, b, nb_, wb_); + + delete[] na_; + delete[] nb_; + delete[] wa_; + delete[] wb_; + +} + + + + + +#endif diff --git a/include/boost/numeric/ublas/tensor/algorithms.hpp b/include/boost/numeric/ublas/tensor/algorithms.hpp index 125e7e6bb..1b4fcb04e 100644 --- a/include/boost/numeric/ublas/tensor/algorithms.hpp +++ b/include/boost/numeric/ublas/tensor/algorithms.hpp @@ -16,146 +16,211 @@ #include #include +#include namespace boost { namespace numeric { namespace ublas { -namespace detail { -namespace recursive { + /** @brief Copies a tensor to another tensor with different layouts * * Implements C[i1,i2,...,ip] = A[i1,i2,...,ip] * - * @note is used in function trans or for tensor views - * - * @param[in] r zero-based recursion level starting with r=p-1 - * @param[in] n pointer to the extents of input or output tensor - * @param[out] c pointer to the output tensor + * @param[in] p rank of input and output tensor + * @param[in] n pointer to the extents of input or output tensor of length p + * @param[in] pi pointer to a one-based permutation tuple of length p + * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c - * @param[in] a pointer to the first input tensor + * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a */ template -void copy(SizeType r, SizeType const*const n, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa) +void copy(const SizeType p, SizeType const*const n, + PointerOut c, SizeType const*const wc, + PointerIn a, SizeType const*const wa) { - if(r > 0) - for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d) - copy(r-1, n, c, wc, a, wa); - else - for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d) - *c = *a; + static_assert( std::is_pointer::value & std::is_pointer::value, + "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types."); + if( p == 0 ) + return; + + if(c == nullptr || a == nullptr) + throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); + + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); + + if(n == nullptr) + throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); + + + std::function lambda; + + lambda = [&lambda, n, wc, wa](SizeType r, PointerOut c, PointerIn a) + { + if(r > 0) + for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d) + lambda(r-1, c, a ); + else + for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d) + *c = *a; + }; + + lambda( p-1, c, a ); } -/** @brief Transposes a tensor - * - * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip] + +/** @brief Copies a tensor to another tensor with different layouts applying a unary operation * - * @note is used in function trans + * Implements C[i1,i2,...,ip] = op ( A[i1,i2,...,ip] ) * - * @param[in] r zero-based recursion level starting with r=p-1 - * @param[in] na pointer to the extents of input tensor a of length p + * @param[in] p rank of input and output tensor + * @param[in] n pointer to the extents of input or output tensor of length p * @param[in] pi pointer to a one-based permutation tuple of length p * @param[out] c pointer to the output tensor * @param[in] wc pointer to the strides of output tensor c * @param[in] a pointer to the input tensor * @param[in] wa pointer to the strides of input tensor a + * @param[in] op unary operation */ -template -void trans(SizeType const r, SizeType const*const n, SizeType const*const pi, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa) +template +void transform(const SizeType p, + SizeType const*const n, + PointerOut c, SizeType const*const wc, + PointerIn a, SizeType const*const wa, + UnaryOp op) { - if(r > 0){ - for(auto d = 0u; d < n[r]; c += wc[pi[r]-1], a += wa[r], ++d){ - trans(r-1, n, pi, c, wc, a, wa); - } - } - else{ - for(auto d = 0u; d < n[0]; c += wc[pi[0]-1], a += wa[0], ++d){ - *c = *a; - } - } + static_assert( std::is_pointer::value & std::is_pointer::value, + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); + if( p == 0 ) + return; + + if(c == nullptr || a == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + + if(n == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + + + std::function lambda; + + lambda = [&lambda, n, wc, wa, op](SizeType r, PointerOut c, PointerIn a) + { + if(r > 0) + for(auto d = 0u; d < n[r]; c += wc[r], a += wa[r], ++d) + lambda(r-1, c, a); + else + for(auto d = 0u; d < n[0]; c += wc[0], a += wa[0], ++d) + *c = op(*a); + }; + + lambda( p-1, c, a ); + } -/** @brief Transposes a tensor +/** @brief Performs a reduce operation with all elements of the tensor and an initial value * - * Implements C[tau[i1],tau[i2],...,tau[ip]] = A[i1,i2,...,ip] + * Implements k = sum_{i1,..,ip} A[i1,i2,...,ip] * - * @note is used in function trans - * - * @param[in] r zero-based recursion level starting with r=p-1 - * @param[in] na pointer to the extents of input tensor a of length p - * @param[in] pi pointer to a one-based permutation tuple of length p - * @param[out] c pointer to the output tensor - * @param[in] wc pointer to the strides of output tensor c - * @param[in] a pointer to the input tensor - * @param[in] wa pointer to the strides of input tensor a + * @param[in] r zero-based recursion level starting with r=p-1 + * @param[in] n pointer to the extents of input or output tensor + * @param[in] a pointer to the first input tensor + * @param[in] w pointer to the strides of input tensor a + * @param[in] k accumulated value */ -template -void trans(SizeType const r, SizeType const*const n, SizeType const*const pi, - std::complex* c, SizeType const*const wc, - std::complex* a, SizeType const*const wa) +template +ValueType accumulate(SizeType const p, SizeType const*const n, + PointerIn a, SizeType const*const w, + ValueType k) { - if(r > 0) - for(auto d = 0u; d < n[r]; c += wc[pi[r]-1], a += wa[r], ++d) - trans(r-1, n, pi, c, wc, a, wa); - else - for(auto d = 0u; d < n[0]; c += wc[pi[0]-1], a += wa[0], ++d) - *c = std::conj(*a); -} - + static_assert(std::is_pointer::value, + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); -} // recursive -} // detail -} // ublas -} // numeric -} // boost + if( p == 0 ) + return k; + if(a == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + if(w == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + if(n == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); -namespace boost { -namespace numeric { -namespace ublas { + std::function lambda; + lambda = [&lambda, n, w](SizeType r, PointerIn a, ValueType k) + { + if(r > 0u) + for(auto d = 0u; d < n[r]; a += w[r], ++d) + k = lambda(r-1, a, k); + else + for(auto d = 0u; d < n[0]; a += w[0], ++d) + k += *a; + return k; + }; + return lambda( p-1, a, k ); +} -/** @brief Copies a tensor to another tensor with different layouts +/** @brief Performs a reduce operation with all elements of the tensor and an initial value * - * Implements C[i1,i2,...,ip] = A[i1,i2,...,ip] + * Implements k = op ( k , A[i1,i2,...,ip] ), for all ir * - * @param[in] p rank of input and output tensor - * @param[in] n pointer to the extents of input or output tensor of length p - * @param[in] pi pointer to a one-based permutation tuple of length p - * @param[out] c pointer to the output tensor - * @param[in] wc pointer to the strides of output tensor c - * @param[in] a pointer to the input tensor - * @param[in] wa pointer to the strides of input tensor a + * @param[in] r zero-based recursion level starting with r=p-1 + * @param[in] n pointer to the extents of input or output tensor + * @param[in] a pointer to the first input tensor + * @param[in] w pointer to the strides of input tensor a + * @param[in] k accumulated value + * @param[in] op binary operation */ -template -void copy(const SizeType p, SizeType const*const n, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa) + +template +ValueType accumulate(SizeType const p, SizeType const*const n, + PointerIn a, SizeType const*const w, + ValueType k, BinaryOp op) { - static_assert( std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types."); + static_assert(std::is_pointer::value, + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); + + if( p == 0 ) - return; + return k; - if(c == nullptr || a == nullptr) - throw std::length_error("Error in boost::numeric::ublas::copy: Pointers shall not be null pointers."); + if(a == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); - detail::recursive::copy( p-1, n, c, wc, a, wa ); + if(w == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); -} + if(n == nullptr) + throw std::length_error("Error in boost::numeric::ublas::transform: Pointers shall not be null pointers."); + + + std::function lambda; + lambda = [&lambda, n, w, op](SizeType r, PointerIn a, ValueType k) + { + if(r > 0u) + for(auto d = 0u; d < n[r]; a += w[r], ++d) + k = lambda(r-1, a, k); + else + for(auto d = 0u; d < n[0]; a += w[0], ++d) + k = op ( k, *a ); + return k; + }; + + return lambda( p-1, a, k ); +} /** @brief Transposes a tensor * @@ -185,9 +250,34 @@ void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, return; if(c == nullptr || a == nullptr) + throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + if(na == nullptr) + throw std::runtime_error("Error in boost::numeric::ublas::trans: Pointers shall not be null."); + + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + if(na == nullptr) + throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + if(pi == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); - detail::recursive::trans( p-1, na, pi, c, wc, a, wa ); + + std::function lambda; + + lambda = [&lambda, na, wc, wa, pi](SizeType r, PointerOut c, PointerIn a) + { + if(r > 0) + for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d) + lambda(r-1, c, a); + else + for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d) + *c = *a; + }; + + lambda( p-1, c, a ); } @@ -207,23 +297,47 @@ void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, */ template -void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, - std::complex* c, SizeType const*const wc, - std::complex* a, SizeType const*const wa) +void trans( SizeType const p, + SizeType const*const na, + SizeType const*const pi, + std::complex* c, SizeType const*const wc, + std::complex* a, SizeType const*const wa) { - -// static_assert( std::is_pointer::value & std::is_pointer::value, -// "Static error in boost::numeric::ublas::trans: Argument types for pointers are not pointer types."); - if( p < 2) return; if(c == nullptr || a == nullptr) throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); - detail::recursive::trans( p-1, na, pi, c, wc, a, wa ); + if(wc == nullptr || wa == nullptr) + throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + if(na == nullptr) + throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + if(pi == nullptr) + throw std::length_error("Error in boost::numeric::ublas::trans: Pointers shall not be null pointers."); + + + std::function* c, std::complex* a)> lambda; + + lambda = [&lambda, na, wc, wa, pi](SizeType r, std::complex* c, std::complex* a) + { + if(r > 0) + for(auto d = 0u; d < na[r]; c += wc[pi[r]-1], a += wa[r], ++d) + lambda(r-1, c, a); + else + for(auto d = 0u; d < na[0]; c += wc[pi[0]-1], a += wa[0], ++d) + *c = std::conj(*a); + }; + + lambda( p-1, c, a ); + } + + + } } } diff --git a/include/boost/numeric/ublas/tensor/expression.hpp b/include/boost/numeric/ublas/tensor/expression.hpp index 01997d486..fd77f989a 100644 --- a/include/boost/numeric/ublas/tensor/expression.hpp +++ b/include/boost/numeric/ublas/tensor/expression.hpp @@ -40,20 +40,14 @@ namespace numeric { namespace ublas { namespace detail { -///** \brief Base class for Tensor Expression models -// * -// * it does not model the Tensor Expression concept but all derived types should. -// * The class defines a common base type and some common interface for all -// * statically derived Tensor Expression classes. -// * We implement the casts to the statically derived type. -// */ - -// \brief expression class for expression templates -// -// \note implements crtp - no use of virtual function calls -// -// \tparam T element type of matrices and scalars of the expression -// \tparam D derived type that can be matrices or generic lambda functions. Must support operator()(std::size_t i) +/** @\brief base class for tensor expressions + * + * \note implements crtp - no use of virtual function calls + * + * \tparam T type of the tensor + * \tparam E type of the derived expression (crtp) + * + **/ template struct tensor_expression : public ublas_expression @@ -62,19 +56,9 @@ struct tensor_expression using expression_type = E; using type_category = tensor_tag; using tensor_type = T; - using derived_type = ublas_expression; - - BOOST_UBLAS_INLINE - auto const& derived() const { return *static_cast (this); } BOOST_UBLAS_INLINE auto const& operator()() const { return *static_cast (this); } - BOOST_UBLAS_INLINE - auto & operator()() { return *static_cast< expression_type*> (this); } - - BOOST_UBLAS_INLINE - decltype(auto) operator()(std::size_t i) const { return static_cast(*this)(i); } - protected : explicit tensor_expression() = default; @@ -89,29 +73,26 @@ struct binary_tensor_expression { using self_type = binary_tensor_expression; using tensor_type = T; - + using binary_operation = OP; using expression_type_left = EL; using expression_type_right = ER; + using derived_type = tensor_expression ; using size_type = typename tensor_type::size_type; - explicit binary_tensor_expression(expression_type_left const& l, expression_type_right const& r, OP o) + explicit binary_tensor_expression(expression_type_left const& l, expression_type_right const& r, binary_operation o) : el(l) , er(r) , op(o) {} binary_tensor_expression() = delete; binary_tensor_expression(const binary_tensor_expression& l) = delete; - binary_tensor_expression(binary_tensor_expression&& l) = delete; - - BOOST_UBLAS_INLINE - const auto & derived_left() const { return *static_cast (this); } - BOOST_UBLAS_INLINE - const auto & derived_right() const { return *static_cast (this); } + binary_tensor_expression(binary_tensor_expression&& l) + : el(l.el), er(l.er), op(l.op) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(el(i), er(i)); } expression_type_left const& el; expression_type_right const& er; - OP op; + binary_operation op; }; /// @brief helper function to simply instantiation of lambda proxy class @@ -163,11 +144,8 @@ struct unary_tensor_expression explicit unary_tensor_expression(E const& ee, OP o) : e(ee) , op(o) {} unary_tensor_expression() = delete; unary_tensor_expression(const unary_tensor_expression& l) = delete; - unary_tensor_expression(unary_tensor_expression&& l) = delete; - - - BOOST_UBLAS_INLINE - const auto& derived() const { return *static_cast (this); } + unary_tensor_expression(unary_tensor_expression&& l) + : e(l.e), op(op.l) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(e(i)); } diff --git a/include/boost/numeric/ublas/tensor/expression_evaluation.hpp b/include/boost/numeric/ublas/tensor/expression_evaluation.hpp index e6f7d8a4b..75e0f9cb0 100644 --- a/include/boost/numeric/ublas/tensor/expression_evaluation.hpp +++ b/include/boost/numeric/ublas/tensor/expression_evaluation.hpp @@ -243,7 +243,7 @@ void eval(tensor_type& lhs, tensor_expression const& #pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) - lhs(i) = expr(i); + lhs(i) = expr()(i); } /** @brief Evaluates expression for a tensor @@ -263,7 +263,7 @@ void eval(tensor_type& lhs, tensor_expression const& #pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) - fn(lhs(i), expr(i)); + fn(lhs(i), expr()(i)); } diff --git a/include/boost/numeric/ublas/tensor/extents.hpp b/include/boost/numeric/ublas/tensor/extents.hpp index b2c474178..11bdc0ea5 100644 --- a/include/boost/numeric/ublas/tensor/extents.hpp +++ b/include/boost/numeric/ublas/tensor/extents.hpp @@ -278,7 +278,7 @@ class basic_extents } auto new_extent = basic_extents{}; - auto insert_iter = std::back_insert_iterator(new_extent._base); + auto insert_iter = std::back_insert_iterator(new_extent._base); std::remove_copy(this->_base.begin(), this->_base.end(), insert_iter ,value_type{1}); return new_extent; @@ -296,7 +296,7 @@ class basic_extents bool operator != (basic_extents const& b) const { - return _base != b._base; + return !( _base == b._base ); } const_iterator diff --git a/include/boost/numeric/ublas/tensor/functions.hpp b/include/boost/numeric/ublas/tensor/functions.hpp index b64de0374..8fa93e0f6 100644 --- a/include/boost/numeric/ublas/tensor/functions.hpp +++ b/include/boost/numeric/ublas/tensor/functions.hpp @@ -19,10 +19,12 @@ #include #include + #include "multiplication.hpp" #include "algorithms.hpp" - - +#include "expression.hpp" +#include "expression_evaluation.hpp" +#include "storage_traits.hpp" namespace boost { namespace numeric { @@ -60,9 +62,10 @@ auto prod(tensor const& a, vector const& b, const std::size_t m) using extents_type = typename tensor_type::extents_type; using ebase_type = typename extents_type::base_type; using value_type = typename tensor_type::value_type; + using size_type = typename extents_type::value_type; - auto const p = a.rank(); - + auto const p = std::size_t(a.rank()); + if( m == 0) throw std::length_error("Error in boost::numeric::ublas::prod: Contraction mode must be greater than zero."); @@ -79,7 +82,7 @@ auto prod(tensor const& a, vector const& b, const std::size_t m) throw std::length_error("Error in boost::numeric::ublas::prod: vector should not be empty."); - auto nc = ebase_type(std::max(p-1,2ul) ,1); + auto nc = ebase_type(std::max(p-1, size_type(2)) , size_type(1)); auto nb = ebase_type{b.size(),1}; @@ -186,11 +189,12 @@ auto prod(tensor const& a, tensor const& b, using tensor_type = tensor; using extents_type = typename tensor_type::extents_type; using value_type = typename tensor_type::value_type; + using size_type = typename extents_type::value_type; auto const pa = a.rank(); auto const pb = b.rank(); - auto const q = phia.size(); + auto const q = size_type(phia.size()); if(pa == 0ul) throw std::runtime_error("Error in ublas::prod: order of left-hand side tensor must be greater than 0."); @@ -225,7 +229,7 @@ auto prod(tensor const& a, tensor const& b, std::iota(phia1.begin(), phia1.end(), 1ul); std::iota(phib1.begin(), phib1.end(), 1ul); - std::vector nc( std::max ( r+s , 2ul ), 1ul ); + std::vector nc( std::max ( r+s , size_type(2) ), size_type(1) ); for(auto i = 0ul; i < phia.size(); ++i) * std::remove(phia1.begin(), phia1.end(), phia.at(i)) = phia.at(i); @@ -262,6 +266,11 @@ auto prod(tensor const& a, tensor const& b, return c; } +//template +//auto operator*( tensor_index const& lhs, tensor_index const& rhs) + + + /** @brief Computes the q-mode tensor-times-tensor product * @@ -332,7 +341,7 @@ auto outer_prod(tensor const& a, tensor const& b) using extents_type = typename tensor_type::extents_type; if( a.empty() || b.empty() ) - throw std::length_error("Error in boost::numeric::ublas::outer_prod: tensors should not be empty."); + throw std::runtime_error("Error in boost::numeric::ublas::outer_prod: tensors should not be empty."); auto nc = typename extents_type::base_type(a.rank() + b.rank()); for(auto i = 0u; i < a.rank(); ++i) @@ -370,7 +379,7 @@ auto trans(tensor const& a, std::vector const& tau) // using strides_type = typename tensor_type::strides_type; if( a.empty() ) - throw std::length_error("Error in boost::numeric::ublas::trans: tensor should not be empty."); + return tensor{}; auto const p = a.rank(); auto const& na = a.extents(); @@ -388,21 +397,159 @@ auto trans(tensor const& a, std::vector const& tau) c.data(), c.strides().data(), a.data(), a.strides().data()); - // auto wc_pi = typename strides_type::base_type (p); // for(auto i = 0u; i < p; ++i) // wc_pi.at(tau.at(i)-1) = c.strides().at(i); - //copy(a.rank(), - // a.extents().data(), - // c.data(), wc_pi.data(), - // a.data(), a.strides().data() ); +//copy(a.rank(), +// a.extents().data(), +// c.data(), wc_pi.data(), +// a.data(), a.strides().data() ); + + return c; +} + +/** @brief Computes the frobenius norm of a tensor expression + * + * @note evaluates the tensor expression and calls the accumulate function + * + * + * Implements the two-norm with + * k = sqrt( sum_(i1,...,ip) A(i1,...,ip)^2 ) + * + * @param[in] a tensor object of rank p + * @returns the frobenius norm of the tensor +*/ +//template +//auto norm(tensor const& a) +template +auto norm(detail::tensor_expression const& expr) +{ + + using tensor_type = typename detail::tensor_expression::tensor_type; + using value_type = typename tensor_type::value_type; + + auto a = tensor_type( expr ); + + if( a.empty() ) + throw std::runtime_error("Error in boost::numeric::ublas::norm: tensors should not be empty."); + + return std::sqrt( accumulate( a.order(), a.extents().data(), a.data(), a.strides().data(), value_type{}, + [](auto const& l, auto const& r){ return l + r*r; } ) ) ; +} + + + +/** @brief Extract the real component of tensor elements within a tensor expression + * + * @param[in] lhs tensor expression + * @returns unary tensor expression +*/ +template +auto real(detail::tensor_expression const& expr) { + return detail::make_unary_tensor_expression (expr(), [] (auto const& l) { return std::real( l ); } ); +} + +/** @brief Extract the real component of tensor elements within a tensor expression + * + * @param[in] lhs tensor expression + * @returns unary tensor expression +*/ +template +auto real(detail::tensor_expression,F,A>,D> const& expr) +{ + using tensor_complex_type = tensor,F,A>; + using tensor_type = tensor::template rebind>; + + if( detail::retrieve_extents( expr ).empty() ) + throw std::runtime_error("Error in boost::numeric::ublas::real: tensors should not be empty."); + + auto a = tensor_complex_type( expr ); + auto c = tensor_type( a.extents() ); + + std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::real(l) ; } ); return c; } +/** @brief Extract the imaginary component of tensor elements within a tensor expression + * + * @param[in] lhs tensor expression + * @returns unary tensor expression +*/ +template +auto imag(detail::tensor_expression const& lhs) { + return detail::make_unary_tensor_expression (lhs(), [] (auto const& l) { return std::imag( l ); } ); +} + + +/** @brief Extract the imag component of tensor elements within a tensor expression + * + * @param[in] lhs tensor expression + * @returns unary tensor expression +*/ +template +auto imag(detail::tensor_expression,F,A>,D> const& expr) +{ + using tensor_complex_type = tensor,F,A>; + using tensor_type = tensor::template rebind>; + + if( detail::retrieve_extents( expr ).empty() ) + throw std::runtime_error("Error in boost::numeric::ublas::real: tensors should not be empty."); + + auto a = tensor_complex_type( expr ); + auto c = tensor_type( a.extents() ); + + std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::imag(l) ; } ); + + return c; +} + +/** @brief Computes the complex conjugate component of tensor elements within a tensor expression + * + * @param[in] expr tensor expression + * @returns complex tensor +*/ +template +auto conj(detail::tensor_expression const& expr) +{ + using tensor_type = T; + using value_type = typename tensor_type::value_type; + using layout_type = typename tensor_type::layout_type; + using array_type = typename tensor_type::array_type; + + using new_value_type = std::complex; + using new_array_type = typename storage_traits::template rebind; + + using tensor_complex_type = tensor; + + if( detail::retrieve_extents( expr ).empty() ) + throw std::runtime_error("Error in boost::numeric::ublas::conj: tensors should not be empty."); + + auto a = tensor_type( expr ); + auto c = tensor_complex_type( a.extents() ); + + std::transform( a.begin(), a.end(), c.begin(), [](auto const& l){ return std::conj(l) ; } ); + + return c; +} + + +/** @brief Computes the complex conjugate component of tensor elements within a tensor expression + * + * @param[in] lhs tensor expression + * @returns unary tensor expression +*/ +template +auto conj(detail::tensor_expression,F,A>,D> const& expr) +{ + return detail::make_unary_tensor_expression,F,A>> (expr(), [] (auto const& l) { return std::conj( l ); } ); +} + + + } } } diff --git a/include/boost/numeric/ublas/tensor/index.hpp b/include/boost/numeric/ublas/tensor/index.hpp new file mode 100644 index 000000000..336500008 --- /dev/null +++ b/include/boost/numeric/ublas/tensor/index.hpp @@ -0,0 +1,89 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + +#ifndef _BOOST_UBLAS_TENSOR_INDEX_HPP_ +#define _BOOST_UBLAS_TENSOR_INDEX_HPP_ + + +#include +#include +#include + +namespace boost { +namespace numeric { +namespace ublas { +namespace index { + +/** @brief Proxy template class for the einstein summation notation + * + * @note index::index_type for 0<=K<=16 is used in tensor::operator() + * + * @tparam I wrapped integer +*/ +template +struct index_type +{ + static constexpr std::size_t value = I; + + constexpr bool operator == (std::size_t other) const { return value == other; } + constexpr bool operator != (std::size_t other) const { return value != other; } + + template + constexpr bool operator == (index_type /*other*/) const { return I==K; } + template + constexpr bool operator != (index_type /*other*/) const { return I!=K; } + + constexpr bool operator == (index_type /*other*/) const { return true; } + constexpr bool operator != (index_type /*other*/) const { return false; } + + constexpr std::size_t operator()() const { return I; } +}; + +/** @brief Proxy classes for the einstein summation notation + * + * @note index::_a ... index::_z is used in tensor::operator() +*/ + +static constexpr index_type< 0> _; +static constexpr index_type< 1> _a; +static constexpr index_type< 2> _b; +static constexpr index_type< 3> _c; +static constexpr index_type< 4> _d; +static constexpr index_type< 5> _e; +static constexpr index_type< 6> _f; +static constexpr index_type< 7> _g; +static constexpr index_type< 8> _h; +static constexpr index_type< 9> _i; +static constexpr index_type<10> _j; +static constexpr index_type<11> _k; +static constexpr index_type<12> _l; +static constexpr index_type<13> _m; +static constexpr index_type<14> _n; +static constexpr index_type<15> _o; +static constexpr index_type<16> _p; +static constexpr index_type<17> _q; +static constexpr index_type<18> _r; +static constexpr index_type<19> _s; +static constexpr index_type<20> _t; +static constexpr index_type<21> _u; +static constexpr index_type<22> _v; +static constexpr index_type<23> _w; +static constexpr index_type<24> _x; +static constexpr index_type<25> _y; +static constexpr index_type<26> _z; + +} // namespace indices + +} +} +} + +#endif // _BOOST_UBLAS_TENSOR_INDEX_HPP_ diff --git a/include/boost/numeric/ublas/tensor/multi_index.hpp b/include/boost/numeric/ublas/tensor/multi_index.hpp new file mode 100644 index 000000000..7b85b56ed --- /dev/null +++ b/include/boost/numeric/ublas/tensor/multi_index.hpp @@ -0,0 +1,110 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + +#ifndef _BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP_ +#define _BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP_ + + +#include +#include +#include + +#include "multi_index_utility.hpp" + +namespace boost { +namespace numeric { +namespace ublas { +namespace index { + +template +struct index_type; + +} // namespace indices +} +} +} + + +namespace boost { +namespace numeric { +namespace ublas { + +/** @brief Proxy class for the einstein summation notation + * + * Denotes an array of index_type types ::_a for 0<=K<=16 is used in tensor::operator() +*/ +template +class multi_index +{ +public: + multi_index() = delete; + + template + constexpr multi_index(index::index_type const& i, indexes ... is ) + : _base{i(), is()... } + { + static_assert( sizeof...(is)+1 == N, + "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." ); + + static_assert( valid_multi_index, indexes ...> >::value, + "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." ); + } + + multi_index(multi_index const& other) + : _base(other._base) + { + } + + multi_index& operator=(multi_index const& other) + { + this->_base = other._base; + return *this; + } + + ~multi_index() = default; + + auto const& base() const { return _base; } + constexpr auto size() const { return _base.size(); } + constexpr auto at(std::size_t i) const { return _base.at(i); } + constexpr auto operator[](std::size_t i) const { return _base.at(i); } + +private: + std::array _base; +}; + +template +constexpr auto get(multi_index const& m) { return std::get(m.base()); } + +template +auto array_to_vector(multi_index const& lhs, multi_index const& rhs) +{ + using vtype = std::vector; + + auto pair_of_vector = std::make_pair( vtype {}, vtype{} ); + + for(auto i = 0u; i < N; ++i) + for(auto j = 0u; j < M; ++j) + if ( lhs.at(i) == rhs.at(j) && lhs.at(i) != boost::numeric::ublas::index::_()) + pair_of_vector.first .push_back( i+1 ), + pair_of_vector.second.push_back( j+1 ); + + return pair_of_vector; +} + + + + + +} // namespace ublas +} // namespace numeric +} // namespace boost + +#endif // MULTI_INDEX_HPP diff --git a/include/boost/numeric/ublas/tensor/multi_index_utility.hpp b/include/boost/numeric/ublas/tensor/multi_index_utility.hpp new file mode 100644 index 000000000..d4a77355f --- /dev/null +++ b/include/boost/numeric/ublas/tensor/multi_index_utility.hpp @@ -0,0 +1,364 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + +#ifndef _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ +#define _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ + + +#include +#include + + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + + +template +struct has_index_impl; + +template +struct has_index_impl +{ + static constexpr bool value = itype_left::value == itype_right::value; +}; + +template +struct has_index_impl > +{ + static constexpr bool value = false; +}; + +template +struct has_index_impl > +{ + static constexpr bool value = has_index_impl::value; +}; + +template +struct has_index_impl > +{ + using next_type = has_index_impl>; + static constexpr bool value = has_index_impl::value || next_type::value; +}; +} // namespace detail + + + +/** @brief has_index is true if index occurs once or more in a multi-index + * + * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type + * + * @code auto has_index_value = has_index, std::tuple,index_type<1>> >::value; @endcode + * + * @tparam index_type type of index + * @tparam tuple_type type of std::tuple representing a multi-index +*/ +template +struct has_index +{ + static constexpr bool value = detail::has_index_impl,std::decay_t>::value; +}; + +} // namespace ublas +} // namespace numeric +} // namespace boost + +//////////////////////////////////////////////// +//////////////////////////////////////////////// + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + + +template +struct valid_multi_index_impl; + +template<> +struct valid_multi_index_impl> +{ + static constexpr bool value = true; +}; + +template +struct valid_multi_index_impl> +{ + static constexpr bool value = true; +}; + + +template +struct valid_multi_index_impl> +{ + using ttype = std::tuple; + using has_index_type = has_index; + + static constexpr bool is_index_zero = itype::value==0ul; + static constexpr bool has_index_value = has_index_type::value && !is_index_zero; + static constexpr bool value = !has_index_value && valid_multi_index_impl::value; +}; +} // namespace detail + +/** @brief valid_multi_index is true if indexes occur only once in a multi-index + * + * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type + * + * @code auto valid = valid_multi_index< std::tuple,index_type<1>> >::value; + * @endcode + * + * @tparam tuple_type type of std::tuple representing a multi-index +*/ +template +struct valid_multi_index +{ + static constexpr bool value = detail::valid_multi_index_impl>::value; +}; + +} // namespace ublas +} // namespace numeric +} // namespace boost + +//////////////////////////////////////////////// +//////////////////////////////////////////////// + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + +template +struct number_equal_indexes_impl; + +template +struct number_equal_indexes_impl < std::tuple<>, std::tuple> +{ + static constexpr unsigned value = 0; +}; + +template +struct number_equal_indexes_impl < std::tuple, std::tuple> +{ + using tuple_right = std::tuple; + using has_index_type = has_index; + + static constexpr bool is_index_zero = itype::value==0ul; + static constexpr bool has_index_value = has_index_type::value && !is_index_zero; + + using next_type = number_equal_indexes_impl< std::tuple, tuple_right >; + static constexpr unsigned v = has_index_value ? 1 : 0; + static constexpr unsigned value = v + next_type::value; +}; +} // namespace detail + + +/** @brief number_equal_indexes contains the number of equal indexes of two multi-indexes + * + * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type + * + * + * @code auto num = number_equal_indexes< + * std::tuple,index_type<1>>, + * std::tuple,index_type<3>> >::value; + * @endcode + * + * @tparam tuple_type_left type of left std::tuple representing a multi-index + * @tparam tuple_type_right type of right std::tuple representing a multi-index +*/ +template +struct number_equal_indexes +{ + static constexpr unsigned value = + detail::number_equal_indexes_impl< std::decay_t, std::decay_t>::value; +}; + +} // namespace ublas +} // namespace numeric +} // namespace boost + + +//////////////////////////////////////////////// +//////////////////////////////////////////////// + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + + +template +struct index_position_impl +{ + static constexpr auto is_same = std::is_same< std::decay_t, std::decay_t> >::value; + static constexpr auto value = is_same ? r : index_position_impl::value; +}; + + + +template +struct index_position_impl < m, m, itype, ttype> +{ + static constexpr auto value = std::tuple_size::value; +}; + +} // namespace detail + + + +/** @brief index_position contains the zero-based index position of an index type within a multi-index + * + * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type + * + * @code auto num = index_position< + * index_type<1>, + * std::tuple,index_type<1>> >::value; + * @endcode + * + * @returns value returns 0 and N-1 if index_type is found, N otherwise where N is tuple_size_v. + * + * @tparam index_type type of index + * @tparam tuple_type type of std::tuple that is searched for index +*/ +template +struct index_position +{ + static constexpr auto value = detail::index_position_impl<0ul,std::tuple_size::value,std::decay_t,std::decay_t>::value; +}; + +} // namespace ublas +} // namespace numeric +} // namespace boost + +//////////////////////////////////////////////// +//////////////////////////////////////////////// + + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + +template +struct index_position_pairs_impl +{ + template + static constexpr void run(array_type& out, tuple_left const& lhs, tuple_right const& rhs, std::size_t p) + { + using index_type = std::tuple_element_t; + using has_index_type = has_index; + using get_index_type = index_position; + using next_type = index_position_pairs_impl; + if constexpr ( has_index_type::value && index_type::value != 0) + out[p++] = std::make_pair(r-1,get_index_type::value); + next_type::run( out, lhs, rhs, p ); + } +}; + +template +struct index_position_pairs_impl +{ + template + static constexpr void run(array_type& out, tuple_left const& , tuple_right const& , std::size_t p) + { + using index_type = std::tuple_element_t; + using has_index_type = has_index; + using get_index_type = index_position; + if constexpr ( has_index_type::value && index_type::value != 0 ) + out[p] = std::make_pair(m-1,get_index_type::value); + } +}; + +template +struct index_position_pairs_impl +{ + template + static constexpr void run(array_type&, tuple_left const& , tuple_right const& , std::size_t) + {} +}; + + +} // namespace detail + + +/** @brief index_position_pairs returns zero-based index positions of matching indexes of two multi-indexes + * + * @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type + * + * @code auto pairs = index_position_pairs(std::make_tuple(_a,_b), std::make_tuple(_b,_c)); + * @endcode + * + * @returns a std::array instance containing index position pairs of type std::pair. + * + * @param lhs left std::tuple instance representing a multi-index + * @param rhs right std::tuple instance representing a multi-index +*/ +template +auto index_position_pairs(tuple_left const& lhs, tuple_right const& rhs) +{ + using pair_type = std::pair; + constexpr auto m = std::tuple_size::value; + constexpr auto p = number_equal_indexes::value; + auto array = std::array{}; + detail::index_position_pairs_impl<1,m>::run(array, lhs, rhs,0); + return array; +} + +} // namespace ublas +} // namespace numeric +} // namespace boost + +//////////////////////////// +//////////////////////////// +//////////////////////////// +//////////////////////////// + + +namespace boost { +namespace numeric { +namespace ublas { +namespace detail { + +template +constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence ) +{ + return std::make_pair( + std::vector{std::get<0>( std::get(array) )+1 ...} , + std::vector{std::get<1>( std::get(array) )+1 ...} ); +} + +} // namespace detail + + +/** @brief array_to_vector converts a std::array of zero-based index position pairs into two std::vector of one-based index positions + * + * @code auto two_vectors = array_to_vector(std::make_array ( std::make_pair(1,2), std::make_pair(3,4) ) ) ; + * @endcode + * + * @returns two std::vector of one-based index positions + * + * @param array std::array of zero-based index position pairs +*/ +template +constexpr auto array_to_vector( std::array const& array) +{ + constexpr auto sequence = std::make_index_sequence{}; + return detail::array_to_vector_impl( array, sequence ); +} + + +} // namespace ublas +} // namespace numeric +} // namespace boost + + +#endif // _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ diff --git a/include/boost/numeric/ublas/tensor/multiplication.hpp b/include/boost/numeric/ublas/tensor/multiplication.hpp index 1fb699fd3..698b6b1ef 100644 --- a/include/boost/numeric/ublas/tensor/multiplication.hpp +++ b/include/boost/numeric/ublas/tensor/multiplication.hpp @@ -650,7 +650,7 @@ void ttv(SizeType const m, SizeType const p, detail::recursive::mtv(m-1, c, nc, wc, a, na, wa, b); else /*if( p == 1 )*/{ auto v = std::remove_pointer_t>{}; - *c = detail::recursive::inner(0ul, na, a, wa, b, wb, v); + *c = detail::recursive::inner(SizeType(0), na, a, wa, b, wb, v); } } diff --git a/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp b/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp index 603b2fc1f..7ae9ffb2c 100644 --- a/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp +++ b/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp @@ -12,15 +12,20 @@ #ifndef _BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_ #define _BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_ -#include -#include +#include "expression.hpp" +#include "expression_evaluation.hpp" +#include "multi_index_utility.hpp" +#include "functions.hpp" + #include #include +#include namespace boost{ namespace numeric{ namespace ublas { + template class tensor; @@ -71,6 +76,8 @@ FIRST_ORDER_OPERATOR_LEFT (-, matrix_expression, detail:: tensor_expression) FIRST_ORDER_OPERATOR_LEFT (/, matrix_expression, detail:: tensor_expression) + + template auto operator+( boost::numeric::ublas::detail::tensor_expression const& lhs, boost::numeric::ublas::detail::tensor_expression const& rhs) { return boost::numeric::ublas::detail::make_binary_tensor_expression (lhs(), rhs(), [](auto const& l, auto const& r){ return l + r; }); @@ -196,4 +203,42 @@ auto operator -(boost::numeric::ublas::detail::tensor_expression const& lhs } + + + +/** @brief Performs a tensor contraction, not an elementwise multiplication + * +*/ + +template +auto operator*( + std::pair< tensor_type_left const&, tuple_type_left > lhs, + std::pair< tensor_type_right const&, tuple_type_right > rhs) +{ + + using namespace boost::numeric::ublas; + + auto const& tensor_left = lhs.first; + auto const& tensor_right = rhs.first; + + auto multi_index_left = lhs.second; + auto multi_index_right = rhs.second; + + static constexpr auto num_equal_ind = number_equal_indexes::value; + + if constexpr ( num_equal_ind == 0 ){ + return tensor_left * tensor_right; + } + else if constexpr ( num_equal_ind==std::tuple_size::value && std::is_same::value ){ + + return boost::numeric::ublas::inner_prod( tensor_left, tensor_right ); + } + else { + auto array_index_pairs = index_position_pairs(multi_index_left,multi_index_right); + auto index_pairs = array_to_vector( array_index_pairs ); + return boost::numeric::ublas::prod( tensor_left, tensor_right, index_pairs.first, index_pairs.second ); + } + +} + #endif diff --git a/include/boost/numeric/ublas/tensor/storage_traits.hpp b/include/boost/numeric/ublas/tensor/storage_traits.hpp new file mode 100644 index 000000000..52840e968 --- /dev/null +++ b/include/boost/numeric/ublas/tensor/storage_traits.hpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer IOSB, Ettlingen Germany +// + + +#ifndef _BOOST_STORAGE_TRAITS_HPP_ +#define _BOOST_STORAGE_TRAITS_HPP_ + +#include +#include + +namespace boost { +namespace numeric { +namespace ublas { + + +template +struct storage_traits; + + +template +struct storage_traits> +{ + using array_type = std::vector; + + using size_type = typename array_type::size_type; + using difference_type = typename array_type::difference_type; + using value_type = typename array_type::value_type; + + using reference = typename array_type::reference; + using const_reference = typename array_type::const_reference; + + using pointer = typename array_type::pointer; + using const_pointer = typename array_type::const_pointer; + + using iterator = typename array_type::iterator; + using const_iterator = typename array_type::const_iterator; + + using reverse_iterator = typename array_type::reverse_iterator; + using const_reverse_iterator = typename array_type::const_reverse_iterator; + + template + using rebind = std::vector::template rebind_alloc>; +}; + + +template +struct storage_traits> +{ + using array_type = std::array; + + using size_type = typename array_type::size_type; + using difference_type = typename array_type::difference_type; + using value_type = typename array_type::value_type; + + using reference = typename array_type::reference; + using const_reference = typename array_type::const_reference; + + using pointer = typename array_type::pointer; + using const_pointer = typename array_type::const_pointer; + + using iterator = typename array_type::iterator; + using const_iterator = typename array_type::const_iterator; + + using reverse_iterator = typename array_type::reverse_iterator; + using const_reverse_iterator = typename array_type::const_reverse_iterator; + + template + using rebind = std::array; +}; + +} // ublas +} // numeric +} // boost + + +#endif // _BOOST_STORAGE_TRAITS_HPP_ diff --git a/include/boost/numeric/ublas/tensor/strides.hpp b/include/boost/numeric/ublas/tensor/strides.hpp index fca98227e..0595b16bd 100644 --- a/include/boost/numeric/ublas/tensor/strides.hpp +++ b/include/boost/numeric/ublas/tensor/strides.hpp @@ -95,12 +95,12 @@ class basic_strides if constexpr (std::is_same::value){ - auto k = 1ul, kend = this->size(); + size_type k = 1ul, kend = this->size(); for(; k < kend; ++k) _base[k] = _base[k-1] * s[k-1]; } else { - auto k = this->size()-2, kend = 0ul; + size_type k = this->size()-2, kend = 0ul; for(; k > kend; --k) _base[k] = _base[k+1] * s[k+1]; _base[0] = _base[1] * s[1]; @@ -202,12 +202,13 @@ using strides = basic_strides; namespace detail { -/** @brief Accesses memory with multi-indices +/** @brief Returns relative memory index with respect to a multi-index * - * @code auto m = access(0, 3,4,5); @endcode + * @code auto j = access(std::vector{3,4,5}, strides{shape{4,2,3},first_order}); @endcode * - * @param[in] i multi-index vector of length p - * @returns relative memory location depending on \c i + * @param[in] i multi-index of length p + * @param[in] w stride vector of length p + * @returns relative memory location depending on \c i and \c w */ BOOST_UBLAS_INLINE template @@ -220,14 +221,14 @@ auto access(std::vector const& i, basic_strides diff --git a/include/boost/numeric/ublas/tensor/tensor.hpp b/include/boost/numeric/ublas/tensor/tensor.hpp index 69a2069e2..90662e021 100644 --- a/include/boost/numeric/ublas/tensor/tensor.hpp +++ b/include/boost/numeric/ublas/tensor/tensor.hpp @@ -1,4 +1,3 @@ -// // Copyright (c) 2018 // Cem Bassoy // @@ -7,9 +6,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. + /// \file tensor.hpp Definition for the tensor template class @@ -25,8 +25,7 @@ #include "expression_evaluation.hpp" #include "extents.hpp" #include "strides.hpp" - - +#include "index.hpp" namespace boost { namespace numeric { namespace ublas { @@ -65,6 +64,8 @@ class vector; // } //}; + + /** @brief A dense tensor of values of type \c T. * * For a \f$n\f$-dimensional tensor \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped @@ -130,7 +131,6 @@ class tensor: using vector_type = vector; - /** @brief Constructs a tensor. * * @note the tensor is empty. @@ -174,7 +174,7 @@ class tensor: * @param s initial tensor dimension extents */ explicit BOOST_UBLAS_INLINE - tensor (shape const& s) + tensor (extents_type const& s) : tensor_expression_type() //tensor_container() , extents_ (s) , strides_ (extents_) @@ -191,7 +191,7 @@ class tensor: * @param a container of \c array_type that is copied according to the storage layout */ BOOST_UBLAS_INLINE - tensor (shape const& s, const array_type &a) + tensor (extents_type const& s, const array_type &a) : tensor_expression_type() //tensor_container() , extents_ (s) , strides_ (extents_) @@ -211,7 +211,7 @@ class tensor: * @param i initial value of all elements of type \c value_type */ BOOST_UBLAS_INLINE - tensor (shape const& e, const value_type &i) + tensor (extents_type const& e, const value_type &i) : tensor_expression_type() //tensor_container () , extents_ (e) , strides_ (extents_) @@ -443,12 +443,18 @@ class tensor: return this->extents_.at(r); } - /** @brief Returns the size of the tensor */ + /** @brief Returns the number of dimensions/modes of the tensor */ BOOST_UBLAS_INLINE size_type rank () const { return this->extents_.size(); } + /** @brief Returns the number of dimensions/modes of the tensor */ + BOOST_UBLAS_INLINE + size_type order () const { + return this->extents_.size(); + } + /** @brief Returns the strides of the tensor */ BOOST_UBLAS_INLINE strides_type const& strides () const { @@ -536,6 +542,8 @@ class tensor: } + + /** @brief Element access using a single index. * * @@ -550,7 +558,6 @@ class tensor: /** @brief Element access using a single index. - * * * @code A(i) = a; @endcode * @@ -561,6 +568,32 @@ class tensor: return this->data_[i]; } + + + + /** @brief Generates a tensor index for tensor contraction + * + * + * @code auto Ai = A(_i,_j,k); @endcode + * + * @param i placeholder + * @param is zero-based indices where 0 <= is[r] < this->size(r) where 0 < r < this->rank() + */ + BOOST_UBLAS_INLINE + template + decltype(auto) operator() (index::index_type p, index_types ... ps) const + { + constexpr auto N = sizeof...(ps)+1; + if( N != this->rank() ) + throw std::runtime_error("Error in boost::numeric::ublas::operator(): size of provided index_types does not match with the rank."); + + return std::make_pair( std::cref(*this), std::make_tuple( p, std::forward(ps)... ) ); + } + + + + + /** @brief Reshapes the tensor * * diff --git a/test/tensor/test_algorithms.cpp b/test/tensor/test_algorithms.cpp index e63128eaa..265c5b088 100644 --- a/test/tensor/test_algorithms.cpp +++ b/test/tensor/test_algorithms.cpp @@ -5,7 +5,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // @@ -76,9 +77,119 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_copy, value, test_type for(auto i = 1ul; i < c.size(); ++i) BOOST_CHECK_EQUAL( c[i], a[i] ); + using size_type = typename ublas::strides::value_type; + size_type const*const p0 = nullptr; + BOOST_CHECK_THROW( ublas::copy( n.size(), p0, c.data(), wc.data(), b.data(), wb.data() ), std::runtime_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), p0, b.data(), wb.data() ), std::runtime_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), p0 ), std::runtime_error ); + + value_type* c0 = nullptr; + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c0, wc.data(), b.data(), wb.data() ), std::runtime_error ); + } + + // special case rank == 0 + { + auto n = ublas::shape{}; + + auto a = vector_type(n.product()); + auto b = vector_type(n.product()); + auto c = vector_type(n.product()); + + + auto wa = ublas::strides(n); + auto wb = ublas::strides (n); + auto wc = ublas::strides(n); + + ublas::copy( n.size(), n.data(), b.data(), wb.data(), a.data(), wa.data() ); + ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data() ); + + + + BOOST_CHECK_NO_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data() ) ); + + } + + + + + +} + + + +BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_transform, value, test_types2, fixture ) +{ + using namespace boost::numeric; + using value_type = value; + using vector_type = std::vector; + + + for(auto const& n : extents) { + + auto a = vector_type(n.product()); + auto b = vector_type(n.product()); + auto c = vector_type(n.product()); + + auto wa = ublas::strides(n); + auto wb = ublas::strides (n); + auto wc = ublas::strides(n); + + auto v = value_type{}; + for(auto i = 0ul; i < a.size(); ++i, v+=1){ + a[i]=v; + } + + ublas::transform( n.size(), n.data(), b.data(), wb.data(), a.data(), wa.data(), [](value_type const& a){ return a + value_type(1);} ); + ublas::transform( n.size(), n.data(), c.data(), wc.data(), b.data(), wb.data(), [](value_type const& a){ return a - value_type(1);} ); + + for(auto i = 1ul; i < c.size(); ++i) + BOOST_CHECK_EQUAL( c[i], a[i] ); + + } +} + + + +BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_accumulate, value, test_types2, fixture ) +{ + using namespace boost::numeric; + using value_type = value; + using vector_type = std::vector; + + + for(auto const& n : extents) { + + auto const s = n.product(); + + auto a = vector_type(n.product()); +// auto b = vector_type(n.product()); +// auto c = vector_type(n.product()); + + auto wa = ublas::strides(n); +// auto wb = ublas::strides (n); +// auto wc = ublas::strides(n); + + auto v = value_type{}; + for(auto i = 0ul; i < a.size(); ++i, v+=value_type(1)){ + a[i]=v; + } + + auto acc = ublas::accumulate( n.size(), n.data(), a.data(), wa.data(), v); + + BOOST_CHECK_EQUAL( acc, value_type( s*(s+1) / 2 ) ); + + + auto acc2 = ublas::accumulate( n.size(), n.data(), a.data(), wa.data(), v, + [](auto const& l, auto const& r){return l + r; }); + + BOOST_CHECK_EQUAL( acc2, value_type( s*(s+1) / 2 ) ); + } } + + + template void init(std::vector& a) { @@ -108,7 +219,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_trans, value, test_typ using vector_type = std::vector; using strides_type = ublas::strides; using extents_type = ublas::shape; - using permutation_type = std::vector; + using size_type = typename extents_type::value_type; + using permutation_type = std::vector; + for(auto const& n : extents) { @@ -127,7 +240,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_trans, value, test_typ init(a); // so wie last-order. - for(auto i = 0ul, j = p; i < n.size(); ++i, --j) + for(auto i = size_type(0), j = p; i < n.size(); ++i, --j) pi[i] = j; auto nc = typename extents_type::base_type (p); diff --git a/test/tensor/test_einstein_notation.cpp b/test/tensor/test_einstein_notation.cpp new file mode 100644 index 000000000..7d23f3a90 --- /dev/null +++ b/test/tensor/test_einstein_notation.cpp @@ -0,0 +1,122 @@ +// Copyright (c) 2018 Cem Bassoy +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. +// +// And we acknowledge the support from all contributors. + + +#include +#include +#include + +#include + +#include "utility.hpp" + +BOOST_AUTO_TEST_SUITE ( test_einstein_notation, * boost::unit_test::depends_on("test_multi_index") ) ; + + +using test_types = zip>::with_t; + +//using test_types = zip::with_t; + +BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types ) +{ + using namespace boost::numeric::ublas; + using value_type = typename value::first_type; + using layout_type = typename value::second_type; + using tensor_type = tensor; + using namespace boost::numeric::ublas::index; + + { + auto A = tensor_type{5,3}; + auto B = tensor_type{3,4}; +// auto C = tensor_type{4,5,6}; + + for(auto j = 0u; j < A.extents().at(1); ++j) + for(auto i = 0u; i < A.extents().at(0); ++i) + A.at( i,j ) = value_type(i+1); + + for(auto j = 0u; j < B.extents().at(1); ++j) + for(auto i = 0u; i < B.extents().at(0); ++i) + B.at( i,j ) = value_type(i+1); + + + + auto AB = A(_,_e) * B(_e,_); + +// std::cout << "A = " << A << std::endl; +// std::cout << "B = " << B << std::endl; +// std::cout << "AB = " << AB << std::endl; + + for(auto j = 0u; j < AB.extents().at(1); ++j) + for(auto i = 0u; i < AB.extents().at(0); ++i) + BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(A.at( i,0 ) * ( B.extents().at(0) * (B.extents().at(0)+1) / 2 )) ); + + + } + + + { + auto A = tensor_type{4,5,3}; + auto B = tensor_type{3,4,2}; + + for(auto k = 0u; k < A.extents().at(2); ++k) + for(auto j = 0u; j < A.extents().at(1); ++j) + for(auto i = 0u; i < A.extents().at(0); ++i) + A.at( i,j,k ) = value_type(i+1); + + for(auto k = 0u; k < B.extents().at(2); ++k) + for(auto j = 0u; j < B.extents().at(1); ++j) + for(auto i = 0u; i < B.extents().at(0); ++i) + B.at( i,j,k ) = value_type(i+1); + + auto AB = A(_d,_,_f) * B(_f,_d,_); + +// std::cout << "A = " << A << std::endl; +// std::cout << "B = " << B << std::endl; +// std::cout << "AB = " << AB << std::endl; + // n*(n+1)/2; + auto const nf = ( B.extents().at(0) * (B.extents().at(0)+1) / 2 ); + auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 ); + + for(auto j = 0u; j < AB.extents().at(1); ++j) + for(auto i = 0u; i < AB.extents().at(0); ++i) + BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(nf * nd) ); + + } + + + { + auto A = tensor_type{4,3}; + auto B = tensor_type{3,4,2}; + + for(auto j = 0u; j < A.extents().at(1); ++j) + for(auto i = 0u; i < A.extents().at(0); ++i) + A.at( i,j ) = value_type(i+1); + + for(auto k = 0u; k < B.extents().at(2); ++k) + for(auto j = 0u; j < B.extents().at(1); ++j) + for(auto i = 0u; i < B.extents().at(0); ++i) + B.at( i,j,k ) = value_type(i+1); + + auto AB = A(_d,_f) * B(_f,_d,_); + + // n*(n+1)/2; + auto const nf = ( B.extents().at(0) * (B.extents().at(0)+1) / 2 ); + auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 ); + + for(auto i = 0u; i < AB.extents().at(0); ++i) + BOOST_CHECK_EQUAL ( AB.at( i ) , value_type(nf * nd) ); + + } +} + +BOOST_AUTO_TEST_SUITE_END(); + diff --git a/test/tensor/test_expression.cpp b/test/tensor/test_expression.cpp index 800c7c6c5..d9207bb78 100644 --- a/test/tensor/test_expression.cpp +++ b/test/tensor/test_expression.cpp @@ -5,7 +5,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // @@ -67,7 +68,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_expression_access, value, test_ty const auto& tensor_expression_const = static_cast( t ); for(auto i = 0ul; i < t.size(); ++i) - BOOST_CHECK_EQUAL( tensor_expression_const(i), t(i) ); + BOOST_CHECK_EQUAL( tensor_expression_const()(i), t(i) ); } } diff --git a/test/tensor/test_expression_evaluation.cpp b/test/tensor/test_expression_evaluation.cpp index 60edb4bac..d771d0c9a 100644 --- a/test/tensor/test_expression_evaluation.cpp +++ b/test/tensor/test_expression_evaluation.cpp @@ -5,7 +5,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // diff --git a/test/tensor/test_functions.cpp b/test/tensor/test_functions.cpp index f5e5a277f..acb1fb5ee 100644 --- a/test/tensor/test_functions.cpp +++ b/test/tensor/test_functions.cpp @@ -5,7 +5,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // // And we acknowledge the support from all contributors. @@ -237,6 +238,115 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_inner_prod, value, test_types, fi } +BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_norm, value, test_types, fixture ) +{ + using namespace boost::numeric; + using value_type = typename value::first_type; + using layout_type = typename value::second_type; + using tensor_type = ublas::tensor; + + + for(auto const& n : extents) { + + auto a = tensor_type(n); + + auto one = value_type(1); + auto v = one; + for(auto& aa: a) + aa = v, v += one; + + + auto c = ublas::inner_prod(a, a); + auto r = std::inner_product(a.begin(),a.end(), a.begin(),value_type(0)); + + auto r2 = ublas::norm( (a+a) / 2 ); + + BOOST_CHECK_EQUAL( c , r ); + BOOST_CHECK_EQUAL( std::sqrt( c ) , r2 ); + + } +} + + +BOOST_FIXTURE_TEST_CASE( test_tensor_real_imag_conj, fixture ) +{ + using namespace boost::numeric; + using value_type = float; + using complex_type = std::complex; + using layout_type = ublas::first_order; + + using tensor_complex_type = ublas::tensor; + using tensor_type = ublas::tensor; + + for(auto const& n : extents) { + + auto a = tensor_type(n); + auto r0 = tensor_type(n); + auto r00 = tensor_complex_type(n); + + + auto one = value_type(1); + auto v = one; + for(auto& aa: a) + aa = v, v += one; + + tensor_type b = (a+a) / value_type( 2 ); + tensor_type r1 = ublas::real( (a+a) / value_type( 2 ) ); + std::transform( b.begin(), b.end(), r0.begin(), [](auto const& l){ return std::real( l ); } ); + BOOST_CHECK( r0 == r1 ); + + tensor_type r2 = ublas::imag( (a+a) / value_type( 2 ) ); + std::transform( b.begin(), b.end(), r0.begin(), [](auto const& l){ return std::imag( l ); } ); + BOOST_CHECK( r0 == r2 ); + + tensor_complex_type r3 = ublas::conj( (a+a) / value_type( 2 ) ); + std::transform( b.begin(), b.end(), r00.begin(), [](auto const& l){ return std::conj( l ); } ); + BOOST_CHECK( r00 == r3 ); + + } + + for(auto const& n : extents) { + + + + + auto a = tensor_complex_type(n); + + auto r00 = tensor_complex_type(n); + auto r0 = tensor_type(n); + + + auto one = complex_type(1,1); + auto v = one; + for(auto& aa: a) + aa = v, v = v + one; + + tensor_complex_type b = (a+a) / complex_type( 2,2 ); + + + tensor_type r1 = ublas::real( (a+a) / complex_type( 2,2 ) ); + std::transform( b.begin(), b.end(), r0.begin(), [](auto const& l){ return std::real( l ); } ); + BOOST_CHECK( r0 == r1 ); + + tensor_type r2 = ublas::imag( (a+a) / complex_type( 2,2 ) ); + std::transform( b.begin(), b.end(), r0.begin(), [](auto const& l){ return std::imag( l ); } ); + BOOST_CHECK( r0 == r2 ); + + tensor_complex_type r3 = ublas::conj( (a+a) / complex_type( 2,2 ) ); + std::transform( b.begin(), b.end(), r00.begin(), [](auto const& l){ return std::conj( l ); } ); + BOOST_CHECK( r00 == r3 ); + + + + } + + + +} + + + + BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_outer_prod, value, test_types, fixture ) { diff --git a/test/tensor/test_multi_index.cpp b/test/tensor/test_multi_index.cpp new file mode 100644 index 000000000..a8ca4d7d5 --- /dev/null +++ b/test/tensor/test_multi_index.cpp @@ -0,0 +1,145 @@ +// Copyright (c) 2018 Cem Bassoy +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The authors gratefully acknowledge the support of +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. +// + +#include +#include +#include +#include + + +#include + +#include "utility.hpp" + + +BOOST_AUTO_TEST_SUITE ( test_multi_index ) ; + + +using test_types = zip>::with_t; + + +BOOST_AUTO_TEST_CASE ( test_index_classes ) +{ + using namespace boost::numeric::ublas::index; + + + BOOST_CHECK_EQUAL ( _a.value , 1 ) ; + BOOST_CHECK_EQUAL ( _b.value , 2 ) ; + BOOST_CHECK_EQUAL ( _c.value , 3 ) ; + BOOST_CHECK_EQUAL ( _d.value , 4 ) ; + BOOST_CHECK_EQUAL ( _e.value , 5 ) ; + BOOST_CHECK_EQUAL ( _f.value , 6 ) ; + BOOST_CHECK_EQUAL ( _g.value , 7 ) ; + BOOST_CHECK_EQUAL ( _h.value , 8 ) ; + BOOST_CHECK_EQUAL ( _i.value , 9 ) ; + BOOST_CHECK_EQUAL ( _j.value , 10 ) ; + BOOST_CHECK_EQUAL ( _k.value , 11 ) ; + BOOST_CHECK_EQUAL ( _l.value , 12 ) ; + BOOST_CHECK_EQUAL ( _m.value , 13 ) ; + BOOST_CHECK_EQUAL ( _n.value , 14 ) ; + BOOST_CHECK_EQUAL ( _o.value , 15 ) ; + BOOST_CHECK_EQUAL ( _p.value , 16 ) ; + BOOST_CHECK_EQUAL ( _q.value , 17 ) ; + BOOST_CHECK_EQUAL ( _r.value , 18 ) ; + BOOST_CHECK_EQUAL ( _s.value , 19 ) ; + BOOST_CHECK_EQUAL ( _t.value , 20 ) ; + BOOST_CHECK_EQUAL ( _u.value , 21 ) ; + BOOST_CHECK_EQUAL ( _v.value , 22 ) ; + BOOST_CHECK_EQUAL ( _w.value , 23 ) ; + BOOST_CHECK_EQUAL ( _x.value , 24 ) ; + BOOST_CHECK_EQUAL ( _y.value , 25 ) ; + BOOST_CHECK_EQUAL ( _z.value , 26 ) ; + +} + +BOOST_AUTO_TEST_CASE ( test_multi_index_class_construction ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + + { + multi_index<2> ind(_a, _b); + + BOOST_CHECK_EQUAL ( get<0>( ind ), 1 ) ; + BOOST_CHECK_EQUAL ( get<1>( ind ), 2 ) ; + } + + + { + multi_index<2> ind(_d,_c); + + BOOST_CHECK_EQUAL ( ind[0] , 4 ) ; + BOOST_CHECK_EQUAL ( ind[1] , 3 ) ; + } +} + + +BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_multi_index_class_generation, value, test_types ) +{ + using namespace boost::numeric::ublas; + using value_type = typename value::first_type; + using layout_type = typename value::second_type; + using tensor_type = tensor; + + auto t = std::make_tuple ( + index::_a, // 0 + index::_b, // 1 + index::_c, // 2 + index::_d, // 3 + index::_e // 4 + ); + + { + auto a = tensor_type(shape{2,3}, value_type{2}); + auto a_ind = a( std::get<0>(t), std::get<2>(t) ); + + BOOST_CHECK_EQUAL ( std::addressof( a_ind.first ), std::addressof( a ) ) ; + + BOOST_CHECK_EQUAL (std::get<0>(a_ind.second)(), index::_a() ) ; + BOOST_CHECK_EQUAL (std::get<1>(a_ind.second)(), index::_c() ) ; + } + + { + auto a = tensor_type(shape{2,3}, value_type{2}); + auto a_ind = a( std::get<2>(t), std::get<0>(t) ); + + BOOST_CHECK_EQUAL ( std::addressof( a_ind.first ), std::addressof( a ) ) ; + + BOOST_CHECK_EQUAL (std::get<0>(a_ind.second)(), index::_c() ) ; + BOOST_CHECK_EQUAL (std::get<1>(a_ind.second)(), index::_a() ) ; + } + + { + auto a = tensor_type(shape{2,3}, value_type{2}); + auto a_ind = a( std::get<2>(t), std::get<3>(t) ); + + BOOST_CHECK_EQUAL (std::addressof( a_ind.first ), std::addressof( a ) ) ; + + BOOST_CHECK_EQUAL (std::get<0>(a_ind.second)(), index::_c() ) ; + BOOST_CHECK_EQUAL (std::get<1>(a_ind.second)(), index::_d() ) ; + } + + { + auto a = tensor_type(shape{2,3,4}, value_type{2}); + auto a_ind = a( std::get<2>(t), std::get<3>(t), std::get<0>(t) ); + + BOOST_CHECK_EQUAL (std::addressof( a_ind.first ), std::addressof( a ) ) ; + + BOOST_CHECK_EQUAL (std::get<0>(a_ind.second)(), index::_c() ) ; + BOOST_CHECK_EQUAL (std::get<1>(a_ind.second)(), index::_d() ) ; + BOOST_CHECK_EQUAL (std::get<2>(a_ind.second)(), index::_a() ) ; + } + +} + +BOOST_AUTO_TEST_SUITE_END(); + diff --git a/test/tensor/test_multi_index_utility.cpp b/test/tensor/test_multi_index_utility.cpp new file mode 100644 index 000000000..a83ece0d0 --- /dev/null +++ b/test/tensor/test_multi_index_utility.cpp @@ -0,0 +1,564 @@ +// Copyright (c) 2018 Cem Bassoy +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The author gratefully acknowledge the support of +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. +// + + +#include + +#include + +BOOST_AUTO_TEST_SUITE ( test_multi_index_utility ) ; + + +BOOST_AUTO_TEST_CASE ( test_multi_index_has_index ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + { + constexpr auto tuple = std::tuple<>{}; + constexpr auto has_a = has_index::value; + constexpr auto has_b = has_index::value; + BOOST_CHECK( !has_a ); + BOOST_CHECK( !has_b ); + } + + + { + constexpr auto tuple = std::make_tuple(_a); + constexpr auto has_a = has_index::value; + constexpr auto has_b = has_index::value; + BOOST_CHECK( has_a ); + BOOST_CHECK( !has_b ); + } + + { + constexpr auto tuple = std::make_tuple(_a,_b,_,_c,_d); + constexpr auto has_a = has_index::value; + constexpr auto has_b = has_index::value; + constexpr auto has_c = has_index::value; + constexpr auto has_d = has_index::value; + constexpr auto has_e = has_index::value; + constexpr auto has__ = has_index::value; + BOOST_CHECK( has_a ); + BOOST_CHECK( has_b ); + BOOST_CHECK( has_c ); + BOOST_CHECK( has_d ); + BOOST_CHECK( !has_e ); + BOOST_CHECK( has__ ); + } +} + + + +BOOST_AUTO_TEST_CASE ( test_multi_index_valid ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + { + constexpr auto tuple = std::tuple<>{}; + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } + + + { + constexpr auto tuple = std::make_tuple(_a); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } + + { + constexpr auto tuple = std::make_tuple(_a,_,_b); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } + + { + constexpr auto tuple = std::make_tuple(_a,_,_b,_b); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( !valid ); + } + + { + constexpr auto tuple = std::make_tuple(_c,_a,_,_b,_b); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( !valid ); + } + + { + constexpr auto tuple = std::make_tuple(_c,_a,_,_b); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } + + { + constexpr auto tuple = std::make_tuple(_,_c,_a,_,_b); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } + + { + constexpr auto tuple = std::make_tuple(_,_c,_a,_,_b,_); + constexpr auto valid = valid_multi_index::value; + BOOST_CHECK( valid ); + } +} + + + + + +BOOST_AUTO_TEST_CASE ( test_multi_index_number_equal_indices ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + { + constexpr auto lhs = std::tuple<>{}; + constexpr auto rhs = std::tuple<>{}; + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::tuple<>{}; + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 0 ); + } + + { + constexpr auto lhs = std::tuple<>{}; + constexpr auto rhs = std::make_tuple(_a); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_b); + constexpr auto rhs = std::make_tuple(_a); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 0 ); + } + + + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::make_tuple(_a); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_a,_b); + constexpr auto rhs = std::make_tuple(_a); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_b); + constexpr auto rhs = std::make_tuple(_a,_b); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::make_tuple(_a); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } + + + + { + constexpr auto lhs = std::make_tuple(_a,_b); + constexpr auto rhs = std::make_tuple(_a,_b); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a); + constexpr auto rhs = std::make_tuple(_a,_b); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_c); + constexpr auto rhs = std::make_tuple(_a,_b); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_c); + constexpr auto rhs = std::make_tuple(_a,_b,_d); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d); + constexpr auto rhs = std::make_tuple(_a,_b,_d); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 3 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d); + constexpr auto rhs = std::make_tuple(_a,_b,_d,_); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 3 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d,_); + constexpr auto rhs = std::make_tuple(_a,_b,_d,_); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 3 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d,_); + constexpr auto rhs = std::make_tuple( _,_b,_d,_); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_,_a,_d,_); + constexpr auto rhs = std::make_tuple(_,_b,_d,_); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_,_a,_d,_); + constexpr auto rhs = std::make_tuple(_,_b,_d,_,_); + constexpr auto num = number_equal_indexes::value; + BOOST_CHECK_EQUAL( num, 1 ); + } +} + + + + + + + +BOOST_AUTO_TEST_CASE ( test_multi_index_index_position ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + { + constexpr auto tuple = std::tuple<>{}; + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,0); + } + + { + constexpr auto tuple = std::make_tuple(_); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,0); + } + + { + constexpr auto tuple = std::make_tuple(_); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,1); + } + + { + constexpr auto tuple = std::make_tuple(_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,0); + } + + { + constexpr auto tuple = std::make_tuple(_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,1); + } + + { + constexpr auto tuple = std::make_tuple(_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,2); + } + + + + + { + constexpr auto tuple = std::make_tuple(_c,_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,0); + } + + { + constexpr auto tuple = std::make_tuple(_c,_,_a,_); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,1); + } + + { + constexpr auto tuple = std::make_tuple(_c,_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,2); + } + + { + constexpr auto tuple = std::make_tuple(_c,_,_a); + constexpr auto ind = index_position::value; + BOOST_CHECK_EQUAL(ind,3); + } + +} + + + + + + + + +BOOST_AUTO_TEST_CASE ( test_multi_index_index_position_pairs ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + { + constexpr auto lhs = std::tuple<>{}; + constexpr auto rhs = std::tuple<>{}; + auto array = index_position_pairs(lhs, rhs); + BOOST_CHECK_EQUAL(array.size(), 0ul ); + } + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::tuple<>{}; + auto array = index_position_pairs(lhs, rhs); + BOOST_CHECK_EQUAL(array.size(), 0ul ); + } + + { + constexpr auto lhs = std::tuple<>{}; + constexpr auto rhs = std::make_tuple(_a); + auto array = index_position_pairs(lhs, rhs); + BOOST_CHECK_EQUAL(array.size(), 0ul ); + } + + { + constexpr auto lhs = std::make_tuple(_b); + constexpr auto rhs = std::make_tuple(_a); + auto array = index_position_pairs(lhs, rhs); + BOOST_CHECK_EQUAL(array.size(), 0ul ); + } + + + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::make_tuple(_a); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_a,_b); + constexpr auto rhs = std::make_tuple(_a); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_b); + constexpr auto rhs = std::make_tuple(_a,_b); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_a); + constexpr auto rhs = std::make_tuple(_a); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 0 ); + } + + + + { + constexpr auto lhs = std::make_tuple(_a,_b); + constexpr auto rhs = std::make_tuple(_a,_b); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 2ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 0 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 1 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a); + constexpr auto rhs = std::make_tuple(_a,_b); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 2ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_c); + constexpr auto rhs = std::make_tuple(_a,_b); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 2ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_c); + constexpr auto rhs = std::make_tuple(_a,_b,_d); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 2ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d); + constexpr auto rhs = std::make_tuple(_a,_b,_d); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 3ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + BOOST_CHECK_EQUAL(array[2].first , 2 ); + BOOST_CHECK_EQUAL(array[2].second, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d); + constexpr auto rhs = std::make_tuple(_a,_b,_d,_); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 3ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + BOOST_CHECK_EQUAL(array[2].first , 2 ); + BOOST_CHECK_EQUAL(array[2].second, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d,_); + constexpr auto rhs = std::make_tuple(_a,_b,_d,_); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 3ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 1 ); + BOOST_CHECK_EQUAL(array[1].second, 0 ); + BOOST_CHECK_EQUAL(array[2].first , 2 ); + BOOST_CHECK_EQUAL(array[2].second, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_b,_a,_d,_); + constexpr auto rhs = std::make_tuple( _,_b,_d,_); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 2ul ); + BOOST_CHECK_EQUAL(array[0].first , 0 ); + BOOST_CHECK_EQUAL(array[0].second, 1 ); + BOOST_CHECK_EQUAL(array[1].first , 2 ); + BOOST_CHECK_EQUAL(array[1].second, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_,_a,_d,_); + constexpr auto rhs = std::make_tuple(_,_b,_d,_); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 2 ); + BOOST_CHECK_EQUAL(array[0].second, 2 ); + } + + { + constexpr auto lhs = std::make_tuple(_,_a,_d,_); + constexpr auto rhs = std::make_tuple(_,_b,_d,_,_); + auto array = index_position_pairs(lhs, rhs); + BOOST_ASSERT(array.size() == 1ul ); + BOOST_CHECK_EQUAL(array[0].first , 2 ); + BOOST_CHECK_EQUAL(array[0].second, 2 ); + } +} + + + +BOOST_AUTO_TEST_CASE ( test_multi_index_array_to_vector ) +{ + using namespace boost::numeric::ublas; + using namespace boost::numeric::ublas::index; + + auto check = [](auto const& lhs, auto const& rhs) + { + auto array = index_position_pairs(lhs, rhs); + + auto vector_pair = array_to_vector( array ); + + BOOST_CHECK_EQUAL(vector_pair.first .size(), array.size() ); + BOOST_CHECK_EQUAL(vector_pair.second.size(), array.size() ); + + for(auto i = 0ul; i < array.size(); ++i) + { + BOOST_CHECK_EQUAL(vector_pair.first [i], array[i].first +1 ); + BOOST_CHECK_EQUAL(vector_pair.second[i], array[i].second+1 ); + } + + }; + + check(std::tuple<>{} , std::tuple<>{}); + check(std::make_tuple(_a) , std::tuple<>{}); + check(std::tuple<>{} , std::make_tuple(_a)); + check(std::make_tuple(_a) , std::make_tuple(_b)); + check(std::make_tuple(_a) , std::make_tuple(_a)); + check(std::make_tuple(_a,_b), std::make_tuple(_a)); + check(std::make_tuple(_a) , std::make_tuple(_a,_b)); + check(std::make_tuple(_a,_b), std::make_tuple(_a,_b)); + check(std::make_tuple(_b,_a), std::make_tuple(_a,_b)); + check(std::make_tuple(_b,_a,_c), std::make_tuple(_a,_b,_d)); +} + + + +BOOST_AUTO_TEST_SUITE_END(); + diff --git a/test/tensor/test_multiplication.cpp b/test/tensor/test_multiplication.cpp index 4be28f9f5..5c23e5a02 100644 --- a/test/tensor/test_multiplication.cpp +++ b/test/tensor/test_multiplication.cpp @@ -5,9 +5,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. #include @@ -59,6 +59,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_mtv, value, test_types, fixture ) using vector_type = std::vector; using extents_type = ublas::shape; using extents_type_base = typename extents_type::base_type; + using size_type = typename extents_type_base::value_type; for(auto const& na : extents) { @@ -68,14 +69,14 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_mtv, value, test_types, fixture ) auto a = vector_type(na.product(), value_type{2}); auto wa = strides_type(na); - for(auto m = 0ul; m < na.size(); ++m){ + for(auto m = 0u; m < na.size(); ++m){ auto nb = extents_type {na[m],1}; auto wb = strides_type (nb); auto b = vector_type (nb.product(), value_type{1} ); - auto nc_base = extents_type_base(std::max(na.size()-1,2ul),1); + auto nc_base = extents_type_base(std::max(na.size()-1, size_type{2}), 1); - for(auto i = 0ul, j = 0ul; i < na.size(); ++i) + for(auto i = 0u, j = 0u; i < na.size(); ++i) if(i != m) nc_base[j++] = na[i]; @@ -84,7 +85,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_mtv, value, test_types, fixture ) auto c = vector_type (nc.product(), value_type{0}); ublas::detail::recursive::mtv( - m, + size_type(m), c.data(), nc.data(), wc.data(), a.data(), na.data(), wa.data(), b.data()); @@ -149,18 +150,19 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttv, value, test_types, fixture ) using vector_type = std::vector; using extents_type = ublas::shape; using extents_type_base = typename extents_type::base_type; + using size_type = typename extents_type_base::value_type; for(auto const& na : extents) { auto a = vector_type(na.product(), value_type{2}); auto wa = strides_type(na); - for(auto m = 0ul; m < na.size(); ++m){ + for(auto m = 0u; m < na.size(); ++m){ auto b = vector_type (na[m], value_type{1} ); auto nb = extents_type {na[m],1}; auto wb = strides_type (nb); - auto nc_base = extents_type_base(std::max(na.size()-1,2ul),1); + auto nc_base = extents_type_base(std::max(na.size()-1, size_type(2)),1); for(auto i = 0ul, j = 0ul; i < na.size(); ++i) if(i != m) @@ -170,7 +172,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttv, value, test_types, fixture ) auto wc = strides_type (nc); auto c = vector_type (nc.product(), value_type{0}); - ublas::ttv( m+1, na.size(), + ublas::ttv(size_type(m+1), na.size(), c.data(), nc.data(), wc.data(), a.data(), na.data(), wa.data(), b.data(), nb.data(), wb.data()); @@ -192,13 +194,14 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttm, value, test_types, fixture ) using strides_type = ublas::strides; using vector_type = std::vector; using extents_type = ublas::shape; + using size_type = typename extents_type::value_type; for(auto const& na : extents) { auto a = vector_type(na.product(), value_type{2}); auto wa = strides_type(na); - for(auto m = 0ul; m < na.size(); ++m){ + for(auto m = 0u; m < na.size(); ++m){ auto nb = extents_type {na[m], na[m] }; auto b = vector_type (nb.product(), value_type{1} ); auto wb = strides_type (nb); @@ -208,7 +211,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttm, value, test_types, fixture ) auto wc = strides_type (nc); auto c = vector_type (nc.product(), value_type{0}); - ublas::ttm( m+1, na.size(), + ublas::ttm(size_type(m+1), na.size(), c.data(), nc.data(), wc.data(), a.data(), na.data(), wa.data(), b.data(), nb.data(), wb.data()); @@ -279,7 +282,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt_permutation, value, test_type // for the number of possible permutations // only permutation tuple pib is changed. - for(auto i = 0ul; i < f; ++i) { + for(auto i = 0u; i < f; ++i) { auto nb = permute_extents( pib, na ); auto wb = strides_type(nb); @@ -287,19 +290,19 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt_permutation, value, test_type auto pb = nb.size(); // the number of contractions is changed. - for( auto q = 0ul; q <= pa; ++q) { + for( auto q = size_type(0); q <= pa; ++q) { auto r = pa - q; auto s = pb - q; - auto pc = r+s > 0 ? std::max(r+s,2ul) : 2ul; + auto pc = r+s > 0 ? std::max(r+s,size_type(2)) : size_type(2); auto nc_base = std::vector( pc , 1 ); - for(auto i = 0ul; i < r; ++i) + for(auto i = 0u; i < r; ++i) nc_base[ i ] = na[ pia[i]-1 ]; - for(auto i = 0ul; i < s; ++i) + for(auto i = 0u; i < s; ++i) nc_base[ r + i ] = nb[ pib_inv[i]-1 ]; auto nc = extents_type ( nc_base ); @@ -315,7 +318,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt_permutation, value, test_type auto acc = value_type(1); for(auto i = r; i < pa; ++i) - acc *= na[pia[i]-1]; + acc *= value_type(na[pia[i]-1]); for(auto i = 0ul; i < c.size(); ++i) BOOST_CHECK_EQUAL( c[i] , acc * a[0] * b[0] ); @@ -368,19 +371,19 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt, value, test_types, fixture ) // the number of contractions is changed. - for( auto q = 0ul; q <= pa; ++q) { // pa + for( auto q = size_type(0); q <= pa; ++q) { // pa auto r = pa - q; auto s = pb - q; - auto pc = r+s > 0 ? std::max(r+s,2ul) : 2ul; + auto pc = r+s > 0 ? std::max(r+s, size_type(2)) : size_type(2); auto nc_base = std::vector( pc , 1 ); - for(auto i = 0ul; i < r; ++i) + for(auto i = 0u; i < r; ++i) nc_base[ i ] = na[ i ]; - for(auto i = 0ul; i < s; ++i) + for(auto i = 0u; i < s; ++i) nc_base[ r + i ] = nb[ i ]; auto nc = extents_type ( nc_base ); @@ -399,9 +402,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt, value, test_types, fixture ) auto acc = value_type(1); for(auto i = r; i < pa; ++i) - acc *= na[i]; + acc *= value_type(na[i]); - for(auto i = 0ul; i < c.size(); ++i) + for(auto i = 0u; i < c.size(); ++i) BOOST_CHECK_EQUAL( c[i] , acc * a[0] * b[0] ); } diff --git a/test/tensor/test_operators_arithmetic.cpp b/test/tensor/test_operators_arithmetic.cpp index bb6382db8..f4e96afe4 100644 --- a/test/tensor/test_operators_arithmetic.cpp +++ b/test/tensor/test_operators_arithmetic.cpp @@ -5,9 +5,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. @@ -67,6 +67,17 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_binary_arithmetic_operations, valu for(auto i = 0ul; i < t.size(); ++i) BOOST_CHECK_EQUAL ( r(i), 3*t(i) + t2(i) ); + + r = t2 / (t+3) * (t+1) - t2; // r = ( t2/ ((t+3)*(t+1)) ) - t2 + + for(auto i = 0ul; i < t.size(); ++i) + BOOST_CHECK_EQUAL ( r(i), t2(i) / (t(i)+3)*(t(i)+1) - t2(i) ); + + r = 3+t2 / (t+3) * (t+1) * t - t2; // r = 3+( t2/ ((t+3)*(t+1)*t) ) - t2 + + for(auto i = 0ul; i < t.size(); ++i) + BOOST_CHECK_EQUAL ( r(i), 3+t2(i) / (t(i)+3)*(t(i)+1)*t(i) - t2(i) ); + r = t2 - t + t2 - t; for(auto i = 0ul; i < r.size(); ++i) diff --git a/test/tensor/test_operators_comparison.cpp b/test/tensor/test_operators_comparison.cpp index 7c5bfe37b..8b0bb0826 100644 --- a/test/tensor/test_operators_comparison.cpp +++ b/test/tensor/test_operators_comparison.cpp @@ -5,9 +5,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. diff --git a/test/tensor/test_strides.cpp b/test/tensor/test_strides.cpp index 9131bf46e..d42cf44e9 100644 --- a/test/tensor/test_strides.cpp +++ b/test/tensor/test_strides.cpp @@ -5,9 +5,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. + diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index ac37c948d..8f873e6a3 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -5,14 +5,14 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. #include -#include +#include #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE TestTensor @@ -461,12 +461,10 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_standard_iterator, value, test_ty BOOST_CHECK_EQUAL( std::distance(t.cbegin(), t.cend ()), t.size() ); BOOST_CHECK_EQUAL( std::distance(t.crbegin(), t.crend()), t.size() ); - BOOST_CHECK( t.data() == std::addressof( *t.begin () ) ) ; - BOOST_CHECK( t.data() == std::addressof( *t.cbegin() ) ) ; - - BOOST_CHECK( (t.data()+t.size()) == std::addressof( *t.end () ) ) ; - BOOST_CHECK( (t.data()+t.size()) == std::addressof( *t.cend() ) ) ; - + if(t.size() > 0) { + BOOST_CHECK( t.data() == std::addressof( *t.begin () ) ) ; + BOOST_CHECK( t.data() == std::addressof( *t.cbegin() ) ) ; + } } } diff --git a/test/tensor/test_tensor_matrix_vector.cpp b/test/tensor/test_tensor_matrix_vector.cpp index 14e25e8b3..e30b5d4fc 100644 --- a/test/tensor/test_tensor_matrix_vector.cpp +++ b/test/tensor/test_tensor_matrix_vector.cpp @@ -5,9 +5,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. #include diff --git a/test/tensor/utility.hpp b/test/tensor/utility.hpp index 3dcbf6df5..e071ee101 100644 --- a/test/tensor/utility.hpp +++ b/test/tensor/utility.hpp @@ -1,4 +1,3 @@ -// // Copyright (c) 2018 // Cem Bassoy // @@ -7,9 +6,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB in producing this work. +// Fraunhofer and Google in producing this work +// which started as a Google Summer of Code project. // -// And we acknowledge the support from all contributors. #ifndef _BOOST_UBLAS_TEST_TENSOR_UTILITY_ #define _BOOST_UBLAS_TEST_TENSOR_UTILITY_ @@ -48,12 +47,8 @@ template using zip = zip_helper,types...>; // creates e.g. -//using test_types = -//std::tuple< -//std::pair, -//std::pair, -//std::pair, -//std::pair +// using test_types = zip::with_t; // equals +// using test_types = std::tuple< std::pair, std::pair, std::pair, std::pair //>; //static_assert(std::is_same< std::tuple_element_t<0,std::tuple_element_t<0,test_types2>>, float>::value,"should be float "); //static_assert(std::is_same< std::tuple_element_t<1,std::tuple_element_t<0,test_types2>>, boost::numeric::ublas::first_order>::value,"should be boost::numeric::ublas::first_order "); From 1e71db9cda4f01b661aec27e576509dffb7415fd Mon Sep 17 00:00:00 2001 From: Cem Bassoy Date: Tue, 19 Feb 2019 09:34:41 +0100 Subject: [PATCH 72/73] tensor gsoc 2018. last changes for merge. --- .appveyor.yml | 8 +- .travis.yml | 24 +- IDEs/qtcreator/benchmarks/bench1/bench1.pro | 16 - IDEs/qtcreator/benchmarks/bench2/bench2.pro | 16 - IDEs/qtcreator/benchmarks/bench3/bench3.pro | 16 - IDEs/qtcreator/benchmarks/bench4/bench4.pro | 15 - IDEs/qtcreator/benchmarks/bench5/bench5.pro | 12 - IDEs/qtcreator/benchmarks/benchmarks.pro | 2 - IDEs/qtcreator/benchmarks/configuration.pri | 15 - .../example_construction_access.pro | 7 + .../example_einstein_notation.pro | 7 + .../example_construction_access.pro | 7 - .../example_einstein_notation.pro | 7 - .../example_prod_expressions.pro | 7 - .../example_simple_expressions.pro | 7 - .../example_prod_expressions.pro | 7 + .../example_simple_expressions.pro | 7 + IDEs/qtcreator/examples/tensor/tensor.pro | 9 +- IDEs/qtcreator/tests.pri | 4 - IDEs/qtcreator/ublas_develop.pro | 5 +- Jamfile.v2 | 17 - README.md | 19 +- examples/tensor/{Jamfile.v2 => Jamfile} | 10 +- ...ion_access.cpp => construction_access.cpp} | 4 +- ...ein_notation.cpp => einstein_notation.cpp} | 4 +- ...d_expressions.cpp => prod_expressions.cpp} | 4 +- ...expressions.cpp => simple_expressions.cpp} | 4 +- .../boost/numeric/ublas/matrix_expression.hpp | 10330 ++++++++-------- include/boost/numeric/ublas/matrix_sparse.hpp | 2 +- .../boost/numeric/ublas/operation/begin.hpp | 566 +- .../boost/numeric/ublas/storage_sparse.hpp | 2 +- include/boost/numeric/ublas/tensor.hpp | 12 +- .../boost/numeric/ublas/tensor/algorithm.hpp | 680 - .../boost/numeric/ublas/tensor/algorithms.hpp | 50 +- .../boost/numeric/ublas/tensor/expression.hpp | 22 +- .../ublas/tensor/expression_evaluation.hpp | 82 +- .../boost/numeric/ublas/tensor/extents.hpp | 47 +- .../boost/numeric/ublas/tensor/functions.hpp | 122 +- include/boost/numeric/ublas/tensor/index.hpp | 8 +- .../numeric/ublas/tensor/multi_index.hpp | 18 +- .../ublas/tensor/multi_index_utility.hpp | 18 +- .../numeric/ublas/tensor/multiplication.hpp | 136 +- .../ublas/tensor/operators_arithmetic.hpp | 8 +- .../ublas/tensor/operators_comparison.hpp | 8 +- .../boost/numeric/ublas/tensor/ostream.hpp | 8 +- .../boost/numeric/ublas/tensor/strides.hpp | 17 +- include/boost/numeric/ublas/tensor/tensor.hpp | 6 +- .../boost/numeric/ublas/vector_of_vector.hpp | 4 +- include/boost/numeric/ublas/vector_sparse.hpp | 2 +- test/Jamfile | 2 +- test/tensor/Jamfile | 42 + test/tensor/Jamfile.v2 | 22 - test/tensor/test_algorithms.cpp | 55 +- test/tensor/test_einstein_notation.cpp | 28 +- test/tensor/test_expression.cpp | 48 +- test/tensor/test_expression_evaluation.cpp | 44 +- test/tensor/test_extents.cpp | 40 +- test/tensor/test_functions.cpp | 62 +- test/tensor/test_multi_index.cpp | 19 +- test/tensor/test_multi_index_utility.cpp | 6 +- test/tensor/test_multiplication.cpp | 120 +- test/tensor/test_operators_arithmetic.cpp | 38 +- test/tensor/test_operators_comparison.cpp | 15 +- test/tensor/test_strides.cpp | 6 +- test/tensor/test_tensor.cpp | 38 +- test/tensor/test_tensor_matrix_vector.cpp | 18 +- test/tensor/utility.hpp | 2 +- test/triangular_layout.cpp | 244 +- 68 files changed, 6260 insertions(+), 6997 deletions(-) delete mode 100644 IDEs/qtcreator/benchmarks/bench1/bench1.pro delete mode 100644 IDEs/qtcreator/benchmarks/bench2/bench2.pro delete mode 100644 IDEs/qtcreator/benchmarks/bench3/bench3.pro delete mode 100644 IDEs/qtcreator/benchmarks/bench4/bench4.pro delete mode 100644 IDEs/qtcreator/benchmarks/bench5/bench5.pro delete mode 100644 IDEs/qtcreator/benchmarks/benchmarks.pro delete mode 100644 IDEs/qtcreator/benchmarks/configuration.pri create mode 100644 IDEs/qtcreator/examples/tensor/construction_access/example_construction_access.pro create mode 100644 IDEs/qtcreator/examples/tensor/einstein_notation/example_einstein_notation.pro delete mode 100644 IDEs/qtcreator/examples/tensor/example_construction_access/example_construction_access.pro delete mode 100644 IDEs/qtcreator/examples/tensor/example_einstein_notation/example_einstein_notation.pro delete mode 100644 IDEs/qtcreator/examples/tensor/example_prod_expressions/example_prod_expressions.pro delete mode 100644 IDEs/qtcreator/examples/tensor/example_simple_expressions/example_simple_expressions.pro create mode 100644 IDEs/qtcreator/examples/tensor/prod_expressions/example_prod_expressions.pro create mode 100644 IDEs/qtcreator/examples/tensor/simple_expressions/example_simple_expressions.pro delete mode 100644 Jamfile.v2 rename examples/tensor/{Jamfile.v2 => Jamfile} (69%) rename examples/tensor/{example_construction_access.cpp => construction_access.cpp} (96%) rename examples/tensor/{example_einstein_notation.cpp => einstein_notation.cpp} (97%) rename examples/tensor/{example_prod_expressions.cpp => prod_expressions.cpp} (98%) rename examples/tensor/{example_simple_expressions.cpp => simple_expressions.cpp} (94%) delete mode 100644 include/boost/numeric/ublas/tensor/algorithm.hpp create mode 100644 test/tensor/Jamfile delete mode 100644 test/tensor/Jamfile.v2 diff --git a/.appveyor.yml b/.appveyor.yml index 232e72303..527af3598 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,8 +10,6 @@ branches: only: - master - develop - - tensor - - subtensor - /feature\/.*/ environment: @@ -19,6 +17,9 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 TOOLSET: msvc-14.1 CXXSTD: 17 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + TOOLSET: msvc-14.0 + CXXSTD: 11 cache: - c:\tools\vcpkg\installed\ @@ -59,7 +60,7 @@ install: using clblas : : $(vcpkg_i) $(vcpkg_l) ; '@ | sc "$env:USERPROFILE/user-config.jam" - cmd /c bootstrap - - b2 -d0 headers + - b2 -j3 headers build: off @@ -69,3 +70,4 @@ test_script: - set ADDRMD=address-model=64 - b2 -j3 libs/numeric/ublas/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% - b2 -j3 libs/numeric/ublas/benchmarks toolset=%TOOLSET% %CXXSTD% %ADDRMD% + - b2 -j3 libs/numeric/ublas/examples/tensor toolset=%TOOLSET% %CXXSTD% %ADDRMD% diff --git a/.travis.yml b/.travis.yml index fcc5b8f1e..6d9eac8ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,6 @@ branches: only: - master - develop - - tensor - - subtensor - doc - ci @@ -26,8 +24,10 @@ env: matrix: include: - os: linux - env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++17 - + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=11 + - os: linux + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=17 + addons: apt: sources: @@ -52,27 +52,29 @@ install: - cd .. - git clone -b master --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - - git submodule update --init tools/build - - git submodule update --init libs/config - - git submodule update --init tools/boostdep + - git submodule update --init --jobs 8 tools/build + - git submodule update --init --jobs 8 libs/config + - git submodule update --init --jobs 8 tools/boostdep - mkdir -p libs/numeric/ - cp -r $TRAVIS_BUILD_DIR/* libs/numeric/ublas - python tools/boostdep/depinst/depinst.py -I benchmarks numeric/ublas - ./bootstrap.sh - - ./b2 headers + - ./b2 -j 8 headers # Use before_script: to run configure steps before_script: + # use script: to execute build steps script: - |- - echo "using $TOOLSET : : $COMPILER : -std=$CXXSTD ;" >> ~/user-config.jam; + echo "using $TOOLSET : : $COMPILER ;" >> ~/user-config.jam; echo "using clblas : : ${CLBLAS_PREFIX}/include ${CLBLAS_PREFIX}/lib ;" >> ~/user-config.jam; cp $TRAVIS_BUILD_DIR/opencl.jam ~/ cp $TRAVIS_BUILD_DIR/clblas.jam ~/ - - ./b2 libs/numeric/ublas/test toolset=$TOOLSET - - ./b2 libs/numeric/ublas/benchmarks toolset=$TOOLSET + - ./b2 -j 8 libs/numeric/ublas/test toolset=$TOOLSET cxxstd=$CXXSTD + - ./b2 -j 8 libs/numeric/ublas/benchmarks toolset=$TOOLSET cxxstd=$CXXSTD + - ./b2 -j 8 libs/numeric/ublas/examples/tensor toolset=$TOOLSET cxxstd=$CXXSTD notifications: email: diff --git a/IDEs/qtcreator/benchmarks/bench1/bench1.pro b/IDEs/qtcreator/benchmarks/bench1/bench1.pro deleted file mode 100644 index c580b766c..000000000 --- a/IDEs/qtcreator/benchmarks/bench1/bench1.pro +++ /dev/null @@ -1,16 +0,0 @@ -TEMPLATE = app -TARGET = bench1 - -include (../configuration.pri) - -OTHER_FILES += \ - ../../../../benchmarks/bench1/Jamfile.v2 - -HEADERS += \ - ../../../../benchmarks/bench1/bench1.hpp - -SOURCES += \ - ../../../../benchmarks/bench1/bench13.cpp \ - ../../../../benchmarks/bench1/bench12.cpp \ - ../../../../benchmarks/bench1/bench11.cpp \ - ../../../../benchmarks/bench1/bench1.cpp diff --git a/IDEs/qtcreator/benchmarks/bench2/bench2.pro b/IDEs/qtcreator/benchmarks/bench2/bench2.pro deleted file mode 100644 index 80132f6eb..000000000 --- a/IDEs/qtcreator/benchmarks/bench2/bench2.pro +++ /dev/null @@ -1,16 +0,0 @@ -TEMPLATE = app -TARGET = bench2 - -include (../configuration.pri) - -OTHER_FILES += \ - ../../../../benchmarks/bench2/Jamfile.v2 - -HEADERS += \ - ../../../../benchmarks/bench2/bench2.hpp - -SOURCES += \ - ../../../../benchmarks/bench2/bench23.cpp \ - ../../../../benchmarks/bench2/bench22.cpp \ - ../../../../benchmarks/bench2/bench21.cpp \ - ../../../../benchmarks/bench2/bench2.cpp diff --git a/IDEs/qtcreator/benchmarks/bench3/bench3.pro b/IDEs/qtcreator/benchmarks/bench3/bench3.pro deleted file mode 100644 index 256b22056..000000000 --- a/IDEs/qtcreator/benchmarks/bench3/bench3.pro +++ /dev/null @@ -1,16 +0,0 @@ -TEMPLATE = app -TARGET = bench3 - -include (../configuration.pri) - -OTHER_FILES += \ - ../../../../benchmarks/bench3/Jamfile.v2 - -HEADERS += \ - ../../../../benchmarks/bench3/bench3.hpp - -SOURCES += \ - ../../../../benchmarks/bench3/bench33.cpp \ - ../../../../benchmarks/bench3/bench32.cpp \ - ../../../../benchmarks/bench3/bench31.cpp \ - ../../../../benchmarks/bench3/bench3.cpp diff --git a/IDEs/qtcreator/benchmarks/bench4/bench4.pro b/IDEs/qtcreator/benchmarks/bench4/bench4.pro deleted file mode 100644 index d1b6f30bf..000000000 --- a/IDEs/qtcreator/benchmarks/bench4/bench4.pro +++ /dev/null @@ -1,15 +0,0 @@ -TEMPLATE = app -TARGET = bench4 - -include (../configuration.pri) - -DEFINES += BOOST_UBLAS_USE_INTERVAL - -OTHER_FILES += \ - ../../../../benchmarks/bench4/Jamfile.v2 - -SOURCES += \ - ../../../../benchmarks/bench4/bench43.cpp \ - ../../../../benchmarks/bench4/bench42.cpp \ - ../../../../benchmarks/bench4/bench41.cpp \ - ../../../../benchmarks/bench4/bench4.cpp diff --git a/IDEs/qtcreator/benchmarks/bench5/bench5.pro b/IDEs/qtcreator/benchmarks/bench5/bench5.pro deleted file mode 100644 index b561cdc6f..000000000 --- a/IDEs/qtcreator/benchmarks/bench5/bench5.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app -TARGET = bench5 - -include (../configuration.pri) - -DEFINES += BOOST_UBLAS_USE_INTERVAL - -OTHER_FILES += \ - ../../../../benchmarks/bench5/Jamfile.v2 - -SOURCES += \ - ../../../../benchmarks/bench5/assignment_bench.cpp diff --git a/IDEs/qtcreator/benchmarks/benchmarks.pro b/IDEs/qtcreator/benchmarks/benchmarks.pro deleted file mode 100644 index 4acf2d693..000000000 --- a/IDEs/qtcreator/benchmarks/benchmarks.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = bench1 bench2 bench3 bench4 bench5 diff --git a/IDEs/qtcreator/benchmarks/configuration.pri b/IDEs/qtcreator/benchmarks/configuration.pri deleted file mode 100644 index a7bc632a1..000000000 --- a/IDEs/qtcreator/benchmarks/configuration.pri +++ /dev/null @@ -1,15 +0,0 @@ -CONFIG -= qt -CONFIG += depend_includepath -win*: CONFIG += console - -# ublas include directory -INCLUDEPATH += \ - ../../../../include - -# If ublas tests are build with boost source code then, -# then boost headers and boost libraries should be used. -exists(../../../../../../boost-build.jam) { - INCLUDEPATH += ../../../../../../.. - LIBS += -L../../../../../../../stage/lib - QMAKE_RPATHDIR += ../../../../../../../stage/lib -} diff --git a/IDEs/qtcreator/examples/tensor/construction_access/example_construction_access.pro b/IDEs/qtcreator/examples/tensor/construction_access/example_construction_access.pro new file mode 100644 index 000000000..8d6abef37 --- /dev/null +++ b/IDEs/qtcreator/examples/tensor/construction_access/example_construction_access.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = construction_access + +include (../../configuration.pri) + +SOURCES += \ + ../../../../../examples/tensor/construction_access.cpp diff --git a/IDEs/qtcreator/examples/tensor/einstein_notation/example_einstein_notation.pro b/IDEs/qtcreator/examples/tensor/einstein_notation/example_einstein_notation.pro new file mode 100644 index 000000000..302b02a10 --- /dev/null +++ b/IDEs/qtcreator/examples/tensor/einstein_notation/example_einstein_notation.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = einstein_notation + +include (../../configuration.pri) + +SOURCES += \ + ../../../../../examples/tensor/einstein_notation.cpp diff --git a/IDEs/qtcreator/examples/tensor/example_construction_access/example_construction_access.pro b/IDEs/qtcreator/examples/tensor/example_construction_access/example_construction_access.pro deleted file mode 100644 index ca5d11df9..000000000 --- a/IDEs/qtcreator/examples/tensor/example_construction_access/example_construction_access.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -TARGET = texample01 - -include (../../configuration.pri) - -SOURCES += \ - ../../../../../examples/tensor/example_construction_access.cpp diff --git a/IDEs/qtcreator/examples/tensor/example_einstein_notation/example_einstein_notation.pro b/IDEs/qtcreator/examples/tensor/example_einstein_notation/example_einstein_notation.pro deleted file mode 100644 index 41ba30d1a..000000000 --- a/IDEs/qtcreator/examples/tensor/example_einstein_notation/example_einstein_notation.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -TARGET = texample03 - -include (../../configuration.pri) - -SOURCES += \ - ../../../../../examples/tensor/example_einstein_notation.cpp diff --git a/IDEs/qtcreator/examples/tensor/example_prod_expressions/example_prod_expressions.pro b/IDEs/qtcreator/examples/tensor/example_prod_expressions/example_prod_expressions.pro deleted file mode 100644 index f5b57b312..000000000 --- a/IDEs/qtcreator/examples/tensor/example_prod_expressions/example_prod_expressions.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -TARGET = texample03 - -include (../../configuration.pri) - -SOURCES += \ - ../../../../../examples/tensor/example_prod_expressions.cpp diff --git a/IDEs/qtcreator/examples/tensor/example_simple_expressions/example_simple_expressions.pro b/IDEs/qtcreator/examples/tensor/example_simple_expressions/example_simple_expressions.pro deleted file mode 100644 index f38276aed..000000000 --- a/IDEs/qtcreator/examples/tensor/example_simple_expressions/example_simple_expressions.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -TARGET = texample02 - -include (../../configuration.pri) - -SOURCES += \ - ../../../../../examples/tensor/example_simple_expressions.cpp diff --git a/IDEs/qtcreator/examples/tensor/prod_expressions/example_prod_expressions.pro b/IDEs/qtcreator/examples/tensor/prod_expressions/example_prod_expressions.pro new file mode 100644 index 000000000..2e210c249 --- /dev/null +++ b/IDEs/qtcreator/examples/tensor/prod_expressions/example_prod_expressions.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = prod_expression + +include (../../configuration.pri) + +SOURCES += \ + ../../../../../examples/tensor/prod_expressions.cpp diff --git a/IDEs/qtcreator/examples/tensor/simple_expressions/example_simple_expressions.pro b/IDEs/qtcreator/examples/tensor/simple_expressions/example_simple_expressions.pro new file mode 100644 index 000000000..3b106c9f3 --- /dev/null +++ b/IDEs/qtcreator/examples/tensor/simple_expressions/example_simple_expressions.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = simple_expressions + +include (../../configuration.pri) + +SOURCES += \ + ../../../../../examples/tensor/simple_expressions.cpp diff --git a/IDEs/qtcreator/examples/tensor/tensor.pro b/IDEs/qtcreator/examples/tensor/tensor.pro index dea38ec2e..d50e56c61 100644 --- a/IDEs/qtcreator/examples/tensor/tensor.pro +++ b/IDEs/qtcreator/examples/tensor/tensor.pro @@ -1,2 +1,9 @@ TEMPLATE = subdirs -SUBDIRS = example_construction_access example_simple_expressions example_prod_expressions example_einstein_notation +SUBDIRS = construction_access simple_expressions prod_expressions einstein_notation + + +construction_access.file = construction_access/example_construction_access.pro +simple_expressions.file = simple_expressions/example_simple_expressions.pro +prod_expressions.file = prod_expressions/example_prod_expressions.pro +einstein_notation.file = einstein_notation/example_einstein_notation.pro + diff --git a/IDEs/qtcreator/tests.pri b/IDEs/qtcreator/tests.pri index 2234436a7..7b55d478c 100644 --- a/IDEs/qtcreator/tests.pri +++ b/IDEs/qtcreator/tests.pri @@ -1,7 +1,3 @@ -OTHER_FILES += \ - ../../test/README \ - ../../test/Jamfile.v2 - SUBDIRS += \ begin_end \ comp_mat_erase \ diff --git a/IDEs/qtcreator/ublas_develop.pro b/IDEs/qtcreator/ublas_develop.pro index f495a9355..8139f2493 100644 --- a/IDEs/qtcreator/ublas_develop.pro +++ b/IDEs/qtcreator/ublas_develop.pro @@ -4,10 +4,7 @@ SUBDIRS = include examples # benchmarks OTHER_FILES += ../../changelog.txt -SUBDIRS += test_tensor -test_tensor.file = test/test_tensor.pro - -#include (tests.pri) +include (tests.pri) diff --git a/Jamfile.v2 b/Jamfile.v2 deleted file mode 100644 index 3586e73f4..000000000 --- a/Jamfile.v2 +++ /dev/null @@ -1,17 +0,0 @@ -# Boost.uBLAS -# -# Copyright (c) 2018 Cem Bassoy -# -# Use, modification and distribution is subject to the Boost Software License, -# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - - -# Project settings -project boost-ublas-tensor - : # requirements - ; - -build-project test/tensor ; -build-project examples/tensor ; -#build-project doc/src/examples ; \ No newline at end of file diff --git a/README.md b/README.md index 5a34f7df1..66e2b271f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,19 @@ -Boost.uBLAS Linear Algebra Library +Boost.uBLAS Linear Algebra Library ===== Boost.uBLAS is part of the [Boost C++ Libraries](http://github.com/boostorg). It is directed towards scientific computing on the level of basic linear algebra constructions with matrices and vectors and their corresponding abstract operations. -## Fork -This fork contains an additional branch tensor that has been created for adding tensor support as a Google Summer of Code 2018 project. All details about the project and code is found on the [wiki page](https://github.com/BoostGSoC18/tensor/wiki). -## License +## Documentation +uBLAS is documented at [boost.org](https://www.boost.org/doc/libs/1_69_0/libs/numeric/ublas/doc/index.html). +The development has a [wiki page](https://github.com/uBLAS/ublas/wiki). +The tensor extension has a separate [wiki page](https://github.com/BoostGSoC18/tensor/wiki). +## License Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). ## Properties - * Header-only -* Requires C++17 compatible compiler, compiles with +* Tensor extension requires C++17 compatible compiler, compiles with * gcc 7.3.0 * clang 6.0 * msvc 14.1 @@ -22,8 +23,9 @@ Distributed under the [Boost Software License, Version 1.0](http://www.boost.org Branch | Travis | Appveyor | codecov.io | Docs | :-------------: | ------ | -------- | ---------- | ---- | -[`develop`](https://travis-ci.org/boostorg/ublas.svg?branch=develop) | [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=develop)](https://travis-ci.org/boostorg/ublas) | [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/uuid/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/uuid/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/numeric) -[`tensor`](https://travis-ci.org/BoostGSoC18/tensor.svg?branch=tensor) | [![Build Status](https://travis-ci.org/BoostGSoC18/tensor.svg?branch=tensor)](https://travis-ci.org/BoostGSoC18/tensor) | [![Build status](https://ci.appveyor.com/api/projects/status/github/BoostGSoC18/tensor?branch=tensor&svg=true)](https://ci.appveyor.com/project/ti6csb/tensor) | [![codecov](https://codecov.io/gh/boostorg/uuid/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/uuid/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/numeric) +[`master`](https://github.com/boostorg/ublas/tree/master) | [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=master)](https://travis-ci.org/boostorg/ublas) | [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/master?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/master) | [![codecov](https://codecov.io/gh/boostorg/ublas/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/ublas/branch/master) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/numeric) +[`develop`](https://github.com/boostorg/ublas/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/ublas.svg?branch=develop)](https://travis-ci.org/boostorg/ublas) | [![Build status](https://ci.appveyor.com/api/projects/status/ctu3wnfowa627ful/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/ublas/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/ublas/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/ublas/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/numeric) + ## Directories @@ -33,6 +35,7 @@ Branch | Travis | Appveyor | codecov.io | Docs | | `examples` | example files | | `include` | headers | | `test` | unit tests | +| `benchmarks`| timing and benchmarking | ## More information diff --git a/examples/tensor/Jamfile.v2 b/examples/tensor/Jamfile similarity index 69% rename from examples/tensor/Jamfile.v2 rename to examples/tensor/Jamfile index 35c006815..42f2fe633 100644 --- a/examples/tensor/Jamfile.v2 +++ b/examples/tensor/Jamfile @@ -10,6 +10,8 @@ # Project settings project boost-ublas-tensor-example : requirements + # these tests require C++17 + 11:no BOOST_UBLAS_NO_EXCEPTIONS vacpp:"BOOST_UBLAS_NO_ELEMENT_PROXIES" gcc:"-Wall -pedantic -Wextra -std=c++17" @@ -17,7 +19,7 @@ project boost-ublas-tensor-example msvc:"/W4" # == all ; -exe example_construction_access : example_construction_access.cpp ; -exe example_simple_expressions : example_simple_expressions.cpp ; -exe example_prod_expressions : example_prod_expressions.cpp ; -exe example_einstein_notation : example_einstein_notation.cpp ; \ No newline at end of file +exe construction_access : construction_access.cpp ; +exe simple_expressions : simple_expressions.cpp ; +exe prod_expressions : prod_expressions.cpp ; +exe einstein_notation : einstein_notation.cpp ; \ No newline at end of file diff --git a/examples/tensor/example_construction_access.cpp b/examples/tensor/construction_access.cpp similarity index 96% rename from examples/tensor/example_construction_access.cpp rename to examples/tensor/construction_access.cpp index 600239288..053690c79 100644 --- a/examples/tensor/example_construction_access.cpp +++ b/examples/tensor/construction_access.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // #include diff --git a/examples/tensor/example_einstein_notation.cpp b/examples/tensor/einstein_notation.cpp similarity index 97% rename from examples/tensor/example_einstein_notation.cpp rename to examples/tensor/einstein_notation.cpp index 0eed3f094..1d95fc06b 100644 --- a/examples/tensor/example_einstein_notation.cpp +++ b/examples/tensor/einstein_notation.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // diff --git a/examples/tensor/example_prod_expressions.cpp b/examples/tensor/prod_expressions.cpp similarity index 98% rename from examples/tensor/example_prod_expressions.cpp rename to examples/tensor/prod_expressions.cpp index 6c0110d89..6ff725214 100644 --- a/examples/tensor/example_prod_expressions.cpp +++ b/examples/tensor/prod_expressions.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // diff --git a/examples/tensor/example_simple_expressions.cpp b/examples/tensor/simple_expressions.cpp similarity index 94% rename from examples/tensor/example_simple_expressions.cpp rename to examples/tensor/simple_expressions.cpp index e086874e7..fabb00f4b 100644 --- a/examples/tensor/example_simple_expressions.cpp +++ b/examples/tensor/simple_expressions.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // diff --git a/include/boost/numeric/ublas/matrix_expression.hpp b/include/boost/numeric/ublas/matrix_expression.hpp index 7576c3a5d..b09ad7fa9 100644 --- a/include/boost/numeric/ublas/matrix_expression.hpp +++ b/include/boost/numeric/ublas/matrix_expression.hpp @@ -22,5671 +22,5671 @@ namespace boost { namespace numeric { namespace ublas { - template - class matrix_reference: - public matrix_expression > { +template +class matrix_reference: + public matrix_expression > { - typedef matrix_reference self_type; - public: + typedef matrix_reference self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename E::size_type size_type; - typedef typename E::difference_type difference_type; - typedef typename E::value_type value_type; - typedef typename E::const_reference const_reference; - typedef typename boost::mpl::if_, - typename E::const_reference, - typename E::reference>::type reference; - typedef E referred_type; - typedef const self_type const_closure_type; - typedef self_type closure_type; - typedef typename E::orientation_category orientation_category; - typedef typename E::storage_category storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - explicit matrix_reference (referred_type &e): - e_ (e) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e_.size1 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e_.size2 (); - } - - public: - // Expression accessors - const correct - BOOST_UBLAS_INLINE - const referred_type &expression () const { - return e_; - } - BOOST_UBLAS_INLINE - referred_type &expression () { - return e_; - } - - public: - // Element access + using matrix_expression::operator (); +#endif + typedef typename E::size_type size_type; + typedef typename E::difference_type difference_type; + typedef typename E::value_type value_type; + typedef typename E::const_reference const_reference; + typedef typename boost::mpl::if_, + typename E::const_reference, + typename E::reference>::type reference; + typedef E referred_type; + typedef const self_type const_closure_type; + typedef self_type closure_type; + typedef typename E::orientation_category orientation_category; + typedef typename E::storage_category storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + explicit matrix_reference (referred_type &e): + e_ (e) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e_.size1 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e_.size2 (); + } + +public: + // Expression accessors - const correct + BOOST_UBLAS_INLINE + const referred_type &expression () const { + return e_; + } + BOOST_UBLAS_INLINE + referred_type &expression () { + return e_; + } + +public: + // Element access #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return expression () (i, j); - } - BOOST_UBLAS_INLINE - reference operator () (size_type i, size_type j) { - return expression () (i, j); - } + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return expression () (i, j); + } + BOOST_UBLAS_INLINE + reference operator () (size_type i, size_type j) { + return expression () (i, j); + } #else - BOOST_UBLAS_INLINE - reference operator () (size_type i, size_type j) const { - return expression () (i, j); - } + BOOST_UBLAS_INLINE + reference operator () (size_type i, size_type j) const { + return expression () (i, j); + } #endif #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return expression () (i); - } - BOOST_UBLAS_INLINE - reference operator () (size_type i) { - return expression () (i); - } + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return expression () (i); + } + BOOST_UBLAS_INLINE + reference operator () (size_type i) { + return expression () (i); + } #else - BOOST_UBLAS_INLINE - reference operator () (size_type i) const { - return expression () (i); - } -#endif - - - // Assignment - BOOST_UBLAS_INLINE - matrix_reference &operator = (const matrix_reference &m) { - expression ().operator = (m); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &operator = (const matrix_expression &ae) { - expression ().operator = (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &assign (const matrix_expression &ae) { - expression ().assign (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &operator += (const matrix_expression &ae) { - expression ().operator += (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &plus_assign (const matrix_expression &ae) { - expression ().plus_assign (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &operator -= (const matrix_expression &ae) { - expression ().operator -= (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &minus_assign (const matrix_expression &ae) { - expression ().minus_assign (ae); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &operator *= (const AT &at) { - expression ().operator *= (at); - return *this; - } - template - BOOST_UBLAS_INLINE - matrix_reference &operator /= (const AT &at) { - expression ().operator /= (at); - return *this; - } - - // Swapping - BOOST_UBLAS_INLINE - void swap (matrix_reference &m) { - expression ().swap (m.expression ()); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_reference &mr) const { - return &(*this).e_ == &mr.e_; - } - - // Iterator types - typedef typename E::const_iterator1 const_iterator1; - typedef typename boost::mpl::if_, - typename E::const_iterator1, - typename E::iterator1>::type iterator1; - typedef typename E::const_iterator2 const_iterator2; - typedef typename boost::mpl::if_, - typename E::const_iterator2, - typename E::iterator2>::type iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - return expression ().find1 (rank, i, j); - } - BOOST_UBLAS_INLINE - iterator1 find1 (int rank, size_type i, size_type j) { - return expression ().find1 (rank, i, j); - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - return expression ().find2 (rank, i, j); - } - BOOST_UBLAS_INLINE - iterator2 find2 (int rank, size_type i, size_type j) { - return expression ().find2 (rank, i, j); - } - - // Iterators are the iterators of the referenced expression. - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return expression ().begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return expression ().end1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } - - BOOST_UBLAS_INLINE - iterator1 begin1 () { - return expression ().begin1 (); - } - BOOST_UBLAS_INLINE - iterator1 end1 () { - return expression ().end1 (); - } - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return expression ().begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return expression ().end2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - BOOST_UBLAS_INLINE - iterator2 begin2 () { - return expression ().begin2 (); - } - BOOST_UBLAS_INLINE - iterator2 end2 () { - return expression ().end2 (); - } - - // Reverse iterators - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base1 reverse_iterator1; - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - reverse_iterator1 rbegin1 () { - return reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - reverse_iterator1 rend1 () { - return reverse_iterator1 (begin1 ()); - } - - typedef reverse_iterator_base2 const_reverse_iterator2; - typedef reverse_iterator_base2 reverse_iterator2; - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - BOOST_UBLAS_INLINE - reverse_iterator2 rbegin2 () { - return reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - reverse_iterator2 rend2 () { - return reverse_iterator2 (begin2 ()); - } - - private: - referred_type &e_; - }; - - - template - class vector_matrix_binary: - public matrix_expression > { - - typedef E1 expression1_type; - typedef E2 expression2_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - private: - typedef vector_matrix_binary self_type; - public: + BOOST_UBLAS_INLINE + reference operator () (size_type i) const { + return expression () (i); + } +#endif + + + // Assignment + BOOST_UBLAS_INLINE + matrix_reference &operator = (const matrix_reference &m) { + expression ().operator = (m); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &operator = (const matrix_expression &ae) { + expression ().operator = (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &assign (const matrix_expression &ae) { + expression ().assign (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &operator += (const matrix_expression &ae) { + expression ().operator += (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &plus_assign (const matrix_expression &ae) { + expression ().plus_assign (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &operator -= (const matrix_expression &ae) { + expression ().operator -= (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &minus_assign (const matrix_expression &ae) { + expression ().minus_assign (ae); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &operator *= (const AT &at) { + expression ().operator *= (at); + return *this; + } + template + BOOST_UBLAS_INLINE + matrix_reference &operator /= (const AT &at) { + expression ().operator /= (at); + return *this; + } + + // Swapping + BOOST_UBLAS_INLINE + void swap (matrix_reference &m) { + expression ().swap (m.expression ()); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_reference &mr) const { + return &(*this).e_ == &mr.e_; + } + + // Iterator types + typedef typename E::const_iterator1 const_iterator1; + typedef typename boost::mpl::if_, + typename E::const_iterator1, + typename E::iterator1>::type iterator1; + typedef typename E::const_iterator2 const_iterator2; + typedef typename boost::mpl::if_, + typename E::const_iterator2, + typename E::iterator2>::type iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + return expression ().find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator1 find1 (int rank, size_type i, size_type j) { + return expression ().find1 (rank, i, j); + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + return expression ().find2 (rank, i, j); + } + BOOST_UBLAS_INLINE + iterator2 find2 (int rank, size_type i, size_type j) { + return expression ().find2 (rank, i, j); + } + + // Iterators are the iterators of the referenced expression. + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return expression ().begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return expression ().end1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } + + BOOST_UBLAS_INLINE + iterator1 begin1 () { + return expression ().begin1 (); + } + BOOST_UBLAS_INLINE + iterator1 end1 () { + return expression ().end1 (); + } + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return expression ().begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return expression ().end2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + BOOST_UBLAS_INLINE + iterator2 begin2 () { + return expression ().begin2 (); + } + BOOST_UBLAS_INLINE + iterator2 end2 () { + return expression ().end2 (); + } + + // Reverse iterators + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base1 reverse_iterator1; + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + reverse_iterator1 rbegin1 () { + return reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator1 rend1 () { + return reverse_iterator1 (begin1 ()); + } + + typedef reverse_iterator_base2 const_reverse_iterator2; + typedef reverse_iterator_base2 reverse_iterator2; + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + + BOOST_UBLAS_INLINE + reverse_iterator2 rbegin2 () { + return reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + reverse_iterator2 rend2 () { + return reverse_iterator2 (begin2 ()); + } + +private: + referred_type &e_; +}; + + +template +class vector_matrix_binary: + public matrix_expression > { + + typedef E1 expression1_type; + typedef E2 expression2_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; +private: + typedef vector_matrix_binary self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef F functor_type; - typedef typename promote_traits::promote_type size_type; - typedef typename promote_traits::promote_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef unknown_orientation_tag orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - vector_matrix_binary (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e1_.size (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e2_.size (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression1_closure_type &expression1 () const { - return e1_; - } - BOOST_UBLAS_INLINE - const expression2_closure_type &expression2 () const { - return e2_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e1_ (i), e2_ (j)); - } - - - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const vector_matrix_binary &vmb) const { - return (*this).expression1 ().same_closure (vmb.expression1 ()) && - (*this).expression2 ().same_closure (vmb.expression2 ()); - } - - // Iterator types - private: - typedef typename E1::const_iterator const_subiterator1_type; - typedef typename E2::const_iterator const_subiterator2_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef F functor_type; + typedef typename promote_traits::promote_type size_type; + typedef typename promote_traits::promote_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef unknown_orientation_tag orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + vector_matrix_binary (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e1_.size (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e2_.size (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression1_closure_type &expression1 () const { + return e1_; + } + BOOST_UBLAS_INLINE + const expression2_closure_type &expression2 () const { + return e2_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e1_ (i), e2_ (j)); + } + + + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const vector_matrix_binary &vmb) const { + return (*this).expression1 ().same_closure (vmb.expression1 ()) && + (*this).expression2 ().same_closure (vmb.expression2 ()); + } + + // Iterator types +private: + typedef typename E1::const_iterator const_subiterator1_type; + typedef typename E2::const_iterator const_subiterator2_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_subiterator1_type it1 (e1_.find (i)); - const_subiterator1_type it1_end (e1_.find (size1 ())); - const_subiterator2_type it2 (e2_.find (j)); - const_subiterator2_type it2_end (e2_.find (size2 ())); - if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) { - it1 = it1_end; - it2 = it2_end; - } + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_subiterator1_type it1 (e1_.find (i)); + const_subiterator1_type it1_end (e1_.find (size1 ())); + const_subiterator2_type it2 (e2_.find (j)); + const_subiterator2_type it2_end (e2_.find (size2 ())); + if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) { + it1 = it1_end; + it2 = it2_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it1.index (), it2.index ()); + return const_iterator1 (*this, it1.index (), it2.index ()); #else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/()); + return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/()); #else - return const_iterator1 (*this, it1, it2); -#endif -#endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_subiterator2_type it2 (e2_.find (j)); - const_subiterator2_type it2_end (e2_.find (size2 ())); - const_subiterator1_type it1 (e1_.find (i)); - const_subiterator1_type it1_end (e1_.find (size1 ())); - if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) { - it2 = it2_end; - it1 = it1_end; - } + return const_iterator1 (*this, it1, it2); +#endif +#endif + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_subiterator2_type it2 (e2_.find (j)); + const_subiterator2_type it2_end (e2_.find (size2 ())); + const_subiterator1_type it1 (e1_.find (i)); + const_subiterator1_type it1_end (e1_.find (size1 ())); + if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) { + it2 = it2_end; + it1 = it1_end; + } #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, it1.index (), it2.index ()); + return const_iterator2 (*this, it1.index (), it2.index ()); #else #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/()); + return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/()); #else - return const_iterator2 (*this, it1, it2); + return const_iterator2 (*this, it1, it2); #endif #endif - } + } - // Iterators enhance the iterators of the referenced expressions - // with the binary functor. + // Iterators enhance the iterators of the referenced expressions + // with the binary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename vector_matrix_binary::difference_type difference_type; - typedef typename vector_matrix_binary::value_type value_type; - typedef typename vector_matrix_binary::const_reference reference; - typedef typename vector_matrix_binary::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction + class const_iterator1: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename vector_matrix_binary::difference_type difference_type; + typedef typename vector_matrix_binary::value_type value_type; + typedef typename vector_matrix_binary::const_reference reference; + typedef typename vector_matrix_binary::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ (), t2_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2): - container_const_reference (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {} + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ (), t2_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2): + container_const_reference (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {} #else - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2): - container_const_reference (vmb), it1_ (it1), it2_ (it2) {} -#endif - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it1_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it1_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ - it.it1_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2): + container_const_reference (vmb), it1_ (it1), it2_ (it2) {} +#endif + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it1_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it1_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ - it.it1_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (*it1_, t2_); + return functor_type::apply (*it1_, t2_); #else - return functor_type::apply (*it1_, *it2_); + return functor_type::apply (*it1_, *it2_); #endif - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - t2_ = it.t2_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ == it.it1_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ < it.it1_; - } - - private: + t2_ = it.t2_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ == it.it1_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ < it.it1_; + } + + private: #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - const_subiterator1_type it1_; - // Mutable due to assignment - /* const */ const_subiterator2_type it2_; - value_type t2_; + const_subiterator1_type it1_; + // Mutable due to assignment + /* const */ const_subiterator2_type it2_; + value_type t2_; #else - const_subiterator1_type it1_; - const_subiterator2_type it2_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + const_subiterator1_type it1_; + const_subiterator2_type it2_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename vector_matrix_binary::difference_type difference_type; - typedef typename vector_matrix_binary::value_type value_type; - typedef typename vector_matrix_binary::const_reference reference; - typedef typename vector_matrix_binary::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction + class const_iterator2: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename vector_matrix_binary::difference_type difference_type; + typedef typename vector_matrix_binary::value_type value_type; + typedef typename vector_matrix_binary::const_reference reference; + typedef typename vector_matrix_binary::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ (), t1_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1): - container_const_reference (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {} + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ (), t1_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1): + container_const_reference (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {} #else - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2): - container_const_reference (vmb), it1_ (it1), it2_ (it2) {} -#endif - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it2_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it2_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ - it.it2_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2): + container_const_reference (vmb), it1_ (it1), it2_ (it2) {} +#endif + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it2_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it2_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ - it.it2_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (t1_, *it2_); + return functor_type::apply (t1_, *it2_); #else - return functor_type::apply (*it1_, *it2_); + return functor_type::apply (*it1_, *it2_); #endif - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - t1_ = it.t1_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ == it.it2_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ < it.it2_; - } - - private: + t1_ = it.t1_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ == it.it2_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ < it.it2_; + } + + private: #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - // Mutable due to assignment - /* const */ const_subiterator1_type it1_; - const_subiterator2_type it2_; - value_type t1_; + // Mutable due to assignment + /* const */ const_subiterator1_type it1_; + const_subiterator2_type it2_; + value_type t1_; #else - const_subiterator1_type it1_; - const_subiterator2_type it2_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct vector_matrix_binary_traits { - typedef vector_matrix_binary expression_type; + const_subiterator1_type it1_; + const_subiterator2_type it2_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct vector_matrix_binary_traits { + typedef vector_matrix_binary expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - // ISSUE matrix is arbitary temporary type - typedef matrix result_type; -#endif - }; - - // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j] - template - BOOST_UBLAS_INLINE - typename vector_matrix_binary_traits >::result_type - outer_prod (const vector_expression &e1, - const vector_expression &e2) { - BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); - typedef typename vector_matrix_binary_traits >::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - template - class matrix_unary1: - public matrix_expression > { - - typedef E expression_type; - typedef F functor_type; - public: - typedef typename E::const_closure_type expression_closure_type; - private: - typedef matrix_unary1 self_type; - public: + // ISSUE matrix is arbitary temporary type + typedef matrix result_type; +#endif +}; + +// (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j] +template +BOOST_UBLAS_INLINE +typename vector_matrix_binary_traits >::result_type +outer_prod (const vector_expression &e1, + const vector_expression &e2) { + BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); + typedef typename vector_matrix_binary_traits >::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +template +class matrix_unary1: + public matrix_expression > { + + typedef E expression_type; + typedef F functor_type; +public: + typedef typename E::const_closure_type expression_closure_type; +private: + typedef matrix_unary1 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename E::size_type size_type; - typedef typename E::difference_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef typename E::orientation_category orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - explicit matrix_unary1 (const expression_type &e): - e_ (e) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e_.size1 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e_.size2 (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression_closure_type &expression () const { - return e_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e_ (i, j)); - } - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e_ (i)); - } - - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_unary1 &mu1) const { - return (*this).expression ().same_closure (mu1.expression ()); - } - - // Iterator types - private: - typedef typename E::const_iterator1 const_subiterator1_type; - typedef typename E::const_iterator2 const_subiterator2_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef typename E::size_type size_type; + typedef typename E::difference_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef typename E::orientation_category orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + explicit matrix_unary1 (const expression_type &e): + e_ (e) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e_.size1 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e_.size2 (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression_closure_type &expression () const { + return e_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e_ (i, j)); + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e_ (i)); + } + + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_unary1 &mu1) const { + return (*this).expression ().same_closure (mu1.expression ()); + } + + // Iterator types +private: + typedef typename E::const_iterator1 const_subiterator1_type; + typedef typename E::const_iterator2 const_subiterator2_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_subiterator1_type it1 (e_.find1 (rank, i, j)); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_subiterator1_type it1 (e_.find1 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it1.index1 (), it1.index2 ()); + return const_iterator1 (*this, it1.index1 (), it1.index2 ()); #else - return const_iterator1 (*this, it1); + return const_iterator1 (*this, it1); #endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_subiterator2_type it2 (e_.find2 (rank, i, j)); + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_subiterator2_type it2 (e_.find2 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, it2.index1 (), it2.index2 ()); + return const_iterator2 (*this, it2.index1 (), it2.index2 ()); #else - return const_iterator2 (*this, it2); + return const_iterator2 (*this, it2); #endif - } + } - // Iterators enhance the iterators of the referenced expression - // with the unary functor. + // Iterators enhance the iterators of the referenced expression + // with the unary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E::const_iterator1::iterator_category iterator_category; - typedef typename matrix_unary1::difference_type difference_type; - typedef typename matrix_unary1::value_type value_type; - typedef typename matrix_unary1::const_reference reference; - typedef typename matrix_unary1::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mu, const const_subiterator1_type &it): - container_const_reference (mu), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator1: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E::const_iterator1::iterator_category iterator_category; + typedef typename matrix_unary1::difference_type difference_type; + typedef typename matrix_unary1::value_type value_type; + typedef typename matrix_unary1::const_reference reference; + typedef typename matrix_unary1::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mu, const const_subiterator1_type &it): + container_const_reference (mu), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ - it.it_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ < it.it_; - } - - private: - const_subiterator1_type it_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ == it.it_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ < it.it_; + } + + private: + const_subiterator1_type it_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E::const_iterator2::iterator_category iterator_category; - typedef typename matrix_unary1::difference_type difference_type; - typedef typename matrix_unary1::value_type value_type; - typedef typename matrix_unary1::const_reference reference; - typedef typename matrix_unary1::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mu, const const_subiterator2_type &it): - container_const_reference (mu), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator2: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E::const_iterator2::iterator_category iterator_category; + typedef typename matrix_unary1::difference_type difference_type; + typedef typename matrix_unary1::value_type value_type; + typedef typename matrix_unary1::const_reference reference; + typedef typename matrix_unary1::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mu, const const_subiterator2_type &it): + container_const_reference (mu), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ - it.it_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ < it.it_; - } - - private: - const_subiterator2_type it_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression_closure_type e_; - }; - - template - struct matrix_unary1_traits { - typedef matrix_unary1 expression_type; + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ == it.it_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ < it.it_; + } + + private: + const_subiterator2_type it_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression_closure_type e_; +}; + +template +struct matrix_unary1_traits { + typedef matrix_unary1 expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E::matrix_temporary_type result_type; -#endif - }; - - // (- m) [i] [j] = - m [i] [j] - template - BOOST_UBLAS_INLINE - typename matrix_unary1_traits >::result_type - operator - (const matrix_expression &e) { - typedef typename matrix_unary1_traits >::expression_type expression_type; - return expression_type (e ()); - } - - // (conj m) [i] [j] = conj (m [i] [j]) - template - BOOST_UBLAS_INLINE - typename matrix_unary1_traits >::result_type - conj (const matrix_expression &e) { - typedef typename matrix_unary1_traits >::expression_type expression_type; - return expression_type (e ()); - } - - // (real m) [i] [j] = real (m [i] [j]) - template - BOOST_UBLAS_INLINE - typename matrix_unary1_traits >::result_type - real (const matrix_expression &e) { - typedef typename matrix_unary1_traits >::expression_type expression_type; - return expression_type (e ()); - } - - // (imag m) [i] [j] = imag (m [i] [j]) - template - BOOST_UBLAS_INLINE - typename matrix_unary1_traits >::result_type - imag (const matrix_expression &e) { - typedef typename matrix_unary1_traits >::expression_type expression_type; - return expression_type (e ()); - } - - template - class matrix_unary2: - public matrix_expression > { - - typedef typename boost::mpl::if_ >, - E, - const E>::type expression_type; - typedef F functor_type; - public: - typedef typename boost::mpl::if_, - typename E::const_closure_type, - typename E::closure_type>::type expression_closure_type; - private: - typedef matrix_unary2 self_type; - public: + typedef typename E::matrix_temporary_type result_type; +#endif +}; + +// (- m) [i] [j] = - m [i] [j] +template +BOOST_UBLAS_INLINE +typename matrix_unary1_traits >::result_type +operator - (const matrix_expression &e) { + typedef typename matrix_unary1_traits >::expression_type expression_type; + return expression_type (e ()); +} + +// (conj m) [i] [j] = conj (m [i] [j]) +template +BOOST_UBLAS_INLINE +typename matrix_unary1_traits >::result_type +conj (const matrix_expression &e) { + typedef typename matrix_unary1_traits >::expression_type expression_type; + return expression_type (e ()); +} + +// (real m) [i] [j] = real (m [i] [j]) +template +BOOST_UBLAS_INLINE +typename matrix_unary1_traits >::result_type +real (const matrix_expression &e) { + typedef typename matrix_unary1_traits >::expression_type expression_type; + return expression_type (e ()); +} + +// (imag m) [i] [j] = imag (m [i] [j]) +template +BOOST_UBLAS_INLINE +typename matrix_unary1_traits >::result_type +imag (const matrix_expression &e) { + typedef typename matrix_unary1_traits >::expression_type expression_type; + return expression_type (e ()); +} + +template +class matrix_unary2: + public matrix_expression > { + + typedef typename boost::mpl::if_ >, + E, + const E>::type expression_type; + typedef F functor_type; +public: + typedef typename boost::mpl::if_, + typename E::const_closure_type, + typename E::closure_type>::type expression_closure_type; +private: + typedef matrix_unary2 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename E::size_type size_type; - typedef typename E::difference_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef typename boost::mpl::if_ >, - typename E::reference, - value_type>::type reference; - - typedef const self_type const_closure_type; - typedef self_type closure_type; - typedef typename boost::mpl::if_, - column_major_tag, - typename boost::mpl::if_, - row_major_tag, - typename E::orientation_category>::type>::type orientation_category; - typedef typename E::storage_category storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - // matrix_unary2 may be used as mutable expression - - // this is the only non const expression constructor - explicit matrix_unary2 (expression_type &e): - e_ (e) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e_.size2 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e_.size1 (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression_closure_type &expression () const { - return e_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e_ (j, i)); - } - BOOST_UBLAS_INLINE - reference operator () (size_type i, size_type j) { - BOOST_STATIC_ASSERT ((boost::is_same >::value)); - return e_ (j, i); - } - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e_ (i)); - } - BOOST_UBLAS_INLINE - reference operator () (size_type i) { - BOOST_STATIC_ASSERT ((boost::is_same >::value)); - return e_ (i); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_unary2 &mu2) const { - return (*this).expression ().same_closure (mu2.expression ()); - } - - // Iterator types - private: - typedef typename E::const_iterator1 const_subiterator2_type; - typedef typename E::const_iterator2 const_subiterator1_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef typename E::size_type size_type; + typedef typename E::difference_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef typename boost::mpl::if_ >, + typename E::reference, + value_type>::type reference; + + typedef const self_type const_closure_type; + typedef self_type closure_type; + typedef typename boost::mpl::if_, + column_major_tag, + typename boost::mpl::if_, + row_major_tag, + typename E::orientation_category>::type>::type orientation_category; + typedef typename E::storage_category storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + // matrix_unary2 may be used as mutable expression - + // this is the only non const expression constructor + explicit matrix_unary2 (expression_type &e): + e_ (e) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e_.size2 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e_.size1 (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression_closure_type &expression () const { + return e_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e_ (j, i)); + } + BOOST_UBLAS_INLINE + reference operator () (size_type i, size_type j) { + BOOST_STATIC_ASSERT ((boost::is_same >::value)); + return e_ (j, i); + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e_ (i)); + } + BOOST_UBLAS_INLINE + reference operator () (size_type i) { + BOOST_STATIC_ASSERT ((boost::is_same >::value)); + return e_ (i); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_unary2 &mu2) const { + return (*this).expression ().same_closure (mu2.expression ()); + } + + // Iterator types +private: + typedef typename E::const_iterator1 const_subiterator2_type; + typedef typename E::const_iterator2 const_subiterator1_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_subiterator1_type it1 (e_.find2 (rank, j, i)); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_subiterator1_type it1 (e_.find2 (rank, j, i)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it1.index2 (), it1.index1 ()); + return const_iterator1 (*this, it1.index2 (), it1.index1 ()); #else - return const_iterator1 (*this, it1); + return const_iterator1 (*this, it1); #endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_subiterator2_type it2 (e_.find1 (rank, j, i)); + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_subiterator2_type it2 (e_.find1 (rank, j, i)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, it2.index2 (), it2.index1 ()); + return const_iterator2 (*this, it2.index2 (), it2.index1 ()); #else - return const_iterator2 (*this, it2); + return const_iterator2 (*this, it2); #endif - } + } - // Iterators enhance the iterators of the referenced expression - // with the unary functor. + // Iterators enhance the iterators of the referenced expression + // with the unary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E::const_iterator2::iterator_category iterator_category; - typedef typename matrix_unary2::difference_type difference_type; - typedef typename matrix_unary2::value_type value_type; - typedef typename matrix_unary2::const_reference reference; - typedef typename matrix_unary2::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mu, const const_subiterator1_type &it): - container_const_reference (mu), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator1: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E::const_iterator2::iterator_category iterator_category; + typedef typename matrix_unary2::difference_type difference_type; + typedef typename matrix_unary2::value_type value_type; + typedef typename matrix_unary2::const_reference reference; + typedef typename matrix_unary2::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mu, const const_subiterator1_type &it): + container_const_reference (mu), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ - it.it_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE -#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it_.index2 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it_.index1 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ < it.it_; - } - - private: - const_subiterator1_type it_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } - -#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E::const_iterator1::iterator_category iterator_category; - typedef typename matrix_unary2::difference_type difference_type; - typedef typename matrix_unary2::value_type value_type; - typedef typename matrix_unary2::const_reference reference; - typedef typename matrix_unary2::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mu, const const_subiterator2_type &it): - container_const_reference (mu), it_ (it) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ - it.it_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } - -#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE -#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + const_reverse_iterator2 crend () const { + return rend (); + } #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE -#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it_.index2 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it_.index1 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ == it.it_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ < it.it_; + } + + private: + const_subiterator1_type it_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } + +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR + class const_iterator2: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E::const_iterator1::iterator_category iterator_category; + typedef typename matrix_unary2::difference_type difference_type; + typedef typename matrix_unary2::value_type value_type; + typedef typename matrix_unary2::const_reference reference; + typedef typename matrix_unary2::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mu, const const_subiterator2_type &it): + container_const_reference (mu), it_ (it) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ - it.it_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } + +#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION + BOOST_UBLAS_INLINE +#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE +#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION + typename self_type:: +#endif + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE +#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION + typename self_type:: +#endif + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it_.index2 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it_.index1 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it_ = it.it_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ == it.it_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it_ < it.it_; - } - - private: - const_subiterator2_type it_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression_closure_type e_; - }; - - template - struct matrix_unary2_traits { - typedef matrix_unary2 expression_type; + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it_.index2 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it_.index1 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it_ = it.it_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ == it.it_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it_ < it.it_; + } + + private: + const_subiterator2_type it_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression_closure_type e_; +}; + +template +struct matrix_unary2_traits { + typedef matrix_unary2 expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E::matrix_temporary_type result_type; -#endif - }; - - // (trans m) [i] [j] = m [j] [i] - template - BOOST_UBLAS_INLINE - typename matrix_unary2_traits >::result_type - trans (const matrix_expression &e) { - typedef typename matrix_unary2_traits >::expression_type expression_type; - return expression_type (e ()); - } - template - BOOST_UBLAS_INLINE - typename matrix_unary2_traits >::result_type - trans (matrix_expression &e) { - typedef typename matrix_unary2_traits >::expression_type expression_type; - return expression_type (e ()); - } - - // (herm m) [i] [j] = conj (m [j] [i]) - template - BOOST_UBLAS_INLINE - typename matrix_unary2_traits >::result_type - herm (const matrix_expression &e) { - typedef typename matrix_unary2_traits >::expression_type expression_type; - return expression_type (e ()); - } - - template - class matrix_binary: - public matrix_expression > { - - typedef E1 expression1_type; - typedef E2 expression2_type; - typedef F functor_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - private: - typedef matrix_binary self_type; - public: + typedef typename E::matrix_temporary_type result_type; +#endif +}; + +// (trans m) [i] [j] = m [j] [i] +template +BOOST_UBLAS_INLINE +typename matrix_unary2_traits >::result_type +trans (const matrix_expression &e) { + typedef typename matrix_unary2_traits >::expression_type expression_type; + return expression_type (e ()); +} +template +BOOST_UBLAS_INLINE +typename matrix_unary2_traits >::result_type +trans (matrix_expression &e) { + typedef typename matrix_unary2_traits >::expression_type expression_type; + return expression_type (e ()); +} + +// (herm m) [i] [j] = conj (m [j] [i]) +template +BOOST_UBLAS_INLINE +typename matrix_unary2_traits >::result_type +herm (const matrix_expression &e) { + typedef typename matrix_unary2_traits >::expression_type expression_type; + return expression_type (e ()); +} + +template +class matrix_binary: + public matrix_expression > { + + typedef E1 expression1_type; + typedef E2 expression2_type; + typedef F functor_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; +private: + typedef matrix_binary self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename promote_traits::promote_type size_type; - typedef typename promote_traits::promote_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef unknown_orientation_tag orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_binary (const E1 &e1, const E2 &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ()); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ()); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression1_closure_type &expression1 () const { - return e1_; - } - BOOST_UBLAS_INLINE - const expression2_closure_type &expression2 () const { - return e2_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e1_ (i, j), e2_ (i, j)); - } - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e1_ (i), e2_ (i)); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_binary &mb) const { - return (*this).expression1 ().same_closure (mb.expression1 ()) && - (*this).expression2 ().same_closure (mb.expression2 ()); - } - - // Iterator types - private: - typedef typename E1::const_iterator1 const_iterator11_type; - typedef typename E1::const_iterator2 const_iterator12_type; - typedef typename E2::const_iterator1 const_iterator21_type; - typedef typename E2::const_iterator2 const_iterator22_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef typename promote_traits::promote_type size_type; + typedef typename promote_traits::promote_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef unknown_orientation_tag orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_binary (const E1 &e1, const E2 &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ()); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ()); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression1_closure_type &expression1 () const { + return e1_; + } + BOOST_UBLAS_INLINE + const expression2_closure_type &expression2 () const { + return e2_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e1_ (i, j), e2_ (i, j)); + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e1_ (i), e2_ (i)); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_binary &mb) const { + return (*this).expression1 ().same_closure (mb.expression1 ()) && + (*this).expression2 ().same_closure (mb.expression2 ()); + } + + // Iterator types +private: + typedef typename E1::const_iterator1 const_iterator11_type; + typedef typename E1::const_iterator2 const_iterator12_type; + typedef typename E2::const_iterator1 const_iterator21_type; + typedef typename E2::const_iterator2 const_iterator22_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category1; - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef typename iterator_restrict_traits::iterator_category iterator_category2; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef typename iterator_restrict_traits::iterator_category iterator_category1; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef typename iterator_restrict_traits::iterator_category iterator_category2; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_iterator11_type it11 (e1_.find1 (rank, i, j)); - const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j)); - const_iterator21_type it21 (e2_.find1 (rank, i, j)); - const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j)); - BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ()) - BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ()) - i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (), - it21 != it21_end ? it21.index1 () : size1 ()); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_iterator11_type it11 (e1_.find1 (rank, i, j)); + const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j)); + const_iterator21_type it21 (e2_.find1 (rank, i, j)); + const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j)); + BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ()) + BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ()) + i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (), + it21 != it21_end ? it21.index1 () : size1 ()); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, i, j); + return const_iterator1 (*this, i, j); #else - return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end); -#endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_iterator12_type it12 (e1_.find2 (rank, i, j)); - const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ())); - const_iterator22_type it22 (e2_.find2 (rank, i, j)); - const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ())); - BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ()) - BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ()) - j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (), - it22 != it22_end ? it22.index2 () : size2 ()); + return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end); +#endif + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_iterator12_type it12 (e1_.find2 (rank, i, j)); + const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ())); + const_iterator22_type it22 (e2_.find2 (rank, i, j)); + const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ())); + BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ()) + BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ()) + j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (), + it22 != it22_end ? it22.index2 () : size2 ()); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, i, j); + return const_iterator2 (*this, i, j); #else - return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end); + return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end); #endif - } + } - // Iterators enhance the iterators of the referenced expression - // with the binary functor. + // Iterators enhance the iterators of the referenced expression + // with the binary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_binary::difference_type difference_type; - typedef typename matrix_binary::value_type value_type; - typedef typename matrix_binary::const_reference reference; - typedef typename matrix_binary::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mb, size_type i, size_type j, - const const_iterator11_type &it1, const const_iterator11_type &it1_end, - const const_iterator21_type &it2, const const_iterator21_type &it2_end): - container_const_reference (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {} - - private: - // Dense specializations - BOOST_UBLAS_INLINE - void increment (dense_random_access_iterator_tag) { - ++ i_; ++ it1_; ++ it2_; - } - BOOST_UBLAS_INLINE - void decrement (dense_random_access_iterator_tag) { - -- i_; -- it1_; -- it2_; - } - BOOST_UBLAS_INLINE - void increment (dense_random_access_iterator_tag, difference_type n) { - i_ += n; it1_ += n; it2_ += n; - } - BOOST_UBLAS_INLINE - void decrement (dense_random_access_iterator_tag, difference_type n) { - i_ -= n; it1_ -= n; it2_ -= n; - } - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - return functor_type::apply (*it1_, *it2_); - } - - // Packed specializations - BOOST_UBLAS_INLINE - void increment (packed_random_access_iterator_tag) { - if (it1_ != it1_end_) - if (it1_.index1 () <= i_) - ++ it1_; - if (it2_ != it2_end_) - if (it2_.index1 () <= i_) - ++ it2_; - ++ i_; - } - BOOST_UBLAS_INLINE - void decrement (packed_random_access_iterator_tag) { - if (it1_ != it1_end_) - if (i_ <= it1_.index1 ()) - -- it1_; - if (it2_ != it2_end_) - if (i_ <= it2_.index1 ()) - -- it2_; - -- i_; - } - BOOST_UBLAS_INLINE - void increment (packed_random_access_iterator_tag, difference_type n) { - while (n > 0) { - increment (packed_random_access_iterator_tag ()); - --n; - } - while (n < 0) { - decrement (packed_random_access_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - void decrement (packed_random_access_iterator_tag, difference_type n) { - while (n > 0) { - decrement (packed_random_access_iterator_tag ()); - --n; - } - while (n < 0) { - increment (packed_random_access_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { - typename E1::value_type t1 = typename E1::value_type/*zero*/(); - if (it1_ != it1_end_) { - BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); - if (it1_.index1 () == i_) - t1 = *it1_; - } - typename E2::value_type t2 = typename E2::value_type/*zero*/(); - if (it2_ != it2_end_) { - BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); - if (it2_.index1 () == i_) - t2 = *it2_; - } - return functor_type::apply (t1, t2); - } - - // Sparse specializations - BOOST_UBLAS_INLINE - void increment (sparse_bidirectional_iterator_tag) { - size_type index1 = (*this) ().size1 (); - if (it1_ != it1_end_) { - if (it1_.index1 () <= i_) - ++ it1_; - if (it1_ != it1_end_) - index1 = it1_.index1 (); - } - size_type index2 = (*this) ().size1 (); - if (it2_ != it2_end_) - if (it2_.index1 () <= i_) - ++ it2_; - if (it2_ != it2_end_) { - index2 = it2_.index1 (); - } - i_ = (std::min) (index1, index2); - } - BOOST_UBLAS_INLINE - void decrement (sparse_bidirectional_iterator_tag) { - size_type index1 = (*this) ().size1 (); - if (it1_ != it1_end_) { - if (i_ <= it1_.index1 ()) - -- it1_; - if (it1_ != it1_end_) - index1 = it1_.index1 (); - } - size_type index2 = (*this) ().size1 (); - if (it2_ != it2_end_) { - if (i_ <= it2_.index1 ()) - -- it2_; - if (it2_ != it2_end_) - index2 = it2_.index1 (); - } - i_ = (std::max) (index1, index2); - } - BOOST_UBLAS_INLINE - void increment (sparse_bidirectional_iterator_tag, difference_type n) { - while (n > 0) { - increment (sparse_bidirectional_iterator_tag ()); - --n; - } - while (n < 0) { - decrement (sparse_bidirectional_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - void decrement (sparse_bidirectional_iterator_tag, difference_type n) { - while (n > 0) { - decrement (sparse_bidirectional_iterator_tag ()); - --n; - } - while (n < 0) { - increment (sparse_bidirectional_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { - typename E1::value_type t1 = typename E1::value_type/*zero*/(); - if (it1_ != it1_end_) { - BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); - if (it1_.index1 () == i_) - t1 = *it1_; - } - typename E2::value_type t2 = typename E2::value_type/*zero*/(); - if (it2_ != it2_end_) { - BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); - if (it2_.index1 () == i_) - t2 = *it2_; - } - return functor_type::apply (t1, t2); - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - increment (iterator_category ()); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - decrement (iterator_category ()); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - increment (iterator_category (), n); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - decrement (iterator_category (), n); - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); - return index1 () - it.index1 (); - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator1: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_binary::difference_type difference_type; + typedef typename matrix_binary::value_type value_type; + typedef typename matrix_binary::const_reference reference; + typedef typename matrix_binary::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mb, size_type i, size_type j, + const const_iterator11_type &it1, const const_iterator11_type &it1_end, + const const_iterator21_type &it2, const const_iterator21_type &it2_end): + container_const_reference (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {} + + private: + // Dense specializations + BOOST_UBLAS_INLINE + void increment (dense_random_access_iterator_tag) { + ++ i_; ++ it1_; ++ it2_; + } + BOOST_UBLAS_INLINE + void decrement (dense_random_access_iterator_tag) { + -- i_; -- it1_; -- it2_; + } + BOOST_UBLAS_INLINE + void increment (dense_random_access_iterator_tag, difference_type n) { + i_ += n; it1_ += n; it2_ += n; + } + BOOST_UBLAS_INLINE + void decrement (dense_random_access_iterator_tag, difference_type n) { + i_ -= n; it1_ -= n; it2_ -= n; + } + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + return functor_type::apply (*it1_, *it2_); + } + + // Packed specializations + BOOST_UBLAS_INLINE + void increment (packed_random_access_iterator_tag) { + if (it1_ != it1_end_) + if (it1_.index1 () <= i_) + ++ it1_; + if (it2_ != it2_end_) + if (it2_.index1 () <= i_) + ++ it2_; + ++ i_; + } + BOOST_UBLAS_INLINE + void decrement (packed_random_access_iterator_tag) { + if (it1_ != it1_end_) + if (i_ <= it1_.index1 ()) + -- it1_; + if (it2_ != it2_end_) + if (i_ <= it2_.index1 ()) + -- it2_; + -- i_; + } + BOOST_UBLAS_INLINE + void increment (packed_random_access_iterator_tag, difference_type n) { + while (n > 0) { + increment (packed_random_access_iterator_tag ()); + --n; + } + while (n < 0) { + decrement (packed_random_access_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + void decrement (packed_random_access_iterator_tag, difference_type n) { + while (n > 0) { + decrement (packed_random_access_iterator_tag ()); + --n; + } + while (n < 0) { + increment (packed_random_access_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { + typename E1::value_type t1 = typename E1::value_type/*zero*/(); + if (it1_ != it1_end_) { + BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); + if (it1_.index1 () == i_) + t1 = *it1_; + } + typename E2::value_type t2 = typename E2::value_type/*zero*/(); + if (it2_ != it2_end_) { + BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); + if (it2_.index1 () == i_) + t2 = *it2_; + } + return functor_type::apply (t1, t2); + } + + // Sparse specializations + BOOST_UBLAS_INLINE + void increment (sparse_bidirectional_iterator_tag) { + size_type index1 = (*this) ().size1 (); + if (it1_ != it1_end_) { + if (it1_.index1 () <= i_) + ++ it1_; + if (it1_ != it1_end_) + index1 = it1_.index1 (); + } + size_type index2 = (*this) ().size1 (); + if (it2_ != it2_end_) + if (it2_.index1 () <= i_) + ++ it2_; + if (it2_ != it2_end_) { + index2 = it2_.index1 (); + } + i_ = (std::min) (index1, index2); + } + BOOST_UBLAS_INLINE + void decrement (sparse_bidirectional_iterator_tag) { + size_type index1 = (*this) ().size1 (); + if (it1_ != it1_end_) { + if (i_ <= it1_.index1 ()) + -- it1_; + if (it1_ != it1_end_) + index1 = it1_.index1 (); + } + size_type index2 = (*this) ().size1 (); + if (it2_ != it2_end_) { + if (i_ <= it2_.index1 ()) + -- it2_; + if (it2_ != it2_end_) + index2 = it2_.index1 (); + } + i_ = (std::max) (index1, index2); + } + BOOST_UBLAS_INLINE + void increment (sparse_bidirectional_iterator_tag, difference_type n) { + while (n > 0) { + increment (sparse_bidirectional_iterator_tag ()); + --n; + } + while (n < 0) { + decrement (sparse_bidirectional_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + void decrement (sparse_bidirectional_iterator_tag, difference_type n) { + while (n > 0) { + decrement (sparse_bidirectional_iterator_tag ()); + --n; + } + while (n < 0) { + increment (sparse_bidirectional_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { + typename E1::value_type t1 = typename E1::value_type/*zero*/(); + if (it1_ != it1_end_) { + BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ()); + if (it1_.index1 () == i_) + t1 = *it1_; + } + typename E2::value_type t2 = typename E2::value_type/*zero*/(); + if (it2_ != it2_end_) { + BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ()); + if (it2_.index1 () == i_) + t2 = *it2_; + } + return functor_type::apply (t1, t2); + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + increment (iterator_category ()); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + decrement (iterator_category ()); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + increment (iterator_category (), n); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + decrement (iterator_category (), n); + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); + return index1 () - it.index1 (); + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return i_; - } - BOOST_UBLAS_INLINE - size_type index2 () const { - // if (it1_ != it1_end_ && it2_ != it2_end_) - // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ()); - // else - return j_; - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - i_ = it.i_; - j_ = it.j_; - it1_ = it.it1_; - it1_end_ = it.it1_end_; - it2_ = it.it2_; - it2_end_ = it.it2_end_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); - return index1 () == it.index1 (); - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); - return index1 () < it.index1 (); - } - - private: - size_type i_; - size_type j_; - const_iterator11_type it1_; - const_iterator11_type it1_end_; - const_iterator21_type it2_; - const_iterator21_type it2_end_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return i_; + } + BOOST_UBLAS_INLINE + size_type index2 () const { + // if (it1_ != it1_end_ && it2_ != it2_end_) + // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ()); + // else + return j_; + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + i_ = it.i_; + j_ = it.j_; + it1_ = it.it1_; + it1_end_ = it.it1_end_; + it2_ = it.it2_; + it2_end_ = it.it2_end_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); + return index1 () == it.index1 (); + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ()); + return index1 () < it.index1 (); + } + + private: + size_type i_; + size_type j_; + const_iterator11_type it1_; + const_iterator11_type it1_end_; + const_iterator21_type it2_; + const_iterator21_type it2_end_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_binary::difference_type difference_type; - typedef typename matrix_binary::value_type value_type; - typedef typename matrix_binary::const_reference reference; - typedef typename matrix_binary::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mb, size_type i, size_type j, - const const_iterator12_type &it1, const const_iterator12_type &it1_end, - const const_iterator22_type &it2, const const_iterator22_type &it2_end): - container_const_reference (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {} - - private: - // Dense access specializations - BOOST_UBLAS_INLINE - void increment (dense_random_access_iterator_tag) { - ++ j_; ++ it1_; ++ it2_; - } - BOOST_UBLAS_INLINE - void decrement (dense_random_access_iterator_tag) { - -- j_; -- it1_; -- it2_; - } - BOOST_UBLAS_INLINE - void increment (dense_random_access_iterator_tag, difference_type n) { - j_ += n; it1_ += n; it2_ += n; - } - BOOST_UBLAS_INLINE - void decrement (dense_random_access_iterator_tag, difference_type n) { - j_ -= n; it1_ -= n; it2_ -= n; - } - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - return functor_type::apply (*it1_, *it2_); - } - - // Packed specializations - BOOST_UBLAS_INLINE - void increment (packed_random_access_iterator_tag) { - if (it1_ != it1_end_) - if (it1_.index2 () <= j_) - ++ it1_; - if (it2_ != it2_end_) - if (it2_.index2 () <= j_) - ++ it2_; - ++ j_; - } - BOOST_UBLAS_INLINE - void decrement (packed_random_access_iterator_tag) { - if (it1_ != it1_end_) - if (j_ <= it1_.index2 ()) - -- it1_; - if (it2_ != it2_end_) - if (j_ <= it2_.index2 ()) - -- it2_; - -- j_; - } - BOOST_UBLAS_INLINE - void increment (packed_random_access_iterator_tag, difference_type n) { - while (n > 0) { - increment (packed_random_access_iterator_tag ()); - --n; - } - while (n < 0) { - decrement (packed_random_access_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - void decrement (packed_random_access_iterator_tag, difference_type n) { - while (n > 0) { - decrement (packed_random_access_iterator_tag ()); - --n; - } - while (n < 0) { - increment (packed_random_access_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { - typename E1::value_type t1 = typename E1::value_type/*zero*/(); - if (it1_ != it1_end_) { - BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); - if (it1_.index2 () == j_) - t1 = *it1_; - } - typename E2::value_type t2 = typename E2::value_type/*zero*/(); - if (it2_ != it2_end_) { - BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); - if (it2_.index2 () == j_) - t2 = *it2_; - } - return functor_type::apply (t1, t2); - } - - // Sparse specializations - BOOST_UBLAS_INLINE - void increment (sparse_bidirectional_iterator_tag) { - size_type index1 = (*this) ().size2 (); - if (it1_ != it1_end_) { - if (it1_.index2 () <= j_) - ++ it1_; - if (it1_ != it1_end_) - index1 = it1_.index2 (); - } - size_type index2 = (*this) ().size2 (); - if (it2_ != it2_end_) { - if (it2_.index2 () <= j_) - ++ it2_; - if (it2_ != it2_end_) - index2 = it2_.index2 (); - } - j_ = (std::min) (index1, index2); - } - BOOST_UBLAS_INLINE - void decrement (sparse_bidirectional_iterator_tag) { - size_type index1 = (*this) ().size2 (); - if (it1_ != it1_end_) { - if (j_ <= it1_.index2 ()) - -- it1_; - if (it1_ != it1_end_) - index1 = it1_.index2 (); - } - size_type index2 = (*this) ().size2 (); - if (it2_ != it2_end_) { - if (j_ <= it2_.index2 ()) - -- it2_; - if (it2_ != it2_end_) - index2 = it2_.index2 (); - } - j_ = (std::max) (index1, index2); - } - BOOST_UBLAS_INLINE - void increment (sparse_bidirectional_iterator_tag, difference_type n) { - while (n > 0) { - increment (sparse_bidirectional_iterator_tag ()); - --n; - } - while (n < 0) { - decrement (sparse_bidirectional_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - void decrement (sparse_bidirectional_iterator_tag, difference_type n) { - while (n > 0) { - decrement (sparse_bidirectional_iterator_tag ()); - --n; - } - while (n < 0) { - increment (sparse_bidirectional_iterator_tag ()); - ++n; - } - } - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { - typename E1::value_type t1 = typename E1::value_type/*zero*/(); - if (it1_ != it1_end_) { - BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); - if (it1_.index2 () == j_) - t1 = *it1_; - } - typename E2::value_type t2 = typename E2::value_type/*zero*/(); - if (it2_ != it2_end_) { - BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); - if (it2_.index2 () == j_) - t2 = *it2_; - } - return functor_type::apply (t1, t2); - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - increment (iterator_category ()); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - decrement (iterator_category ()); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - increment (iterator_category (), n); - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - decrement (iterator_category (), n); - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); - return index2 () - it.index2 (); - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator2: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_binary::difference_type difference_type; + typedef typename matrix_binary::value_type value_type; + typedef typename matrix_binary::const_reference reference; + typedef typename matrix_binary::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mb, size_type i, size_type j, + const const_iterator12_type &it1, const const_iterator12_type &it1_end, + const const_iterator22_type &it2, const const_iterator22_type &it2_end): + container_const_reference (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {} + + private: + // Dense access specializations + BOOST_UBLAS_INLINE + void increment (dense_random_access_iterator_tag) { + ++ j_; ++ it1_; ++ it2_; + } + BOOST_UBLAS_INLINE + void decrement (dense_random_access_iterator_tag) { + -- j_; -- it1_; -- it2_; + } + BOOST_UBLAS_INLINE + void increment (dense_random_access_iterator_tag, difference_type n) { + j_ += n; it1_ += n; it2_ += n; + } + BOOST_UBLAS_INLINE + void decrement (dense_random_access_iterator_tag, difference_type n) { + j_ -= n; it1_ -= n; it2_ -= n; + } + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + return functor_type::apply (*it1_, *it2_); + } + + // Packed specializations + BOOST_UBLAS_INLINE + void increment (packed_random_access_iterator_tag) { + if (it1_ != it1_end_) + if (it1_.index2 () <= j_) + ++ it1_; + if (it2_ != it2_end_) + if (it2_.index2 () <= j_) + ++ it2_; + ++ j_; + } + BOOST_UBLAS_INLINE + void decrement (packed_random_access_iterator_tag) { + if (it1_ != it1_end_) + if (j_ <= it1_.index2 ()) + -- it1_; + if (it2_ != it2_end_) + if (j_ <= it2_.index2 ()) + -- it2_; + -- j_; + } + BOOST_UBLAS_INLINE + void increment (packed_random_access_iterator_tag, difference_type n) { + while (n > 0) { + increment (packed_random_access_iterator_tag ()); + --n; + } + while (n < 0) { + decrement (packed_random_access_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + void decrement (packed_random_access_iterator_tag, difference_type n) { + while (n > 0) { + decrement (packed_random_access_iterator_tag ()); + --n; + } + while (n < 0) { + increment (packed_random_access_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { + typename E1::value_type t1 = typename E1::value_type/*zero*/(); + if (it1_ != it1_end_) { + BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); + if (it1_.index2 () == j_) + t1 = *it1_; + } + typename E2::value_type t2 = typename E2::value_type/*zero*/(); + if (it2_ != it2_end_) { + BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); + if (it2_.index2 () == j_) + t2 = *it2_; + } + return functor_type::apply (t1, t2); + } + + // Sparse specializations + BOOST_UBLAS_INLINE + void increment (sparse_bidirectional_iterator_tag) { + size_type index1 = (*this) ().size2 (); + if (it1_ != it1_end_) { + if (it1_.index2 () <= j_) + ++ it1_; + if (it1_ != it1_end_) + index1 = it1_.index2 (); + } + size_type index2 = (*this) ().size2 (); + if (it2_ != it2_end_) { + if (it2_.index2 () <= j_) + ++ it2_; + if (it2_ != it2_end_) + index2 = it2_.index2 (); + } + j_ = (std::min) (index1, index2); + } + BOOST_UBLAS_INLINE + void decrement (sparse_bidirectional_iterator_tag) { + size_type index1 = (*this) ().size2 (); + if (it1_ != it1_end_) { + if (j_ <= it1_.index2 ()) + -- it1_; + if (it1_ != it1_end_) + index1 = it1_.index2 (); + } + size_type index2 = (*this) ().size2 (); + if (it2_ != it2_end_) { + if (j_ <= it2_.index2 ()) + -- it2_; + if (it2_ != it2_end_) + index2 = it2_.index2 (); + } + j_ = (std::max) (index1, index2); + } + BOOST_UBLAS_INLINE + void increment (sparse_bidirectional_iterator_tag, difference_type n) { + while (n > 0) { + increment (sparse_bidirectional_iterator_tag ()); + --n; + } + while (n < 0) { + decrement (sparse_bidirectional_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + void decrement (sparse_bidirectional_iterator_tag, difference_type n) { + while (n > 0) { + decrement (sparse_bidirectional_iterator_tag ()); + --n; + } + while (n < 0) { + increment (sparse_bidirectional_iterator_tag ()); + ++n; + } + } + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { + typename E1::value_type t1 = typename E1::value_type/*zero*/(); + if (it1_ != it1_end_) { + BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ()); + if (it1_.index2 () == j_) + t1 = *it1_; + } + typename E2::value_type t2 = typename E2::value_type/*zero*/(); + if (it2_ != it2_end_) { + BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ()); + if (it2_.index2 () == j_) + t2 = *it2_; + } + return functor_type::apply (t1, t2); + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + increment (iterator_category ()); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + decrement (iterator_category ()); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + increment (iterator_category (), n); + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + decrement (iterator_category (), n); + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); + return index2 () - it.index2 (); + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - // if (it1_ != it1_end_ && it2_ != it2_end_) - // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ()); - // else - return i_; - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return j_; - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - i_ = it.i_; - j_ = it.j_; - it1_ = it.it1_; - it1_end_ = it.it1_end_; - it2_ = it.it2_; - it2_end_ = it.it2_end_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); - return index2 () == it.index2 (); - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); - return index2 () < it.index2 (); - } - - private: - size_type i_; - size_type j_; - const_iterator12_type it1_; - const_iterator12_type it1_end_; - const_iterator22_type it2_; - const_iterator22_type it2_end_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_binary_traits { - typedef matrix_binary expression_type; + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + // if (it1_ != it1_end_ && it2_ != it2_end_) + // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ()); + // else + return i_; + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return j_; + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + i_ = it.i_; + j_ = it.j_; + it1_ = it.it1_; + it1_end_ = it.it1_end_; + it2_ = it.it2_; + it2_end_ = it.it2_end_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); + return index2 () == it.index2 (); + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ()); + return index2 () < it.index2 (); + } + + private: + size_type i_; + size_type j_; + const_iterator12_type it1_; + const_iterator12_type it1_end_; + const_iterator22_type it2_; + const_iterator22_type it2_end_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_binary_traits { + typedef matrix_binary expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E1::matrix_temporary_type result_type; -#endif - }; - - // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j] - template - BOOST_UBLAS_INLINE - typename matrix_binary_traits >::result_type - operator + (const matrix_expression &e1, - const matrix_expression &e2) { - typedef typename matrix_binary_traits >::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j] - template - BOOST_UBLAS_INLINE - typename matrix_binary_traits >::result_type - operator - (const matrix_expression &e1, - const matrix_expression &e2) { - typedef typename matrix_binary_traits >::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j] - template - BOOST_UBLAS_INLINE - typename matrix_binary_traits >::result_type - element_prod (const matrix_expression &e1, - const matrix_expression &e2) { - typedef typename matrix_binary_traits >::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j] - template - BOOST_UBLAS_INLINE - typename matrix_binary_traits >::result_type - element_div (const matrix_expression &e1, - const matrix_expression &e2) { - typedef typename matrix_binary_traits >::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - template - class matrix_binary_scalar1: - public matrix_expression > { - - typedef E1 expression1_type; - typedef E2 expression2_type; - typedef F functor_type; - typedef const E1& expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - typedef matrix_binary_scalar1 self_type; - public: + typedef typename E1::matrix_temporary_type result_type; +#endif +}; + +// (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j] +template +BOOST_UBLAS_INLINE +typename matrix_binary_traits >::result_type +operator + (const matrix_expression &e1, + const matrix_expression &e2) { + typedef typename matrix_binary_traits >::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j] +template +BOOST_UBLAS_INLINE +typename matrix_binary_traits >::result_type +operator - (const matrix_expression &e1, + const matrix_expression &e2) { + typedef typename matrix_binary_traits >::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j] +template +BOOST_UBLAS_INLINE +typename matrix_binary_traits >::result_type +element_prod (const matrix_expression &e1, + const matrix_expression &e2) { + typedef typename matrix_binary_traits >::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j] +template +BOOST_UBLAS_INLINE +typename matrix_binary_traits >::result_type +element_div (const matrix_expression &e1, + const matrix_expression &e2) { + typedef typename matrix_binary_traits >::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +template +class matrix_binary_scalar1: + public matrix_expression > { + + typedef E1 expression1_type; + typedef E2 expression2_type; + typedef F functor_type; + typedef const E1& expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; + typedef matrix_binary_scalar1 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename E2::size_type size_type; - typedef typename E2::difference_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef typename E2::orientation_category orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e2_.size1 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e2_.size2 (); - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (expression1_type (e1_), e2_ (i, j)); - } - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (expression1_type (e1_), e2_ (i)); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_binary_scalar1 &mbs1) const { - return &e1_ == &(mbs1.e1_) && - (*this).e2_.same_closure (mbs1.e2_); - } - - // Iterator types - private: - typedef expression1_type const_subiterator1_type; - typedef typename E2::const_iterator1 const_iterator21_type; - typedef typename E2::const_iterator2 const_iterator22_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef typename E2::size_type size_type; + typedef typename E2::difference_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef typename E2::orientation_category orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e2_.size1 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e2_.size2 (); + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (expression1_type (e1_), e2_ (i, j)); + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (expression1_type (e1_), e2_ (i)); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_binary_scalar1 &mbs1) const { + return &e1_ == &(mbs1.e1_) && + (*this).e2_.same_closure (mbs1.e2_); + } + + // Iterator types +private: + typedef expression1_type const_subiterator1_type; + typedef typename E2::const_iterator1 const_iterator21_type; + typedef typename E2::const_iterator2 const_iterator22_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_iterator21_type it21 (e2_.find1 (rank, i, j)); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_iterator21_type it21 (e2_.find1 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it21.index1 (), it21.index2 ()); + return const_iterator1 (*this, it21.index1 (), it21.index2 ()); #else - return const_iterator1 (*this, const_subiterator1_type (e1_), it21); + return const_iterator1 (*this, const_subiterator1_type (e1_), it21); #endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_iterator22_type it22 (e2_.find2 (rank, i, j)); + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_iterator22_type it22 (e2_.find2 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, it22.index1 (), it22.index2 ()); + return const_iterator2 (*this, it22.index1 (), it22.index2 ()); #else - return const_iterator2 (*this, const_subiterator1_type (e1_), it22); + return const_iterator2 (*this, const_subiterator1_type (e1_), it22); #endif - } + } - // Iterators enhance the iterators of the referenced expression - // with the binary functor. + // Iterators enhance the iterators of the referenced expression + // with the binary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E2::const_iterator1::iterator_category iterator_category; - typedef typename matrix_binary_scalar1::difference_type difference_type; - typedef typename matrix_binary_scalar1::value_type value_type; - typedef typename matrix_binary_scalar1::const_reference reference; - typedef typename matrix_binary_scalar1::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2): - container_const_reference (mbs), it1_ (it1), it2_ (it2) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it2_ ; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it2_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it2_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ - it.it2_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (it1_, *it2_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator1: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E2::const_iterator1::iterator_category iterator_category; + typedef typename matrix_binary_scalar1::difference_type difference_type; + typedef typename matrix_binary_scalar1::value_type value_type; + typedef typename matrix_binary_scalar1::const_reference reference; + typedef typename matrix_binary_scalar1::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2): + container_const_reference (mbs), it1_ (it1), it2_ (it2) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it2_ ; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it2_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it2_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ - it.it2_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (it1_, *it2_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it2_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ == it.it2_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ < it.it2_; - } - - private: - const_subiterator1_type it1_; - const_iterator21_type it2_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it2_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ == it.it2_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ < it.it2_; + } + + private: + const_subiterator1_type it1_; + const_iterator21_type it2_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E2::const_iterator2::iterator_category iterator_category; - typedef typename matrix_binary_scalar1::difference_type difference_type; - typedef typename matrix_binary_scalar1::value_type value_type; - typedef typename matrix_binary_scalar1::const_reference reference; - typedef typename matrix_binary_scalar1::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2): - container_const_reference (mbs), it1_ (it1), it2_ (it2) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it2_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it2_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ - it.it2_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (it1_, *it2_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator2: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E2::const_iterator2::iterator_category iterator_category; + typedef typename matrix_binary_scalar1::difference_type difference_type; + typedef typename matrix_binary_scalar1::value_type value_type; + typedef typename matrix_binary_scalar1::const_reference reference; + typedef typename matrix_binary_scalar1::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2): + container_const_reference (mbs), it1_ (it1), it2_ (it2) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it2_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it2_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ - it.it2_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (it1_, *it2_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it2_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ == it.it2_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ < it.it2_; - } - - private: - const_subiterator1_type it1_; - const_iterator22_type it2_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_binary_scalar1_traits { - typedef matrix_binary_scalar1 expression_type; // allow E1 to be builtin type + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it2_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ == it.it2_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ < it.it2_; + } + + private: + const_subiterator1_type it1_; + const_iterator22_type it2_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_binary_scalar1_traits { + typedef matrix_binary_scalar1 expression_type; // allow E1 to be builtin type #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E2::matrix_temporary_type result_type; -#endif - }; - - // (t * m) [i] [j] = t * m [i] [j] - template - BOOST_UBLAS_INLINE - typename boost::enable_if< is_convertible, - typename matrix_binary_scalar1_traits >::result_type - >::type - operator * (const T1 &e1, - const matrix_expression &e2) { - typedef typename matrix_binary_scalar1_traits >::expression_type expression_type; - return expression_type (e1, e2 ()); - } - - - template - class matrix_binary_scalar2: - public matrix_expression > { - - typedef E1 expression1_type; - typedef E2 expression2_type; - typedef F functor_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef const E2& expression2_closure_type; - private: - typedef matrix_binary_scalar2 self_type; - public: + typedef typename E2::matrix_temporary_type result_type; +#endif +}; + +// (t * m) [i] [j] = t * m [i] [j] +template +BOOST_UBLAS_INLINE +typename boost::enable_if< is_convertible, +typename matrix_binary_scalar1_traits >::result_type +>::type +operator * (const T1 &e1, + const matrix_expression &e2) { + typedef typename matrix_binary_scalar1_traits >::expression_type expression_type; + return expression_type (e1, e2 ()); +} + + +template +class matrix_binary_scalar2: + public matrix_expression > { + + typedef E1 expression1_type; + typedef E2 expression2_type; + typedef F functor_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef const E2& expression2_closure_type; +private: + typedef matrix_binary_scalar2 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - typedef typename E1::size_type size_type; - typedef typename E1::difference_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef typename E1::orientation_category orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e1_.size1 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e1_.size2 (); - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e1_ (i, j), expression2_type (e2_)); - } - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e1_ (i), expression2_type (e2_)); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_binary_scalar2 &mbs2) const { - return (*this).e1_.same_closure (mbs2.e1_) && - &e2_ == &(mbs2.e2_); - } - - // Iterator types - private: - typedef typename E1::const_iterator1 const_iterator11_type; - typedef typename E1::const_iterator2 const_iterator12_type; - typedef expression2_type const_subiterator2_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + typedef typename E1::size_type size_type; + typedef typename E1::difference_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef typename E1::orientation_category orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e1_.size1 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e1_.size2 (); + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e1_ (i, j), expression2_type (e2_)); + } + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e1_ (i), expression2_type (e2_)); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_binary_scalar2 &mbs2) const { + return (*this).e1_.same_closure (mbs2.e1_) && + &e2_ == &(mbs2.e2_); + } + + // Iterator types +private: + typedef typename E1::const_iterator1 const_iterator11_type; + typedef typename E1::const_iterator2 const_iterator12_type; + typedef expression2_type const_subiterator2_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int rank, size_type i, size_type j) const { - const_iterator11_type it11 (e1_.find1 (rank, i, j)); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int rank, size_type i, size_type j) const { + const_iterator11_type it11 (e1_.find1 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it11.index1 (), it11.index2 ()); + return const_iterator1 (*this, it11.index1 (), it11.index2 ()); #else - return const_iterator1 (*this, it11, const_subiterator2_type (e2_)); + return const_iterator1 (*this, it11, const_subiterator2_type (e2_)); #endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int rank, size_type i, size_type j) const { - const_iterator12_type it12 (e1_.find2 (rank, i, j)); + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int rank, size_type i, size_type j) const { + const_iterator12_type it12 (e1_.find2 (rank, i, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, it12.index1 (), it12.index2 ()); + return const_iterator2 (*this, it12.index1 (), it12.index2 ()); #else - return const_iterator2 (*this, it12, const_subiterator2_type (e2_)); + return const_iterator2 (*this, it12, const_subiterator2_type (e2_)); #endif - } + } - // Iterators enhance the iterators of the referenced expression - // with the binary functor. + // Iterators enhance the iterators of the referenced expression + // with the binary functor. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E1::const_iterator1::iterator_category iterator_category; - typedef typename matrix_binary_scalar2::difference_type difference_type; - typedef typename matrix_binary_scalar2::value_type value_type; - typedef typename matrix_binary_scalar2::const_reference reference; - typedef typename matrix_binary_scalar2::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2): - container_const_reference (mbs), it1_ (it1), it2_ (it2) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it1_ ; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it1_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it1_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ - it.it1_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it1_, it2_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + class const_iterator1: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E1::const_iterator1::iterator_category iterator_category; + typedef typename matrix_binary_scalar2::difference_type difference_type; + typedef typename matrix_binary_scalar2::value_type value_type; + typedef typename matrix_binary_scalar2::const_reference reference; + typedef typename matrix_binary_scalar2::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2): + container_const_reference (mbs), it1_ (it1), it2_ (it2) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it1_ ; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it1_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it1_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ - it.it1_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it1_, it2_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it1_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ == it.it1_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ < it.it1_; - } - - private: - const_iterator11_type it1_; - const_subiterator2_type it2_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it1_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ == it.it1_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ < it.it1_; + } + + private: + const_iterator11_type it1_; + const_subiterator2_type it2_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } + +#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR + class const_iterator2: + public container_const_reference, + public iterator_base_traits::template + iterator_base::type { + public: + typedef typename E1::const_iterator2::iterator_category iterator_category; + typedef typename matrix_binary_scalar2::difference_type difference_type; + typedef typename matrix_binary_scalar2::value_type value_type; + typedef typename matrix_binary_scalar2::const_reference reference; + typedef typename matrix_binary_scalar2::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2): + container_const_reference (mbs), it1_ (it1), it2_ (it2) {} + + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it1_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it1_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ - it.it1_; + } -#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::template - iterator_base::type { - public: - typedef typename E1::const_iterator2::iterator_category iterator_category; - typedef typename matrix_binary_scalar2::difference_type difference_type; - typedef typename matrix_binary_scalar2::value_type value_type; - typedef typename matrix_binary_scalar2::const_reference reference; - typedef typename matrix_binary_scalar2::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2): - container_const_reference (mbs), it1_ (it1), it2_ (it2) {} - - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it1_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it1_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ - it.it1_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return functor_type::apply (*it1_, it2_); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return functor_type::apply (*it1_, it2_); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it1_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ == it.it1_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - // FIXME we shouldn't compare floats - // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ < it.it1_; - } - - private: - const_iterator12_type it1_; - const_subiterator2_type it2_; - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_binary_scalar2_traits { - typedef matrix_binary_scalar2 expression_type; // allow E2 to be builtin type + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it1_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ == it.it1_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + // FIXME we shouldn't compare floats + // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ < it.it1_; + } + + private: + const_iterator12_type it1_; + const_subiterator2_type it2_; + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_binary_scalar2_traits { + typedef matrix_binary_scalar2 expression_type; // allow E2 to be builtin type #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E1::matrix_temporary_type result_type; -#endif - }; - - // (m * t) [i] [j] = m [i] [j] * t - template - BOOST_UBLAS_INLINE - typename boost::enable_if< is_convertible, - typename matrix_binary_scalar2_traits >::result_type - >::type - operator * (const matrix_expression &e1, - const T2 &e2) { - typedef typename matrix_binary_scalar2_traits >::expression_type expression_type; - return expression_type (e1 (), e2); - } - - // (m / t) [i] [j] = m [i] [j] / t - template - BOOST_UBLAS_INLINE - typename boost::enable_if< is_convertible, - typename matrix_binary_scalar2_traits >::result_type - >::type - operator / (const matrix_expression &e1, - const T2 &e2) { - typedef typename matrix_binary_scalar2_traits >::expression_type expression_type; - return expression_type (e1 (), e2); - } - - - template - class matrix_vector_binary1: - public vector_expression > { - - public: - typedef E1 expression1_type; - typedef E2 expression2_type; - private: - typedef F functor_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - private: - typedef matrix_vector_binary1 self_type; - public: + typedef typename E1::matrix_temporary_type result_type; +#endif +}; + +// (m * t) [i] [j] = m [i] [j] * t +template +BOOST_UBLAS_INLINE +typename boost::enable_if< is_convertible, +typename matrix_binary_scalar2_traits >::result_type +>::type +operator * (const matrix_expression &e1, + const T2 &e2) { + typedef typename matrix_binary_scalar2_traits >::expression_type expression_type; + return expression_type (e1 (), e2); +} + +// (m / t) [i] [j] = m [i] [j] / t +template +BOOST_UBLAS_INLINE +typename boost::enable_if< is_convertible, +typename matrix_binary_scalar2_traits >::result_type +>::type +operator / (const matrix_expression &e1, + const T2 &e2) { + typedef typename matrix_binary_scalar2_traits >::expression_type expression_type; + return expression_type (e1 (), e2); +} + + +template +class matrix_vector_binary1: + public vector_expression > { + +public: + typedef E1 expression1_type; + typedef E2 expression2_type; +private: + typedef F functor_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; +private: + typedef matrix_vector_binary1 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using vector_expression::operator (); -#endif - static const unsigned complexity = 1; - typedef typename promote_traits::promote_type size_type; - typedef typename promote_traits::promote_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size () const { - return e1_.size1 (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression1_closure_type &expression1 () const { - return e1_; - } - BOOST_UBLAS_INLINE - const expression2_closure_type &expression2 () const { - return e2_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e1_, e2_, i); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_vector_binary1 &mvb1) const { - return (*this).expression1 ().same_closure (mvb1.expression1 ()) && - (*this).expression2 ().same_closure (mvb1.expression2 ()); - } - - // Iterator types - private: - typedef typename E1::const_iterator1 const_subiterator1_type; - typedef typename E2::const_iterator const_subiterator2_type; - typedef const value_type *const_pointer; - - public: + using vector_expression::operator (); +#endif + static const unsigned complexity = 1; + typedef typename promote_traits::promote_type size_type; + typedef typename promote_traits::promote_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size () const { + return e1_.size1 (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression1_closure_type &expression1 () const { + return e1_; + } + BOOST_UBLAS_INLINE + const expression2_closure_type &expression2 () const { + return e2_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e1_, e2_, i); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_vector_binary1 &mvb1) const { + return (*this).expression1 ().same_closure (mvb1.expression1 ()) && + (*this).expression2 ().same_closure (mvb1.expression2 ()); + } + + // Iterator types +private: + typedef typename E1::const_iterator1 const_subiterator1_type; + typedef typename E2::const_iterator const_subiterator2_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator const_iterator; - typedef const_iterator iterator; + typedef indexed_const_iterator const_iterator; + typedef const_iterator iterator; #else - class const_iterator; - typedef const_iterator iterator; + class const_iterator; + typedef const_iterator iterator; #endif - // Element lookup - BOOST_UBLAS_INLINE - const_iterator find (size_type i) const { + // Element lookup + BOOST_UBLAS_INLINE + const_iterator find (size_type i) const { #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - const_subiterator1_type it1 (e1_.find1 (0, i, 0)); - return const_iterator (*this, it1.index1 ()); + const_subiterator1_type it1 (e1_.find1 (0, i, 0)); + return const_iterator (*this, it1.index1 ()); #else - return const_iterator (*this, e1_.find1 (0, i, 0)); + return const_iterator (*this, e1_.find1 (0, i, 0)); #endif - } + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_vector_binary1::difference_type difference_type; - typedef typename matrix_vector_binary1::value_type value_type; - typedef typename matrix_vector_binary1::const_reference reference; - typedef typename matrix_vector_binary1::const_pointer pointer; - - // Construction and destruction + class const_iterator: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_vector_binary1::difference_type difference_type; + typedef typename matrix_vector_binary1::value_type value_type; + typedef typename matrix_vector_binary1::const_reference reference; + typedef typename matrix_vector_binary1::const_pointer pointer; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator (): - container_const_reference (), it1_ (), e2_begin_ (), e2_end_ () {} - BOOST_UBLAS_INLINE - const_iterator (const self_type &mvb, const const_subiterator1_type &it1): - container_const_reference (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {} + BOOST_UBLAS_INLINE + const_iterator (): + container_const_reference (), it1_ (), e2_begin_ (), e2_end_ () {} + BOOST_UBLAS_INLINE + const_iterator (const self_type &mvb, const const_subiterator1_type &it1): + container_const_reference (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {} #else - BOOST_UBLAS_INLINE - const_iterator (): - container_const_reference (), it1_ () {} - BOOST_UBLAS_INLINE - const_iterator (const self_type &mvb, const const_subiterator1_type &it1): - container_const_reference (mvb), it1_ (it1) {} -#endif - - private: - // Dense random access specialization - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - const self_type &mvb = (*this) (); + BOOST_UBLAS_INLINE + const_iterator (): + container_const_reference (), it1_ () {} + BOOST_UBLAS_INLINE + const_iterator (const self_type &mvb, const const_subiterator1_type &it1): + container_const_reference (mvb), it1_ (it1) {} +#endif + + private: + // Dense random access specialization + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + const self_type &mvb = (*this) (); #ifdef BOOST_UBLAS_USE_INDEXING - return mvb (index ()); + return mvb (index ()); #elif BOOST_UBLAS_USE_ITERATING - difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); + difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_.begin (), e2_begin_); + return functor_type::apply (size, it1_.begin (), e2_begin_); #else - return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ()); + return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ()); #endif #else - difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) + difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ()); + if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_.begin (), e2_begin_); + return functor_type::apply (size, it1_.begin (), e2_begin_); #else - return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ()); + return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ()); #endif - else - return mvb (index ()); + else + return mvb (index ()); #endif - } + } - // Packed bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { + // Packed bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_); + return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_); #else - const self_type &mvb = (*this) (); + const self_type &mvb = (*this) (); #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - mvb.expression2 ().begin (), mvb.expression2 ().end ()); + return functor_type::apply (it1_.begin (), it1_.end (), + mvb.expression2 ().begin (), mvb.expression2 ().end ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - mvb.expression2 ().begin (), mvb.expression2 ().end ()); + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + mvb.expression2 ().begin (), mvb.expression2 ().end ()); #endif #endif - } + } - // Sparse bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { + // Sparse bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ()); #else - const self_type &mvb = (*this) (); + const self_type &mvb = (*this) (); #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ()); -#endif -#endif - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator &operator ++ () { - ++ it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator -- () { - -- it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator += (difference_type n) { - it1_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator -= (difference_type n) { - it1_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it1_ - it.it1_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it1_.index1 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator &operator = (const const_iterator &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ()); +#endif +#endif + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator &operator ++ () { + ++ it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator -- () { + -- it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator += (difference_type n) { + it1_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator -= (difference_type n) { + it1_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it1_ - it.it1_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } + + // Index + BOOST_UBLAS_INLINE + size_type index () const { + return it1_.index1 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator &operator = (const const_iterator &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - e2_begin_ = it.e2_begin_; - e2_end_ = it.e2_end_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it1_ == it.it1_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it1_ < it.it1_; - } - - private: - const_subiterator1_type it1_; + e2_begin_ = it.e2_begin_; + e2_end_ = it.e2_end_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it1_ == it.it1_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it1_ < it.it1_; + } + + private: + const_subiterator1_type it1_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - // Mutable due to assignment - /* const */ const_subiterator2_type e2_begin_; - /* const */ const_subiterator2_type e2_end_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator begin () const { - return find (0); - } - BOOST_UBLAS_INLINE - const_iterator cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE - const_iterator end () const { - return find (size ()); - } - BOOST_UBLAS_INLINE - const_iterator cend () const { - return end (); - } - - // Reverse iterator - typedef reverse_iterator_base const_reverse_iterator; - - BOOST_UBLAS_INLINE - const_reverse_iterator rbegin () const { - return const_reverse_iterator (end ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator rend () const { - return const_reverse_iterator (begin ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator crend () const { - return rend (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_vector_binary1_traits { - typedef unknown_storage_tag storage_category; - typedef row_major_tag orientation_category; - typedef typename promote_traits::promote_type promote_type; - typedef matrix_vector_binary1 > expression_type; + // Mutable due to assignment + /* const */ const_subiterator2_type e2_begin_; + /* const */ const_subiterator2_type e2_end_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator begin () const { + return find (0); + } + BOOST_UBLAS_INLINE + const_iterator cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE + const_iterator end () const { + return find (size ()); + } + BOOST_UBLAS_INLINE + const_iterator cend () const { + return end (); + } + + // Reverse iterator + typedef reverse_iterator_base const_reverse_iterator; + + BOOST_UBLAS_INLINE + const_reverse_iterator rbegin () const { + return const_reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator rend () const { + return const_reverse_iterator (begin ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator crend () const { + return rend (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_vector_binary1_traits { + typedef unknown_storage_tag storage_category; + typedef row_major_tag orientation_category; + typedef typename promote_traits::promote_type promote_type; + typedef matrix_vector_binary1 > expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E1::vector_temporary_type result_type; -#endif - }; - - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary1_traits::result_type - prod (const matrix_expression &e1, - const vector_expression &e2, - unknown_storage_tag, - row_major_tag) { - typedef typename matrix_vector_binary1_traits::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary1_traits::result_type - prod (const matrix_expression &e1, - const vector_expression &e2) { - BOOST_STATIC_ASSERT (E2::complexity == 0); - typedef typename matrix_vector_binary1_traits::storage_category storage_category; - typedef typename matrix_vector_binary1_traits::orientation_category orientation_category; - return prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const matrix_expression &e1, - const vector_expression &e2, - unknown_storage_tag, - row_major_tag) { - typedef typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const matrix_expression &e1, - const vector_expression &e2) { - BOOST_STATIC_ASSERT (E2::complexity == 0); - typedef typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::storage_category storage_category; - typedef typename matrix_vector_binary1_traits::precision_type, E1, - typename type_traits::precision_type, E2>::orientation_category orientation_category; - return prec_prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - V & - prod (const matrix_expression &e1, - const vector_expression &e2, - V &v) { - return v.assign (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V & - prec_prod (const matrix_expression &e1, - const vector_expression &e2, - V &v) { - return v.assign (prec_prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V - prod (const matrix_expression &e1, - const vector_expression &e2) { - return V (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V - prec_prod (const matrix_expression &e1, - const vector_expression &e2) { - return V (prec_prod (e1, e2)); - } - - template - class matrix_vector_binary2: - public vector_expression > { - - typedef E1 expression1_type; - typedef E2 expression2_type; - typedef F functor_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - private: - typedef matrix_vector_binary2 self_type; - public: + typedef typename E1::vector_temporary_type result_type; +#endif +}; + +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary1_traits::result_type +prod (const matrix_expression &e1, + const vector_expression &e2, + unknown_storage_tag, + row_major_tag) { + typedef typename matrix_vector_binary1_traits::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary1_traits::result_type +prod (const matrix_expression &e1, + const vector_expression &e2) { + BOOST_STATIC_ASSERT (E2::complexity == 0); + typedef typename matrix_vector_binary1_traits::storage_category storage_category; + typedef typename matrix_vector_binary1_traits::orientation_category orientation_category; + return prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary1_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const matrix_expression &e1, + const vector_expression &e2, + unknown_storage_tag, + row_major_tag) { + typedef typename matrix_vector_binary1_traits::precision_type, E1, + typename type_traits::precision_type, E2>::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary1_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const matrix_expression &e1, + const vector_expression &e2) { + BOOST_STATIC_ASSERT (E2::complexity == 0); + typedef typename matrix_vector_binary1_traits::precision_type, E1, + typename type_traits::precision_type, E2>::storage_category storage_category; + typedef typename matrix_vector_binary1_traits::precision_type, E1, + typename type_traits::precision_type, E2>::orientation_category orientation_category; + return prec_prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +V & +prod (const matrix_expression &e1, + const vector_expression &e2, + V &v) { + return v.assign (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V & +prec_prod (const matrix_expression &e1, + const vector_expression &e2, + V &v) { + return v.assign (prec_prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V +prod (const matrix_expression &e1, + const vector_expression &e2) { + return V (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V +prec_prod (const matrix_expression &e1, + const vector_expression &e2) { + return V (prec_prod (e1, e2)); +} + +template +class matrix_vector_binary2: + public vector_expression > { + + typedef E1 expression1_type; + typedef E2 expression2_type; + typedef F functor_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; +private: + typedef matrix_vector_binary2 self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using vector_expression::operator (); -#endif - static const unsigned complexity = 1; - typedef typename promote_traits::promote_type size_type; - typedef typename promote_traits::promote_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size () const { - return e2_.size2 (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression1_closure_type &expression1 () const { - return e1_; - } - BOOST_UBLAS_INLINE - const expression2_closure_type &expression2 () const { - return e2_; - } - public: - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type j) const { - return functor_type::apply (e1_, e2_, j); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_vector_binary2 &mvb2) const { - return (*this).expression1 ().same_closure (mvb2.expression1 ()) && - (*this).expression2 ().same_closure (mvb2.expression2 ()); - } - - // Iterator types - private: - typedef typename E1::const_iterator const_subiterator1_type; - typedef typename E2::const_iterator2 const_subiterator2_type; - typedef const value_type *const_pointer; - - public: + using vector_expression::operator (); +#endif + static const unsigned complexity = 1; + typedef typename promote_traits::promote_type size_type; + typedef typename promote_traits::promote_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size () const { + return e2_.size2 (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression1_closure_type &expression1 () const { + return e1_; + } + BOOST_UBLAS_INLINE + const expression2_closure_type &expression2 () const { + return e2_; + } +public: + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type j) const { + return functor_type::apply (e1_, e2_, j); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_vector_binary2 &mvb2) const { + return (*this).expression1 ().same_closure (mvb2.expression1 ()) && + (*this).expression2 ().same_closure (mvb2.expression2 ()); + } + + // Iterator types +private: + typedef typename E1::const_iterator const_subiterator1_type; + typedef typename E2::const_iterator2 const_subiterator2_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef indexed_const_iterator const_iterator; - typedef const_iterator iterator; + typedef indexed_const_iterator const_iterator; + typedef const_iterator iterator; #else - class const_iterator; - typedef const_iterator iterator; + class const_iterator; + typedef const_iterator iterator; #endif - // Element lookup - BOOST_UBLAS_INLINE - const_iterator find (size_type j) const { + // Element lookup + BOOST_UBLAS_INLINE + const_iterator find (size_type j) const { #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - const_subiterator2_type it2 (e2_.find2 (0, 0, j)); - return const_iterator (*this, it2.index2 ()); + const_subiterator2_type it2 (e2_.find2 (0, 0, j)); + return const_iterator (*this, it2.index2 ()); #else - return const_iterator (*this, e2_.find2 (0, 0, j)); + return const_iterator (*this, e2_.find2 (0, 0, j)); #endif - } + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_vector_binary2::difference_type difference_type; - typedef typename matrix_vector_binary2::value_type value_type; - typedef typename matrix_vector_binary2::const_reference reference; - typedef typename matrix_vector_binary2::const_pointer pointer; - - // Construction and destruction + class const_iterator: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_vector_binary2::difference_type difference_type; + typedef typename matrix_vector_binary2::value_type value_type; + typedef typename matrix_vector_binary2::const_reference reference; + typedef typename matrix_vector_binary2::const_pointer pointer; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator (): - container_const_reference (), it2_ (), e1_begin_ (), e1_end_ () {} - BOOST_UBLAS_INLINE - const_iterator (const self_type &mvb, const const_subiterator2_type &it2): - container_const_reference (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {} + BOOST_UBLAS_INLINE + const_iterator (): + container_const_reference (), it2_ (), e1_begin_ (), e1_end_ () {} + BOOST_UBLAS_INLINE + const_iterator (const self_type &mvb, const const_subiterator2_type &it2): + container_const_reference (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {} #else - BOOST_UBLAS_INLINE - const_iterator (): - container_const_reference (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator (const self_type &mvb, const const_subiterator2_type &it2): - container_const_reference (mvb), it2_ (it2) {} -#endif - - private: - // Dense random access specialization - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - const self_type &mvb = (*this) (); + BOOST_UBLAS_INLINE + const_iterator (): + container_const_reference (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator (const self_type &mvb, const const_subiterator2_type &it2): + container_const_reference (mvb), it2_ (it2) {} +#endif + + private: + // Dense random access specialization + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + const self_type &mvb = (*this) (); #ifdef BOOST_UBLAS_USE_INDEXING - return mvb (index ()); + return mvb (index ()); #elif BOOST_UBLAS_USE_ITERATING - difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); + difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, e1_begin_, it2_.begin ()); + return functor_type::apply (size, e1_begin_, it2_.begin ()); #else - return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ()); + return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ()); #endif #else - difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) + difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ()); + if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, e1_begin_, it2_.begin ()); + return functor_type::apply (size, e1_begin_, it2_.begin ()); #else - return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ()); + return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ()); #endif - else - return mvb (index ()); + else + return mvb (index ()); #endif - } + } - // Packed bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { + // Packed bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ()); + return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ()); #else - const self_type &mvb = (*this) (); + const self_type &mvb = (*this) (); #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), - it2_.begin (), it2_.end ()); + return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), + it2_.begin (), it2_.end ()); #else - return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ())); + return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ())); #endif #endif - } + } - // Sparse bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { + // Sparse bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else - const self_type &mvb = (*this) (); + const self_type &mvb = (*this) (); #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), - it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), + it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else - return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); -#endif -#endif - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator &operator ++ () { - ++ it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator -- () { - -- it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator += (difference_type n) { - it2_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator &operator -= (difference_type n) { - it2_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it2_ - it.it2_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } - - // Index - BOOST_UBLAS_INLINE - size_type index () const { - return it2_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator &operator = (const const_iterator &it) { - container_const_reference::assign (&it ()); - it2_ = it.it2_; + return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); +#endif +#endif + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator &operator ++ () { + ++ it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator -- () { + -- it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator += (difference_type n) { + it2_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator &operator -= (difference_type n) { + it2_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it2_ - it.it2_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } + + // Index + BOOST_UBLAS_INLINE + size_type index () const { + return it2_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator &operator = (const const_iterator &it) { + container_const_reference::assign (&it ()); + it2_ = it.it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - e1_begin_ = it.e1_begin_; - e1_end_ = it.e1_end_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it2_ == it.it2_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - return it2_ < it.it2_; - } - - private: - const_subiterator2_type it2_; + e1_begin_ = it.e1_begin_; + e1_end_ = it.e1_end_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it2_ == it.it2_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + return it2_ < it.it2_; + } + + private: + const_subiterator2_type it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - // Mutable due to assignment - /* const */ const_subiterator1_type e1_begin_; - /* const */ const_subiterator1_type e1_end_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator begin () const { - return find (0); - } - BOOST_UBLAS_INLINE - const_iterator cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE - const_iterator end () const { - return find (size ()); - } - BOOST_UBLAS_INLINE - const_iterator cend () const { - return end (); - } - - // Reverse iterator - typedef reverse_iterator_base const_reverse_iterator; - - BOOST_UBLAS_INLINE - const_reverse_iterator rbegin () const { - return const_reverse_iterator (end ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator rend () const { - return const_reverse_iterator (begin ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator crend () const { - return rend (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_vector_binary2_traits { - typedef unknown_storage_tag storage_category; - typedef column_major_tag orientation_category; - typedef typename promote_traits::promote_type promote_type; - typedef matrix_vector_binary2 > expression_type; + // Mutable due to assignment + /* const */ const_subiterator1_type e1_begin_; + /* const */ const_subiterator1_type e1_end_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator begin () const { + return find (0); + } + BOOST_UBLAS_INLINE + const_iterator cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE + const_iterator end () const { + return find (size ()); + } + BOOST_UBLAS_INLINE + const_iterator cend () const { + return end (); + } + + // Reverse iterator + typedef reverse_iterator_base const_reverse_iterator; + + BOOST_UBLAS_INLINE + const_reverse_iterator rbegin () const { + return const_reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator rend () const { + return const_reverse_iterator (begin ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator crend () const { + return rend (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_vector_binary2_traits { + typedef unknown_storage_tag storage_category; + typedef column_major_tag orientation_category; + typedef typename promote_traits::promote_type promote_type; + typedef matrix_vector_binary2 > expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E2::vector_temporary_type result_type; -#endif - }; - - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary2_traits::result_type - prod (const vector_expression &e1, - const matrix_expression &e2, - unknown_storage_tag, - column_major_tag) { - typedef typename matrix_vector_binary2_traits::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary2_traits::result_type - prod (const vector_expression &e1, - const matrix_expression &e2) { - BOOST_STATIC_ASSERT (E1::complexity == 0); - typedef typename matrix_vector_binary2_traits::storage_category storage_category; - typedef typename matrix_vector_binary2_traits::orientation_category orientation_category; - return prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const vector_expression &e1, - const matrix_expression &e2, - unknown_storage_tag, - column_major_tag) { - typedef typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const vector_expression &e1, - const matrix_expression &e2) { - BOOST_STATIC_ASSERT (E1::complexity == 0); - typedef typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::storage_category storage_category; - typedef typename matrix_vector_binary2_traits::precision_type, E1, - typename type_traits::precision_type, E2>::orientation_category orientation_category; - return prec_prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - V & - prod (const vector_expression &e1, - const matrix_expression &e2, - V &v) { - return v.assign (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V & - prec_prod (const vector_expression &e1, - const matrix_expression &e2, - V &v) { - return v.assign (prec_prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V - prod (const vector_expression &e1, - const matrix_expression &e2) { - return V (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - V - prec_prod (const vector_expression &e1, - const matrix_expression &e2) { - return V (prec_prod (e1, e2)); - } - - template - class matrix_matrix_binary: - public matrix_expression > { - - public: - typedef E1 expression1_type; - typedef E2 expression2_type; - private: - typedef F functor_type; - public: - typedef typename E1::const_closure_type expression1_closure_type; - typedef typename E2::const_closure_type expression2_closure_type; - private: - typedef matrix_matrix_binary self_type; - public: + typedef typename E2::vector_temporary_type result_type; +#endif +}; + +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary2_traits::result_type +prod (const vector_expression &e1, + const matrix_expression &e2, + unknown_storage_tag, + column_major_tag) { + typedef typename matrix_vector_binary2_traits::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary2_traits::result_type +prod (const vector_expression &e1, + const matrix_expression &e2) { + BOOST_STATIC_ASSERT (E1::complexity == 0); + typedef typename matrix_vector_binary2_traits::storage_category storage_category; + typedef typename matrix_vector_binary2_traits::orientation_category orientation_category; + return prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary2_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const vector_expression &e1, + const matrix_expression &e2, + unknown_storage_tag, + column_major_tag) { + typedef typename matrix_vector_binary2_traits::precision_type, E1, + typename type_traits::precision_type, E2>::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_vector_binary2_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const vector_expression &e1, + const matrix_expression &e2) { + BOOST_STATIC_ASSERT (E1::complexity == 0); + typedef typename matrix_vector_binary2_traits::precision_type, E1, + typename type_traits::precision_type, E2>::storage_category storage_category; + typedef typename matrix_vector_binary2_traits::precision_type, E1, + typename type_traits::precision_type, E2>::orientation_category orientation_category; + return prec_prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +V & +prod (const vector_expression &e1, + const matrix_expression &e2, + V &v) { + return v.assign (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V & +prec_prod (const vector_expression &e1, + const matrix_expression &e2, + V &v) { + return v.assign (prec_prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V +prod (const vector_expression &e1, + const matrix_expression &e2) { + return V (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +V +prec_prod (const vector_expression &e1, + const matrix_expression &e2) { + return V (prec_prod (e1, e2)); +} + +template +class matrix_matrix_binary: + public matrix_expression > { + +public: + typedef E1 expression1_type; + typedef E2 expression2_type; +private: + typedef F functor_type; +public: + typedef typename E1::const_closure_type expression1_closure_type; + typedef typename E2::const_closure_type expression2_closure_type; +private: + typedef matrix_matrix_binary self_type; +public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS - using matrix_expression::operator (); -#endif - static const unsigned complexity = 1; - typedef typename promote_traits::promote_type size_type; - typedef typename promote_traits::promote_type difference_type; - typedef typename F::result_type value_type; - typedef value_type const_reference; - typedef const_reference reference; - typedef const self_type const_closure_type; - typedef const_closure_type closure_type; - typedef unknown_orientation_tag orientation_category; - typedef unknown_storage_tag storage_category; - - // Construction and destruction - BOOST_UBLAS_INLINE - matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2): - e1_ (e1), e2_ (e2) {} - - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return e1_.size1 (); - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return e2_.size2 (); - } - - public: - // Expression accessors - BOOST_UBLAS_INLINE - const expression1_closure_type &expression1 () const { - return e1_; - } - BOOST_UBLAS_INLINE - const expression2_closure_type &expression2 () const { - return e2_; - } - - public: - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i, size_type j) const { - return functor_type::apply (e1_, e2_, i, j); - } - - // Element access - BOOST_UBLAS_INLINE - const_reference operator () (size_type i) const { - return functor_type::apply (e1_, e2_, i); - } - - // Closure comparison - BOOST_UBLAS_INLINE - bool same_closure (const matrix_matrix_binary &mmb) const { - return (*this).expression1 ().same_closure (mmb.expression1 ()) && - (*this).expression2 ().same_closure (mmb.expression2 ()); - } - - // Iterator types - private: - typedef typename E1::const_iterator1 const_iterator11_type; - typedef typename E1::const_iterator2 const_iterator12_type; - typedef typename E2::const_iterator1 const_iterator21_type; - typedef typename E2::const_iterator2 const_iterator22_type; - typedef const value_type *const_pointer; - - public: + using matrix_expression::operator (); +#endif + static const unsigned complexity = 1; + typedef typename promote_traits::promote_type size_type; + typedef typename promote_traits::promote_type difference_type; + typedef typename F::result_type value_type; + typedef value_type const_reference; + typedef const_reference reference; + typedef const self_type const_closure_type; + typedef const_closure_type closure_type; + typedef unknown_orientation_tag orientation_category; + typedef unknown_storage_tag storage_category; + + // Construction and destruction + BOOST_UBLAS_INLINE + matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2): + e1_ (e1), e2_ (e2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return e1_.size1 (); + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return e2_.size2 (); + } + +public: + // Expression accessors + BOOST_UBLAS_INLINE + const expression1_closure_type &expression1 () const { + return e1_; + } + BOOST_UBLAS_INLINE + const expression2_closure_type &expression2 () const { + return e2_; + } + +public: + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i, size_type j) const { + return functor_type::apply (e1_, e2_, i, j); + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator () (size_type i) const { + return functor_type::apply (e1_, e2_, i); + } + + // Closure comparison + BOOST_UBLAS_INLINE + bool same_closure (const matrix_matrix_binary &mmb) const { + return (*this).expression1 ().same_closure (mmb.expression1 ()) && + (*this).expression2 ().same_closure (mmb.expression2 ()); + } + + // Iterator types +private: + typedef typename E1::const_iterator1 const_iterator11_type; + typedef typename E1::const_iterator2 const_iterator12_type; + typedef typename E2::const_iterator1 const_iterator21_type; + typedef typename E2::const_iterator2 const_iterator22_type; + typedef const value_type *const_pointer; + +public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef indexed_const_iterator1 const_iterator1; - typedef const_iterator1 iterator1; - typedef indexed_const_iterator2 const_iterator2; - typedef const_iterator2 iterator2; + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef indexed_const_iterator1 const_iterator1; + typedef const_iterator1 iterator1; + typedef indexed_const_iterator2 const_iterator2; + typedef const_iterator2 iterator2; #else - class const_iterator1; - typedef const_iterator1 iterator1; - class const_iterator2; - typedef const_iterator2 iterator2; -#endif - typedef reverse_iterator_base1 const_reverse_iterator1; - typedef reverse_iterator_base2 const_reverse_iterator2; - - // Element lookup - BOOST_UBLAS_INLINE - const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { - // FIXME sparse matrix tests fail! - // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); - const_iterator11_type it11 (e1_.find1 (0, i, 0)); + class const_iterator1; + typedef const_iterator1 iterator1; + class const_iterator2; + typedef const_iterator2 iterator2; +#endif + typedef reverse_iterator_base1 const_reverse_iterator1; + typedef reverse_iterator_base2 const_reverse_iterator2; + + // Element lookup + BOOST_UBLAS_INLINE + const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { + // FIXME sparse matrix tests fail! + // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); + const_iterator11_type it11 (e1_.find1 (0, i, 0)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator1 (*this, it11.index1 (), j); + return const_iterator1 (*this, it11.index1 (), j); #else - // FIXME sparse matrix tests fail! - // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); - const_iterator22_type it22 (e2_.find2 (0, 0, j)); - return const_iterator1 (*this, it11, it22); -#endif - } - BOOST_UBLAS_INLINE - const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { - // FIXME sparse matrix tests fail! - // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); - const_iterator22_type it22 (e2_.find2 (0, 0, j)); + // FIXME sparse matrix tests fail! + // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); + const_iterator22_type it22 (e2_.find2 (0, 0, j)); + return const_iterator1 (*this, it11, it22); +#endif + } + BOOST_UBLAS_INLINE + const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { + // FIXME sparse matrix tests fail! + // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); + const_iterator22_type it22 (e2_.find2 (0, 0, j)); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR - return const_iterator2 (*this, i, it22.index2 ()); + return const_iterator2 (*this, i, it22.index2 ()); #else - // FIXME sparse matrix tests fail! - // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); - const_iterator11_type it11 (e1_.find1 (0, i, 0)); - return const_iterator2 (*this, it11, it22); + // FIXME sparse matrix tests fail! + // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); + const_iterator11_type it11 (e1_.find1 (0, i, 0)); + return const_iterator2 (*this, it11, it22); #endif - } + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator1: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_matrix_binary::difference_type difference_type; - typedef typename matrix_matrix_binary::value_type value_type; - typedef typename matrix_matrix_binary::const_reference reference; - typedef typename matrix_matrix_binary::const_pointer pointer; - - typedef const_iterator2 dual_iterator_type; - typedef const_reverse_iterator2 dual_reverse_iterator_type; - - // Construction and destruction + class const_iterator1: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_matrix_binary::difference_type difference_type; + typedef typename matrix_matrix_binary::value_type value_type; + typedef typename matrix_matrix_binary::const_reference reference; + typedef typename matrix_matrix_binary::const_pointer pointer; + + typedef const_iterator2 dual_iterator_type; + typedef const_reverse_iterator2 dual_reverse_iterator_type; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): - container_const_reference (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {} + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): + container_const_reference (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {} #else - BOOST_UBLAS_INLINE - const_iterator1 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): - container_const_reference (mmb), it1_ (it1), it2_ (it2) {} -#endif - - private: - // Random access specialization - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - const self_type &mmb = (*this) (); + BOOST_UBLAS_INLINE + const_iterator1 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): + container_const_reference (mmb), it1_ (it1), it2_ (it2) {} +#endif + + private: + // Random access specialization + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + const self_type &mmb = (*this) (); #ifdef BOOST_UBLAS_USE_INDEXING - return mmb (index1 (), index2 ()); + return mmb (index1 (), index2 ()); #elif BOOST_UBLAS_USE_ITERATING - difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); + difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_.begin (), it2_begin_); + return functor_type::apply (size, it1_.begin (), it2_begin_); #else - return functor_type::apply (size, it1_.begin (), it2_.begin ()); + return functor_type::apply (size, it1_.begin (), it2_.begin ()); #endif #else - difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) + difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); + if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_.begin (), it2_begin_); + return functor_type::apply (size, it1_.begin (), it2_begin_); #else - return functor_type::apply (size, it1_.begin (), it2_.begin ()); + return functor_type::apply (size, it1_.begin (), it2_.begin ()); #endif - else - return mmb (index1 (), index2 ()); + else + return mmb (index1 (), index2 ()); #endif - } + } - // Packed bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { + // Packed bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_.begin (), it1_.end (), - it2_begin_, it2_end_, packed_random_access_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_begin_, it2_end_, packed_random_access_iterator_tag ()); #else #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ()); + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ()); #endif #endif - } + } - // Sparse bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { + // Sparse bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_.begin (), it1_.end (), - it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ()); #else #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); -#endif -#endif - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator1 &operator ++ () { - ++ it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -- () { - -- it1_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator += (difference_type n) { - it1_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator1 &operator -= (difference_type n) { - it1_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ - it.it1_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); +#endif +#endif + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator1 &operator ++ () { + ++ it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -- () { + -- it1_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator += (difference_type n) { + it1_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator1 &operator -= (difference_type n) { + it1_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ - it.it1_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 begin () const { - return (*this) ().find2 (1, index1 (), 0); - } - BOOST_UBLAS_INLINE + const_iterator2 begin () const { + return (*this) ().find2 (1, index1 (), 0); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator2 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 end () const { - return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); - } - BOOST_UBLAS_INLINE + const_iterator2 end () const { + return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator2 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator2 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rbegin () const { - return const_reverse_iterator2 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin () const { + return const_reverse_iterator2 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator2 rend () const { - return const_reverse_iterator2 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator2 rend () const { + return const_reverse_iterator2 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator2 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator1 &operator = (const const_iterator1 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; + typename self_type:: +#endif + const_reverse_iterator2 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator1 &operator = (const const_iterator1 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - it2_begin_ = it.it2_begin_; - it2_end_ = it.it2_end_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ == it.it1_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator1 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); - return it1_ < it.it1_; - } - - private: - const_iterator11_type it1_; - // Mutable due to assignment - /* const */ const_iterator22_type it2_; + it2_begin_ = it.it2_begin_; + it2_end_ = it.it2_end_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ == it.it1_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator1 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); + return it1_ < it.it1_; + } + + private: + const_iterator11_type it1_; + // Mutable due to assignment + /* const */ const_iterator22_type it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - /* const */ const_iterator21_type it2_begin_; - /* const */ const_iterator21_type it2_end_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator1 begin1 () const { - return find1 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cbegin1 () const { - return begin1 (); - } - BOOST_UBLAS_INLINE - const_iterator1 end1 () const { - return find1 (0, size1 (), 0); - } - BOOST_UBLAS_INLINE - const_iterator1 cend1 () const { - return end1 (); - } + /* const */ const_iterator21_type it2_begin_; + /* const */ const_iterator21_type it2_end_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator1 begin1 () const { + return find1 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cbegin1 () const { + return begin1 (); + } + BOOST_UBLAS_INLINE + const_iterator1 end1 () const { + return find1 (0, size1 (), 0); + } + BOOST_UBLAS_INLINE + const_iterator1 cend1 () const { + return end1 (); + } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR - class const_iterator2: - public container_const_reference, - public iterator_base_traits::iterator_category>::template - iterator_base::type { - public: - typedef typename iterator_restrict_traits::iterator_category iterator_category; - typedef typename matrix_matrix_binary::difference_type difference_type; - typedef typename matrix_matrix_binary::value_type value_type; - typedef typename matrix_matrix_binary::const_reference reference; - typedef typename matrix_matrix_binary::const_pointer pointer; - - typedef const_iterator1 dual_iterator_type; - typedef const_reverse_iterator1 dual_reverse_iterator_type; - - // Construction and destruction + class const_iterator2: + public container_const_reference, + public iterator_base_traits::iterator_category>::template + iterator_base::type { + public: + typedef typename iterator_restrict_traits::iterator_category iterator_category; + typedef typename matrix_matrix_binary::difference_type difference_type; + typedef typename matrix_matrix_binary::value_type value_type; + typedef typename matrix_matrix_binary::const_reference reference; + typedef typename matrix_matrix_binary::const_pointer pointer; + + typedef const_iterator1 dual_iterator_type; + typedef const_reverse_iterator1 dual_reverse_iterator_type; + + // Construction and destruction #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): - container_const_reference (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {} + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): + container_const_reference (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {} #else - BOOST_UBLAS_INLINE - const_iterator2 (): - container_const_reference (), it1_ (), it2_ () {} - BOOST_UBLAS_INLINE - const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): - container_const_reference (mmb), it1_ (it1), it2_ (it2) {} -#endif - - private: - // Random access specialization - BOOST_UBLAS_INLINE - value_type dereference (dense_random_access_iterator_tag) const { - const self_type &mmb = (*this) (); + BOOST_UBLAS_INLINE + const_iterator2 (): + container_const_reference (), it1_ (), it2_ () {} + BOOST_UBLAS_INLINE + const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2): + container_const_reference (mmb), it1_ (it1), it2_ (it2) {} +#endif + + private: + // Random access specialization + BOOST_UBLAS_INLINE + value_type dereference (dense_random_access_iterator_tag) const { + const self_type &mmb = (*this) (); #ifdef BOOST_UBLAS_USE_INDEXING - return mmb (index1 (), index2 ()); + return mmb (index1 (), index2 ()); #elif BOOST_UBLAS_USE_ITERATING - difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); + difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_begin_, it2_.begin ()); + return functor_type::apply (size, it1_begin_, it2_.begin ()); #else - return functor_type::apply (size, it1_.begin (), it2_.begin ()); + return functor_type::apply (size, it1_.begin (), it2_.begin ()); #endif #else - difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); - if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) + difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ()); + if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (size, it1_begin_, it2_.begin ()); + return functor_type::apply (size, it1_begin_, it2_.begin ()); #else - return functor_type::apply (size, it1_.begin (), it2_.begin ()); + return functor_type::apply (size, it1_.begin (), it2_.begin ()); #endif - else - return mmb (index1 (), index2 ()); + else + return mmb (index1 (), index2 ()); #endif - } + } - // Packed bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (packed_random_access_iterator_tag) const { + // Packed bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (packed_random_access_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_begin_, it1_end_, - it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); + return functor_type::apply (it1_begin_, it1_end_, + it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); #else #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_.begin (), it2_.end (), packed_random_access_iterator_tag ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ()); + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ()); #endif #endif - } + } - // Sparse bidirectional specialization - BOOST_UBLAS_INLINE - value_type dereference (sparse_bidirectional_iterator_tag) const { + // Sparse bidirectional specialization + BOOST_UBLAS_INLINE + value_type dereference (sparse_bidirectional_iterator_tag) const { #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - return functor_type::apply (it1_begin_, it1_end_, - it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_begin_, it1_end_, + it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - return functor_type::apply (it1_.begin (), it1_.end (), - it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); + return functor_type::apply (it1_.begin (), it1_.end (), + it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ()); #else - return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), - boost::numeric::ublas::end (it1_, iterator1_tag ()), - boost::numeric::ublas::begin (it2_, iterator2_tag ()), - boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); -#endif -#endif - } - - public: - // Arithmetic - BOOST_UBLAS_INLINE - const_iterator2 &operator ++ () { - ++ it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -- () { - -- it2_; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator += (difference_type n) { - it2_ += n; - return *this; - } - BOOST_UBLAS_INLINE - const_iterator2 &operator -= (difference_type n) { - it2_ -= n; - return *this; - } - BOOST_UBLAS_INLINE - difference_type operator - (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ - it.it2_; - } - - // Dereference - BOOST_UBLAS_INLINE - const_reference operator * () const { - return dereference (iterator_category ()); - } - BOOST_UBLAS_INLINE - const_reference operator [] (difference_type n) const { - return *(*this + n); - } + return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()), + boost::numeric::ublas::end (it1_, iterator1_tag ()), + boost::numeric::ublas::begin (it2_, iterator2_tag ()), + boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ()); +#endif +#endif + } + + public: + // Arithmetic + BOOST_UBLAS_INLINE + const_iterator2 &operator ++ () { + ++ it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -- () { + -- it2_; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator += (difference_type n) { + it2_ += n; + return *this; + } + BOOST_UBLAS_INLINE + const_iterator2 &operator -= (difference_type n) { + it2_ -= n; + return *this; + } + BOOST_UBLAS_INLINE + difference_type operator - (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ - it.it2_; + } + + // Dereference + BOOST_UBLAS_INLINE + const_reference operator * () const { + return dereference (iterator_category ()); + } + BOOST_UBLAS_INLINE + const_reference operator [] (difference_type n) const { + return *(*this + n); + } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION - BOOST_UBLAS_INLINE + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 begin () const { - return (*this) ().find1 (1, 0, index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 begin () const { + return (*this) ().find1 (1, 0, index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cbegin () const { - return begin (); - } - BOOST_UBLAS_INLINE + const_iterator1 cbegin () const { + return begin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 end () const { - return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); - } - BOOST_UBLAS_INLINE + const_iterator1 end () const { + return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_iterator1 cend () const { - return end (); - } - BOOST_UBLAS_INLINE + const_iterator1 cend () const { + return end (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rbegin () const { - return const_reverse_iterator1 (end ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin () const { + return const_reverse_iterator1 (end ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 crbegin () const { - return rbegin (); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin () const { + return rbegin (); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: + typename self_type:: #endif - const_reverse_iterator1 rend () const { - return const_reverse_iterator1 (begin ()); - } - BOOST_UBLAS_INLINE + const_reverse_iterator1 rend () const { + return const_reverse_iterator1 (begin ()); + } + BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION - typename self_type:: -#endif - const_reverse_iterator1 crend () const { - return rend (); - } -#endif - - // Indices - BOOST_UBLAS_INLINE - size_type index1 () const { - return it1_.index1 (); - } - BOOST_UBLAS_INLINE - size_type index2 () const { - return it2_.index2 (); - } - - // Assignment - BOOST_UBLAS_INLINE - const_iterator2 &operator = (const const_iterator2 &it) { - container_const_reference::assign (&it ()); - it1_ = it.it1_; - it2_ = it.it2_; + typename self_type:: +#endif + const_reverse_iterator1 crend () const { + return rend (); + } +#endif + + // Indices + BOOST_UBLAS_INLINE + size_type index1 () const { + return it1_.index1 (); + } + BOOST_UBLAS_INLINE + size_type index2 () const { + return it2_.index2 (); + } + + // Assignment + BOOST_UBLAS_INLINE + const_iterator2 &operator = (const const_iterator2 &it) { + container_const_reference::assign (&it ()); + it1_ = it.it1_; + it2_ = it.it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - it1_begin_ = it.it1_begin_; - it1_end_ = it.it1_end_; -#endif - return *this; - } - - // Comparison - BOOST_UBLAS_INLINE - bool operator == (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ == it.it2_; - } - BOOST_UBLAS_INLINE - bool operator < (const const_iterator2 &it) const { - BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); - BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); - return it2_ < it.it2_; - } - - private: - // Mutable due to assignment - /* const */ const_iterator11_type it1_; - const_iterator22_type it2_; + it1_begin_ = it.it1_begin_; + it1_end_ = it.it1_end_; +#endif + return *this; + } + + // Comparison + BOOST_UBLAS_INLINE + bool operator == (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ == it.it2_; + } + BOOST_UBLAS_INLINE + bool operator < (const const_iterator2 &it) const { + BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); + BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); + return it2_ < it.it2_; + } + + private: + // Mutable due to assignment + /* const */ const_iterator11_type it1_; + const_iterator22_type it2_; #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING - /* const */ const_iterator12_type it1_begin_; - /* const */ const_iterator12_type it1_end_; -#endif - }; -#endif - - BOOST_UBLAS_INLINE - const_iterator2 begin2 () const { - return find2 (0, 0, 0); - } - BOOST_UBLAS_INLINE - const_iterator2 cbegin2 () const { - return begin2 (); - } - BOOST_UBLAS_INLINE - const_iterator2 end2 () const { - return find2 (0, 0, size2 ()); - } - BOOST_UBLAS_INLINE - const_iterator2 cend2 () const { - return end2 (); - } - - // Reverse iterators - - BOOST_UBLAS_INLINE - const_reverse_iterator1 rbegin1 () const { - return const_reverse_iterator1 (end1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crbegin1 () const { - return rbegin1 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 rend1 () const { - return const_reverse_iterator1 (begin1 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator1 crend1 () const { - return rend1 (); - } - - BOOST_UBLAS_INLINE - const_reverse_iterator2 rbegin2 () const { - return const_reverse_iterator2 (end2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crbegin2 () const { - return rbegin2 (); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 rend2 () const { - return const_reverse_iterator2 (begin2 ()); - } - BOOST_UBLAS_INLINE - const_reverse_iterator2 crend2 () const { - return rend2 (); - } - - private: - expression1_closure_type e1_; - expression2_closure_type e2_; - }; - - template - struct matrix_matrix_binary_traits { - typedef unknown_storage_tag storage_category; - typedef unknown_orientation_tag orientation_category; - typedef typename promote_traits::promote_type promote_type; - typedef matrix_matrix_binary > expression_type; + /* const */ const_iterator12_type it1_begin_; + /* const */ const_iterator12_type it1_end_; +#endif + }; +#endif + + BOOST_UBLAS_INLINE + const_iterator2 begin2 () const { + return find2 (0, 0, 0); + } + BOOST_UBLAS_INLINE + const_iterator2 cbegin2 () const { + return begin2 (); + } + BOOST_UBLAS_INLINE + const_iterator2 end2 () const { + return find2 (0, 0, size2 ()); + } + BOOST_UBLAS_INLINE + const_iterator2 cend2 () const { + return end2 (); + } + + // Reverse iterators + + BOOST_UBLAS_INLINE + const_reverse_iterator1 rbegin1 () const { + return const_reverse_iterator1 (end1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crbegin1 () const { + return rbegin1 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 rend1 () const { + return const_reverse_iterator1 (begin1 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator1 crend1 () const { + return rend1 (); + } + + BOOST_UBLAS_INLINE + const_reverse_iterator2 rbegin2 () const { + return const_reverse_iterator2 (end2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crbegin2 () const { + return rbegin2 (); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 rend2 () const { + return const_reverse_iterator2 (begin2 ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator2 crend2 () const { + return rend2 (); + } + +private: + expression1_closure_type e1_; + expression2_closure_type e2_; +}; + +template +struct matrix_matrix_binary_traits { + typedef unknown_storage_tag storage_category; + typedef unknown_orientation_tag orientation_category; + typedef typename promote_traits::promote_type promote_type; + typedef matrix_matrix_binary > expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename E1::matrix_temporary_type result_type; -#endif - }; - - template - BOOST_UBLAS_INLINE - typename matrix_matrix_binary_traits::result_type - prod (const matrix_expression &e1, - const matrix_expression &e2, - unknown_storage_tag, - unknown_orientation_tag) { - typedef typename matrix_matrix_binary_traits::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_matrix_binary_traits::result_type - prod (const matrix_expression &e1, - const matrix_expression &e2) { - BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); - typedef typename matrix_matrix_binary_traits::storage_category storage_category; - typedef typename matrix_matrix_binary_traits::orientation_category orientation_category; - return prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const matrix_expression &e1, - const matrix_expression &e2, - unknown_storage_tag, - unknown_orientation_tag) { - typedef typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::expression_type expression_type; - return expression_type (e1 (), e2 ()); - } - - // Dispatcher - template - BOOST_UBLAS_INLINE - typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::result_type - prec_prod (const matrix_expression &e1, - const matrix_expression &e2) { - BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); - typedef typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::storage_category storage_category; - typedef typename matrix_matrix_binary_traits::precision_type, E1, - typename type_traits::precision_type, E2>::orientation_category orientation_category; - return prec_prod (e1, e2, storage_category (), orientation_category ()); - } - - template - BOOST_UBLAS_INLINE - M & - prod (const matrix_expression &e1, - const matrix_expression &e2, - M &m) { - return m.assign (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - M & - prec_prod (const matrix_expression &e1, - const matrix_expression &e2, - M &m) { - return m.assign (prec_prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - M - prod (const matrix_expression &e1, - const matrix_expression &e2) { - return M (prod (e1, e2)); - } - - template - BOOST_UBLAS_INLINE - M - prec_prod (const matrix_expression &e1, - const matrix_expression &e2) { - return M (prec_prod (e1, e2)); - } - - template - class matrix_scalar_unary: - public scalar_expression > { - public: - typedef E expression_type; - typedef F functor_type; - typedef typename F::result_type value_type; - typedef typename E::const_closure_type expression_closure_type; - - // Construction and destruction - BOOST_UBLAS_INLINE - explicit matrix_scalar_unary (const expression_type &e): - e_ (e) {} - - private: - // Expression accessors - BOOST_UBLAS_INLINE - const expression_closure_type &expression () const { - return e_; - } - - public: - BOOST_UBLAS_INLINE - operator value_type () const { - return functor_type::apply (e_); - } - - private: - expression_closure_type e_; - }; - - template - struct matrix_scalar_unary_traits { - typedef matrix_scalar_unary expression_type; + typedef typename E1::matrix_temporary_type result_type; +#endif +}; + +template +BOOST_UBLAS_INLINE +typename matrix_matrix_binary_traits::result_type +prod (const matrix_expression &e1, + const matrix_expression &e2, + unknown_storage_tag, + unknown_orientation_tag) { + typedef typename matrix_matrix_binary_traits::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_matrix_binary_traits::result_type +prod (const matrix_expression &e1, + const matrix_expression &e2) { + BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); + typedef typename matrix_matrix_binary_traits::storage_category storage_category; + typedef typename matrix_matrix_binary_traits::orientation_category orientation_category; + return prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +typename matrix_matrix_binary_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const matrix_expression &e1, + const matrix_expression &e2, + unknown_storage_tag, + unknown_orientation_tag) { + typedef typename matrix_matrix_binary_traits::precision_type, E1, + typename type_traits::precision_type, E2>::expression_type expression_type; + return expression_type (e1 (), e2 ()); +} + +// Dispatcher +template +BOOST_UBLAS_INLINE +typename matrix_matrix_binary_traits::precision_type, E1, +typename type_traits::precision_type, E2>::result_type +prec_prod (const matrix_expression &e1, + const matrix_expression &e2) { + BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0); + typedef typename matrix_matrix_binary_traits::precision_type, E1, + typename type_traits::precision_type, E2>::storage_category storage_category; + typedef typename matrix_matrix_binary_traits::precision_type, E1, + typename type_traits::precision_type, E2>::orientation_category orientation_category; + return prec_prod (e1, e2, storage_category (), orientation_category ()); +} + +template +BOOST_UBLAS_INLINE +M & +prod (const matrix_expression &e1, + const matrix_expression &e2, + M &m) { + return m.assign (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +M & +prec_prod (const matrix_expression &e1, + const matrix_expression &e2, + M &m) { + return m.assign (prec_prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +M +prod (const matrix_expression &e1, + const matrix_expression &e2) { + return M (prod (e1, e2)); +} + +template +BOOST_UBLAS_INLINE +M +prec_prod (const matrix_expression &e1, + const matrix_expression &e2) { + return M (prec_prod (e1, e2)); +} + +template +class matrix_scalar_unary: + public scalar_expression > { +public: + typedef E expression_type; + typedef F functor_type; + typedef typename F::result_type value_type; + typedef typename E::const_closure_type expression_closure_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + explicit matrix_scalar_unary (const expression_type &e): + e_ (e) {} + +private: + // Expression accessors + BOOST_UBLAS_INLINE + const expression_closure_type &expression () const { + return e_; + } + +public: + BOOST_UBLAS_INLINE + operator value_type () const { + return functor_type::apply (e_); + } + +private: + expression_closure_type e_; +}; + +template +struct matrix_scalar_unary_traits { + typedef matrix_scalar_unary expression_type; #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG - typedef expression_type result_type; + typedef expression_type result_type; #else - typedef typename F::result_type result_type; -#endif - }; - - template - BOOST_UBLAS_INLINE - typename matrix_scalar_unary_traits >::result_type - norm_1 (const matrix_expression &e) { - typedef typename matrix_scalar_unary_traits >::expression_type expression_type; - return expression_type (e ()); - } - - template - BOOST_UBLAS_INLINE - typename matrix_scalar_unary_traits >::result_type - norm_frobenius (const matrix_expression &e) { - typedef typename matrix_scalar_unary_traits >::expression_type expression_type; - return expression_type (e ()); - } - - template - BOOST_UBLAS_INLINE - typename matrix_scalar_unary_traits >::result_type - norm_inf (const matrix_expression &e) { - typedef typename matrix_scalar_unary_traits >::expression_type expression_type; - return expression_type (e ()); - } + typedef typename F::result_type result_type; +#endif +}; + +template +BOOST_UBLAS_INLINE +typename matrix_scalar_unary_traits >::result_type +norm_1 (const matrix_expression &e) { + typedef typename matrix_scalar_unary_traits >::expression_type expression_type; + return expression_type (e ()); +} + +template +BOOST_UBLAS_INLINE +typename matrix_scalar_unary_traits >::result_type +norm_frobenius (const matrix_expression &e) { + typedef typename matrix_scalar_unary_traits >::expression_type expression_type; + return expression_type (e ()); +} + +template +BOOST_UBLAS_INLINE +typename matrix_scalar_unary_traits >::result_type +norm_inf (const matrix_expression &e) { + typedef typename matrix_scalar_unary_traits >::expression_type expression_type; + return expression_type (e ()); +} }}} diff --git a/include/boost/numeric/ublas/matrix_sparse.hpp b/include/boost/numeric/ublas/matrix_sparse.hpp index d9677540d..9a70029fb 100644 --- a/include/boost/numeric/ublas/matrix_sparse.hpp +++ b/include/boost/numeric/ublas/matrix_sparse.hpp @@ -368,7 +368,7 @@ namespace boost { namespace numeric { namespace ublas { // Reserving BOOST_UBLAS_INLINE - void reserve (size_type non_zeros, bool preserve = true) { + void reserve (size_type non_zeros, bool /*preserve*/ = true) { detail::map_reserve (data (), restrict_capacity (non_zeros)); } diff --git a/include/boost/numeric/ublas/operation/begin.hpp b/include/boost/numeric/ublas/operation/begin.hpp index d14bb35ca..ea71349d6 100644 --- a/include/boost/numeric/ublas/operation/begin.hpp +++ b/include/boost/numeric/ublas/operation/begin.hpp @@ -28,289 +28,289 @@ namespace boost { namespace numeric { namespace ublas { namespace detail { - /** - * \brief Auxiliary class for implementing the \c begin operation. - * \tparam CategoryT The expression category type (e.g., vector_tag). - * \tparam TagT The dimension type tag (e.g., tag::major). - * \tparam OrientationT The orientation category type (e.g., row_major_tag). - */ - template - struct begin_impl; - - - /// \brief Specialization of \c begin_impl for iterating vector expressions. - template <> - struct begin_impl - { - /** - * \brief Return an iterator to the first element of the given vector - * expression. - * \tparam ExprT A model of VectorExpression type. - * \param e A vector expression. - * \return An iterator over the given vector expression. - */ - template - static typename ExprT::iterator apply(ExprT& e) - { - return e.begin(); - } - - - /** - * \brief Return a const iterator to the first element of the given vector - * expression. - * \tparam ExprT A model of VectorExpression type. - * \param e A vector expression. - * \return A const iterator to the first element of the given vector - * expression. - */ - template - static typename ExprT::const_iterator apply(ExprT const& e) - { - return e.begin(); - } - }; - - - /// \brief Specialization of \c begin_impl for iterating matrix expressions with - /// a row-major orientation over the major dimension. - template <> - struct begin_impl - { - /** - * \brief Return an iterator to the first element of the given row-major - * matrix expression over the major dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return An iterator over the major dimension of the given matrix - * expression. - */ - template - static typename ExprT::iterator1 apply(ExprT& e) - { - return e.begin1(); - } - - - /** - * \brief Return a const iterator to the first element of the given - * row-major matrix expression over the major dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return A const iterator over the major dimension of the given matrix - * expression. - */ - template - static typename ExprT::const_iterator1 apply(ExprT const& e) - { - return e.begin1(); - } - }; - - - /// \brief Specialization of \c begin_impl for iterating matrix expressions with - /// a column-major orientation over the major dimension. - template <> - struct begin_impl - { - /** - * \brief Return an iterator to the first element of the given column-major - * matrix expression over the major dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return An iterator over the major dimension of the given matrix - * expression. - */ - template - static typename ExprT::iterator2 apply(ExprT& e) - { - return e.begin2(); - } - - - /** - * \brief Return a const iterator to the first element of the given - * column-major matrix expression over the major dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return A const iterator over the major dimension of the given matrix - * expression. - */ - template - static typename ExprT::const_iterator2 apply(ExprT const& e) - { - return e.begin2(); - } - }; - - - /// \brief Specialization of \c begin_impl for iterating matrix expressions with - /// a row-major orientation over the minor dimension. - template <> - struct begin_impl - { - /** - * \brief Return an iterator to the first element of the given row-major - * matrix expression over the minor dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return An iterator over the minor dimension of the given matrix - * expression. - */ - template - static typename ExprT::iterator2 apply(ExprT& e) - { - return e.begin2(); - } - - - /** - * \brief Return a const iterator to the first element of the given - * row-major matrix expression over the minor dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return A const iterator over the minor dimension of the given matrix - * expression. - */ - template - static typename ExprT::const_iterator2 apply(ExprT const& e) - { - return e.begin2(); - } - }; - - - - /// \brief Specialization of \c begin_impl for iterating matrix expressions with - /// a column-major orientation over the minor dimension. - template <> - struct begin_impl - { - /** - * \brief Return an iterator to the first element of the given column-major - * matrix expression over the minor dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return An iterator over the minor dimension of the given matrix - * expression. - */ - template - static typename ExprT::iterator1 apply(ExprT& e) - { - return e.begin1(); - } - - - /** - * \brief Return a const iterator to the first element of the given - * column-major matrix expression over the minor dimension. - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return A const iterator over the minor dimension of the given matrix - * expression. - */ - template - static typename ExprT::const_iterator1 apply(ExprT const& e) - { - return e.begin1(); - } - }; - - } // Namespace detail - - - /** - * \brief An iterator to the first element of the given vector expression. - * \tparam ExprT A model of VectorExpression type. - * \param e A vector expression. - * \return An iterator to the first element of the given vector expression. - */ - template - BOOST_UBLAS_INLINE - typename ExprT::iterator begin(vector_expression& e) - { - return detail::begin_impl::apply(e()); - } - - - /** - * \brief A const iterator to the first element of the given vector expression. - * \tparam ExprT A model of VectorExpression type. - * \param e A vector expression. - * \return A const iterator to the first element of the given vector expression. - */ - template - BOOST_UBLAS_INLINE - typename ExprT::const_iterator begin(vector_expression const& e) - { - return detail::begin_impl::apply(e()); - } - - - /** - * \brief An iterator to the first element of the given matrix expression - * according to its orientation. - * \tparam DimTagT A dimension tag type (e.g., tag::major). - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return An iterator to the first element of the given matrix expression - * according to its orientation. - */ - template - BOOST_UBLAS_INLINE - typename iterator_type::type begin(matrix_expression& e) - { - return detail::begin_impl::apply(e()); - } - - - /** - * \brief A const iterator to the first element of the given matrix expression - * according to its orientation. - * \tparam TagT A dimension tag type (e.g., tag::major). - * \tparam ExprT A model of MatrixExpression type. - * \param e A matrix expression. - * \return A const iterator to the first element of the given matrix expression - * according to its orientation. - */ - template - BOOST_UBLAS_INLINE - typename const_iterator_type::type begin(matrix_expression const& e) - { - return detail::begin_impl::apply(e()); - } - - - /** - * \brief An iterator to the first element over the dual dimension of the given - * iterator. - * \tparam IteratorT A model of Iterator type. - * \param it An iterator. - * \return An iterator to the first element over the dual dimension of the given - * iterator. - */ - template - BOOST_UBLAS_INLINE - typename IteratorT::dual_iterator_type begin(IteratorT& it) - { - return it.begin(); - } - - - /** - * \brief A const iterator to the first element over the dual dimension of the - * given iterator. - * \tparam IteratorT A model of Iterator type. - * \param it An iterator. - * \return A const iterator to the first element over the dual dimension of the - * given iterator. - */ - template - BOOST_UBLAS_INLINE - typename IteratorT::dual_iterator_type begin(IteratorT const& it) - { - return it.begin(); - } + /** + * \brief Auxiliary class for implementing the \c begin operation. + * \tparam CategoryT The expression category type (e.g., vector_tag). + * \tparam TagT The dimension type tag (e.g., tag::major). + * \tparam OrientationT The orientation category type (e.g., row_major_tag). + */ + template + struct begin_impl; + + + /// \brief Specialization of \c begin_impl for iterating vector expressions. + template <> + struct begin_impl + { + /** + * \brief Return an iterator to the first element of the given vector + * expression. + * \tparam ExprT A model of VectorExpression type. + * \param e A vector expression. + * \return An iterator over the given vector expression. + */ + template + static typename ExprT::iterator apply(ExprT& e) + { + return e.begin(); + } + + + /** + * \brief Return a const iterator to the first element of the given vector + * expression. + * \tparam ExprT A model of VectorExpression type. + * \param e A vector expression. + * \return A const iterator to the first element of the given vector + * expression. + */ + template + static typename ExprT::const_iterator apply(ExprT const& e) + { + return e.begin(); + } + }; + + + /// \brief Specialization of \c begin_impl for iterating matrix expressions with + /// a row-major orientation over the major dimension. + template <> + struct begin_impl + { + /** + * \brief Return an iterator to the first element of the given row-major + * matrix expression over the major dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return An iterator over the major dimension of the given matrix + * expression. + */ + template + static typename ExprT::iterator1 apply(ExprT& e) + { + return e.begin1(); + } + + + /** + * \brief Return a const iterator to the first element of the given + * row-major matrix expression over the major dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return A const iterator over the major dimension of the given matrix + * expression. + */ + template + static typename ExprT::const_iterator1 apply(ExprT const& e) + { + return e.begin1(); + } + }; + + + /// \brief Specialization of \c begin_impl for iterating matrix expressions with + /// a column-major orientation over the major dimension. + template <> + struct begin_impl + { + /** + * \brief Return an iterator to the first element of the given column-major + * matrix expression over the major dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return An iterator over the major dimension of the given matrix + * expression. + */ + template + static typename ExprT::iterator2 apply(ExprT& e) + { + return e.begin2(); + } + + + /** + * \brief Return a const iterator to the first element of the given + * column-major matrix expression over the major dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return A const iterator over the major dimension of the given matrix + * expression. + */ + template + static typename ExprT::const_iterator2 apply(ExprT const& e) + { + return e.begin2(); + } + }; + + + /// \brief Specialization of \c begin_impl for iterating matrix expressions with + /// a row-major orientation over the minor dimension. + template <> + struct begin_impl + { + /** + * \brief Return an iterator to the first element of the given row-major + * matrix expression over the minor dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return An iterator over the minor dimension of the given matrix + * expression. + */ + template + static typename ExprT::iterator2 apply(ExprT& e) + { + return e.begin2(); + } + + + /** + * \brief Return a const iterator to the first element of the given + * row-major matrix expression over the minor dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return A const iterator over the minor dimension of the given matrix + * expression. + */ + template + static typename ExprT::const_iterator2 apply(ExprT const& e) + { + return e.begin2(); + } + }; + + + + /// \brief Specialization of \c begin_impl for iterating matrix expressions with + /// a column-major orientation over the minor dimension. + template <> + struct begin_impl + { + /** + * \brief Return an iterator to the first element of the given column-major + * matrix expression over the minor dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return An iterator over the minor dimension of the given matrix + * expression. + */ + template + static typename ExprT::iterator1 apply(ExprT& e) + { + return e.begin1(); + } + + + /** + * \brief Return a const iterator to the first element of the given + * column-major matrix expression over the minor dimension. + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return A const iterator over the minor dimension of the given matrix + * expression. + */ + template + static typename ExprT::const_iterator1 apply(ExprT const& e) + { + return e.begin1(); + } + }; + + } // Namespace detail + + + /** + * \brief An iterator to the first element of the given vector expression. + * \tparam ExprT A model of VectorExpression type. + * \param e A vector expression. + * \return An iterator to the first element of the given vector expression. + */ + template + BOOST_UBLAS_INLINE + typename ExprT::iterator begin(vector_expression& e) + { + return detail::begin_impl::apply(e()); + } + + + /** + * \brief A const iterator to the first element of the given vector expression. + * \tparam ExprT A model of VectorExpression type. + * \param e A vector expression. + * \return A const iterator to the first element of the given vector expression. + */ + template + BOOST_UBLAS_INLINE + typename ExprT::const_iterator begin(vector_expression const& e) + { + return detail::begin_impl::apply(e()); + } + + + /** + * \brief An iterator to the first element of the given matrix expression + * according to its orientation. + * \tparam DimTagT A dimension tag type (e.g., tag::major). + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return An iterator to the first element of the given matrix expression + * according to its orientation. + */ + template + BOOST_UBLAS_INLINE + typename iterator_type::type begin(matrix_expression& e) + { + return detail::begin_impl::apply(e()); + } + + + /** + * \brief A const iterator to the first element of the given matrix expression + * according to its orientation. + * \tparam TagT A dimension tag type (e.g., tag::major). + * \tparam ExprT A model of MatrixExpression type. + * \param e A matrix expression. + * \return A const iterator to the first element of the given matrix expression + * according to its orientation. + */ + template + BOOST_UBLAS_INLINE + typename const_iterator_type::type begin(matrix_expression const& e) + { + return detail::begin_impl::apply(e()); + } + + + /** + * \brief An iterator to the first element over the dual dimension of the given + * iterator. + * \tparam IteratorT A model of Iterator type. + * \param it An iterator. + * \return An iterator to the first element over the dual dimension of the given + * iterator. + */ + template + BOOST_UBLAS_INLINE + typename IteratorT::dual_iterator_type begin(IteratorT& it) + { + return it.begin(); + } + + + /** + * \brief A const iterator to the first element over the dual dimension of the + * given iterator. + * \tparam IteratorT A model of Iterator type. + * \param it An iterator. + * \return A const iterator to the first element over the dual dimension of the + * given iterator. + */ + template + BOOST_UBLAS_INLINE + typename IteratorT::dual_iterator_type begin(IteratorT const& it) + { + return it.begin(); + } }}} // Namespace boost::numeric::ublas diff --git a/include/boost/numeric/ublas/storage_sparse.hpp b/include/boost/numeric/ublas/storage_sparse.hpp index 641a22d53..f87685c79 100644 --- a/include/boost/numeric/ublas/storage_sparse.hpp +++ b/include/boost/numeric/ublas/storage_sparse.hpp @@ -397,7 +397,7 @@ namespace boost { namespace numeric { namespace ublas { } // Form Sorted Associative Container concept // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. - iterator insert (iterator hint, const value_type &p) { + iterator insert (iterator /*hint*/, const value_type &p) { return insert (p).first; } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. diff --git a/include/boost/numeric/ublas/tensor.hpp b/include/boost/numeric/ublas/tensor.hpp index d3d38cf77..5a72d43bb 100644 --- a/include/boost/numeric/ublas/tensor.hpp +++ b/include/boost/numeric/ublas/tensor.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 +// Copyright (c) 2018-2019 // Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See @@ -12,10 +12,8 @@ /// \file tensor.hpp Definition for the class vector and its derivative -#ifndef BOOST_NUMERIC_UBLAS_TENSOR -#define BOOST_NUMERIC_UBLAS_TENSOR - -#if __cplusplus >= 201703L +#ifndef BOOST_NUMERIC_UBLAS_TENSOR_HPP +#define BOOST_NUMERIC_UBLAS_TENSOR_HPP #include "tensor/functions.hpp" #include "tensor/operators_arithmetic.hpp" @@ -25,6 +23,4 @@ #include "tensor/ostream.hpp" #include "tensor/tensor.hpp" -#endif - -#endif +#endif // BOOST_NUMERIC_UBLAS_TENSOR_HPP diff --git a/include/boost/numeric/ublas/tensor/algorithm.hpp b/include/boost/numeric/ublas/tensor/algorithm.hpp deleted file mode 100644 index 8eea14135..000000000 --- a/include/boost/numeric/ublas/tensor/algorithm.hpp +++ /dev/null @@ -1,680 +0,0 @@ -// -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany -// - - - -#ifndef _BOOST_UBLAS_TENSOR_ALGORITHM_ -#define _BOOST_UBLAS_TENSOR_ALGORITHM_ - -#include - -namespace boost { namespace numeric { namespace ublas { -struct first_order; -}}} - - -namespace boost { namespace numeric { namespace ublas { namespace detail { - -template -struct recursion -{ - static constexpr bool is_first_order = std::is_same_v; - - static constexpr inline auto cmpr(const std::size_t r, const std::size_t p) - { - if constexpr (is_first_order) return r > 0; - else return r < p; - } - - - static constexpr inline auto nextr(const std::size_t r) - { - if constexpr (is_first_order) return r - 1; - else return r + 1; - } - - static constexpr inline auto lastr(const std::size_t p) - { - if constexpr (is_first_order) return 0; - else return p-1; - } - - - template - static void run (const std::size_t p, - const std::size_t r, - const size_type *const n, - const size_type *const wa, - const size_type *const wc, - const value_type* a, - value_type *c, - unary_op op) - { - if(cmpr(r,p)) - for(auto i = 0ul; i < n[r]; ++i, a+=wa[r], c+=wc[r] ) - run(p, nextr(r), n, wa, wc, a, c, op); - else - for(auto i = 0ul; i < n[0]; ++i, ++a, ++c ) - op(*c,*a); - } -}; - -}}}} - - - -namespace boost { namespace numeric { namespace ublas { - -template -void copy(size_type const p, - size_type const*const n, - size_type const*const wa, - size_type const*const wc, - value_type const* a, - value_type * c, - layout_type l = layout_type() ) -{ - detail::recursion::run( p, p-1, n, wa, wc, a, c, [](value_type& c, value_type const& a){c = a;}); -} - -}}} - - - - - - -template -void -ttm_recursion_notzero( - const size_t m, size_t r, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - - if(r == m) { - ttm_recursion_notzero(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); - } - - - else if(r == 0){ - for(size_t i0 = 0u; i0 < nc[0]; c += wc[0], a += wa[0], ++i0) { - - auto cm = c; - auto b0 = b; - - // r == m - for(size_t i0 = 0u; i0 < nc[m]; cm += wc[m], b0 += wb[0], ++i0){ - - auto am = a; - auto b1 = b0; - - for(size_t i1 = 0u; i1 < nb[1]; am += wa[m], b1 += wb[1], ++i1){ - *cm += *am * *b1; - } - } - } - } - - else{ - for(size_t i = 0u; i < na[r]; c += wc[r], a += wa[r], ++i) - ttm_recursion_notzero(m, r-1, c, nc, wc, a, na, wa, b, nb, wb); - } -} - - - - - - - - -template -void -ttm_recursion_zero( - size_t r, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - - if(r > 1){ - for(size_t i = 0u; i < na[r]; c += wc[r], a += wa[r], ++i) - ttm_recursion_zero(r-1, c, nc, wc, a, na, wa, b, nb, wb); - } - else{ - for(size_t i1 = 0u; i1 < nc[1]; c += wc[1], a += wa[1], ++i1) { - auto cm = c; - auto b0 = b; - // r == m == 0 - for(size_t i0 = 0u; i0 < nc[0]; cm += wc[0], b0 += wb[0], ++i0){ - - auto am = a; - auto b1 = b0; - for(size_t i1 = 0u; i1 < nb[1]; am += wa[0], b1 += wb[1], ++i1){ - - *cm += *am * *b1; - } - } - } - } -} - - -template -typename std::remove_cv::type>::type -inner_recursive( const size_t r, const size_t* n, pointer_t_a a, const size_t* wa, pointer_t_b b, const size_t* wb) -{ - using value_t = typename std::remove_cv::type>::type; - using value_t_b = typename std::remove_cv::type>::type; - static_assert(std::is_same::value, "static assert in inner_recursive: both pointer types must point to the same type."); - - value_t sum = value_t(); - - if(r == 0){ - for(size_t i0 = 0u; i0 < n[0]; a += wa[0], b += wb[0], ++i0) - sum += *a * *b; - } - else{ - for(size_t ir = 0u; ir < n[r]; a += wa[r], b += wb[r], ++ir) - sum += inner_recursive(r-1, n, a, wa, b, wb); - } - return sum; -} - - -template -void -outer_2x2( - size_t const pa, - size_t const rc, pointer_t_c c, const size_t* , const size_t* wc, - size_t const ra, pointer_t_a a, const size_t* na, const size_t* wa, - size_t const rb, pointer_t_b b, const size_t* nb, const size_t* wb) -{ - assert(rc == 3); - assert(ra == 1); - assert(rb == 1); - - for(size_t ib1 = 0u; ib1 < nb[1]; b += wb[1], c += wc[pa+1], ++ib1) - { - auto c2 = c; - auto b0 = b; - for(size_t ib0 = 0u; ib0 < nb[0]; b0 += wb[0], c2 += wc[pa], ++ib0) - { - const auto b = *b0; - auto c1 = c2; - auto a1 = a; - for(size_t ia1 = 0u; ia1 < na[1]; a1 += wa[1], c1 += wc[1], ++ia1) - { - auto a0 = a1; - auto c0 = c1; - for(size_t ia0 = 0u; ia0 < na[0]; a0 += wa[0], c0 += wc[0], ++ia0){ - *c0 = *a0 * b; - } - } - } - } -} - -template -void -outer_recursion( - size_t const pa, - size_t const rc, pointer_t_c c, const size_t* nc, const size_t* wc, - size_t const ra, pointer_t_a a, const size_t* na, const size_t* wa, - size_t const rb, pointer_t_b b, const size_t* nb, const size_t* wb) -{ - if(rb > 1) // ra > 1 && - { - for(size_t ib = 0u; ib < nb[rb]; b += wb[rb], c += wc[rc], ++ib) - outer_recursion(pa, rc-1, c, nc, wc, ra, a, na, wa, rb-1, b, nb, wb); - } - else if(ra > 1) // && rb == 1 - { - for(size_t ia = 0u; ia < na[ra]; a += wa[ra], c += wc[ra], ++ia) - outer_recursion(pa, rc-1, c, nc, wc, ra-1, a, na, wa, rb, b, nb, wb); - } - else - { - assert(ra == 1 && rb == 1 && rc == 3); - outer_2x2(pa, rc, c, nc, wc, ra, a, na, wa, rb, b, nb, wb); - } -} - - -template -void -ttt_recursion( - size_t k, size_t const ar, size_t br, size_t const m, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - if(k < ar) - { - assert(nc[k] == na[k]); - for(size_t ic = 0u; ic < nc[k]; a += wa[k], c += wc[k], ++ic) - ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); - } - else if(k < ar+br) - { - assert(nc[k] == nb[k-ar]); - for(size_t ic = 0u; ic < nc[k]; b += wb[k-ar], c += wc[k], ++ic) - ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); - } - else if(k < ar+br+m-1) - { - assert(na[k-br] == nb[k-ar]); - for(size_t ia = 0u; ia < na[k-br]; a += wa[k-br], b += wb[k-ar], ++ia) - ttt_recursion(k+1, ar, br, m, c, nc, wc, a, na, wa, b, nb, wb); - } - else - { - assert(na[k-br] == nb[k-ar]); - for(size_t ia = 0u; ia < na[k-br]; a += wa[k-br], b += wb[k-ar], ++ia) - *c += *a * *b; - } -} - - -} // namespace detail -} // namespace ublas -} // namespace numeric -} // namespace boost - - -namespace boost { -namespace numeric { -namespace ublas { - -/* -template -void -transpose(size_t p, const size_t* tau, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa) -{ - if(c == nullptr || a == nullptr) - throw std::length_error("Error in fhg::transpose(...) : data pointers shall not be null pointers."); - - if(nc == nullptr || na == nullptr) - throw std::length_error("Error in fhg::transpose(...) : extent pointers shall not be null pointers."); - - if(wc == nullptr || wa == nullptr) - throw std::length_error("Error in fhg::transpose(...) : stride pointers shall not be null pointers."); - - if(tau == nullptr) - throw std::length_error("Error in fhg::transpose(...) : transpose permutation pointer shall not be a null pointer."); - - if(p < 2) - throw std::length_error("Error in fhg::transpose(...) : rank cannot be less than 2."); - - - // compute extents of C - for(size_t i = 0u; i < p; ++i) - if( nc[i] != na[tau[i]-1] ) - throw std::length_error("Error in fhg::transpose(...) : extents of left and right hand side tensor do not match."); - - size_t* vc = new size_t[p]; - for(size_t i = 0u; i < p; ++i) - vc[tau[i]-1] = wc[i]; - - if( std::equal(vc, vc+p, wa) ){ - const size_t nna = std::accumulate(na, na+p, 1ul, std::multiplies()); - std::copy(a,a+nna,c); - } - else{ - ::fhg::copy_pointer(p, na, c, vc, a, wa); - } - - - delete[] vc; -} -*/ - - - -/* -template -void -transpose(size_t p, const size_t* tau, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa) -{ - if(c == nullptr || a == nullptr) - throw std::length_error("Error in fhg::transpose(...) : data pointers shall not be null pointers."); - - if(nc == nullptr || na == nullptr) - throw std::length_error("Error in fhg::transpose(...) : extent pointers shall not be null pointers."); - - if(wc == nullptr || wa == nullptr) - throw std::length_error("Error in fhg::transpose(...) : stride pointers shall not be null pointers."); - - if(tau == nullptr) - throw std::length_error("Error in fhg::transpose(...) : transpose permutation pointer shall not be a null pointer."); - - if(p < 2) - throw std::length_error("Error in fhg::transpose(...) : rank cannot be less than 2."); - - - // compute extents of C - for(size_t i = 0u; i < p; ++i) - if( nc[i] != na[tau[i]-1] ) - throw std::length_error("Error in fhg::transpose(...) : extents of left and right hand side tensor do not match."); - - size_t* vc = new size_t[p]; - for(size_t i = 0u; i < p; ++i) - vc[tau[i]-1] = wc[i]; - - if( std::equal(vc, vc+p, wa) ){ - const size_t nna = std::accumulate(na, na+p, 1ul, std::multiplies()); - std::copy(a,a+nna,c); - } - else{ - ::fhg::copy_pointer(p, na, c, vc, a, wa); - } - - - delete[] vc; -} -*/ - - -template -void -tensor_times_vector(size_t m, size_t p, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* /*wb*/) -{ - - if( p < m ) - throw std::length_error("pointer_t_cError in tensor times vector function. Rank must be greater equal the modus."); - - if( p == 0) - throw std::length_error("Error intensor times vector function. Rank must be greater than zero."); - - if(c == nullptr || a == nullptr || b == nullptr) - throw std::length_error("Error in tensor times vector function. Pointers shall not be null pointers."); - - for(size_t i = 0; i < m-1; ++i){ - if(na[i] != nc[i]) - throw std::length_error("Error in tensor times vector function. Extents (except of dimension mode) of A and C must be equal."); - } - - for(size_t i = m; i < p; ++i){ - if(na[i] != nc[i-1]) - throw std::length_error("Error in tensor times vector function. Extents (except of dimension mode) of A and C must be equal."); - } - - const auto max = std::max(nb[0], nb[1]); - if( na[m-1] != max) - throw std::length_error("Error in tensor times vector function. Extent of dimension mode of A and b must be equal."); - - - if((m != 1) && (p > 2)) - detail::ttv_recursion_notzero(m-1, p-1, p-2, c, nc, wc, a, na, wa, b); - else if ((m == 1) && (p > 2)) - detail::ttv_recursion_zero(p-1, c, nc, wc, a, na, wa, b); - else - detail::mtv(m-1, c, nc, wc, a, na, wa, b); - -} - -template -void -tensor_times_matrix(const size_t m, const size_t p, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, const size_t* taua, - pointer_t_b b, const size_t* nb, const size_t* wb, const size_t* taub) -{ - if( p < m ) - throw std::length_error("Error in tensor times matrix function. Rank must be greater equal the modus."); - - if( p == 0) - throw std::length_error("Error in tensor times matrix function. Rank must be greater than zero."); - - if(c == nullptr || a == nullptr || b == nullptr) - throw std::length_error("Error in tensor times matrix function. Pointers shall not be null pointers."); - - for(size_t i = 0; i < m-1; ++i){ - if(na[taua[i]-1] != nc[i]) - throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); - } - - for(size_t i = m; i < p; ++i){ - if(na[taua[i]-1] != nc[i]) - throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); - } - - if(na[taua[m-1]-1] != nb[taub[1]-1]) - throw std::length_error("Error in tensor times matrix function. 2nd Extent of B and M-th Extent of A must be the equal."); - - if(nc[m-1] != nb[taub[0]-1]) - throw std::length_error("Error in tensor times matrix function. 1nd Extent of B and M-th Extent of C must be the equal."); - - - // need to compute the inverse of the transposition tuple tau - size_t* taua_1 = new size_t[p]; - size_t* taub_1 = new size_t[2]; - for(auto i = 0u; i < p; ++i){ - taua_1[taua[i]-1] = i+1; - } - for(auto i = 0u; i < 2; ++i){ - taub_1[taub[i]-1] = i+1; - } - - //compute v_a from w_a directly - size_t* va = new size_t[p]; - size_t* vb = new size_t[2]; -// size_t va[p], vb[2]; - for(size_t i = 0u; i < p; ++i){ - va[taua_1[i]-1] = wa[i]; - } - for(size_t i = 0u; i < 2; ++i){ - vb[taub_1[i]-1] = wb[i]; - } - - delete[] taua_1; - delete[] taub_1; - - if(m != 1) { - detail::ttm_recursion_notzero(m-1, p-1, c, nc, wc, a, na, va, b, nb, vb); - } - else { - detail::ttm_recursion_zero(p-1, c, nc, wc, a, na, va, b, nb, vb); - } - - delete[] va; - delete[] vb; -} - - - - -template -void -tensor_times_matrix(const size_t m, const size_t p, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - - static_assert( (std::is_pointer::value && std::is_pointer::value) && std::is_pointer::value, - "Static error at tensor_times_matrix function: argument types for pointers must be pointer types."); - - if( p < m ) - throw std::length_error("Error in tensor times matrix function. Rank must be greater equal the modus."); - - if( p == 0) - throw std::length_error("Error in tensor times matrix function. Rank must be greater than zero."); - - if(c == nullptr || a == nullptr || b == nullptr) - throw std::length_error("Error in tensor times matrix function. Pointers shall not be null pointers."); - - for(size_t i = 0; i < m-1; ++i){ - if(na[i] != nc[i]) - throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); - } - - for(size_t i = m; i < p; ++i){ - if(na[i] != nc[i]) - throw std::length_error("Error in tensor times matrix function. Extents (except of dimension mode) of A and C must be equal."); - } - - if(na[m-1] != nb[1]) - throw std::length_error("Error in tensor times matrix function. 2nd Extent of B and M-th Extent of A must be the equal."); - - if(nc[m-1] != nb[0]) - throw std::length_error("Error in tensor times matrix function. 1nd Extent of B and M-th Extent of C must be the equal."); - - if(m != 1) - detail::ttm_recursion_notzero(m-1, p-1, c, nc, wc, a, na, wa, b, nb, wb); - else - detail::ttm_recursion_zero(p-1, c, nc, wc, a, na, wa, b, nb, wb); - -} - - - - - -template -typename std::remove_cv::type>::type -inner(const size_t p, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* /*nb*/, const size_t* wb) -{ - static_assert( std::is_pointer::value && std::is_pointer::value, - "Static error at inner function: argument types for pointers must be pointer types."); - - if(p<2) - throw std::length_error("Error when performing inner product: Rank must be greater than zero."); - - if(a == nullptr || b == nullptr) - throw std::length_error("Error when performing inner product: Pointers shall not be null pointers."); - - return detail::inner_recursive(p-1, na, a, wa, b, wb); - -} - - - - -template -void -outer(size_t pc, size_t pa, size_t pb, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - - if(pa < 2 || pb < 2) - throw std::length_error("Error when performing outer product: number of extents of A and B must be equal or greater than two."); - - if((pa + pb) != pc) - throw std::length_error("Error when performing outer product: number of extents of A plus B must be equal to the number of extents of C."); - - if(a == nullptr || b == nullptr || c == nullptr) - { - throw std::length_error("Error when performing outer product: Pointers shall not be null pointers."); - } - - - detail::outer_recursion(pa, pc-1, c, nc, wc, pa-1, a, na, wa, pb-1, b, nb, wb); - -} - - -template -void -tensor_times_tensor( - const size_t pc, const size_t pa, const size_t pb, - const size_t m, const size_t ar, const size_t br, - const size_t* phia, const size_t* phib, - pointer_t_c c, const size_t* nc, const size_t* wc, - pointer_t_a a, const size_t* na, const size_t* wa, - pointer_t_b b, const size_t* nb, const size_t* wb) -{ - -// const auto pc = nc.size(); -// const auto pa = na.size(); -// const auto pb = nb.size(); - - if(pa < 2 || pb < 2 || pc < 2) - throw std::length_error("Error when performing tensor tensor product: number of extents of A, B and C must be equal or greater than two."); - -// if(ar+m != phia.size()) -// throw std::length_error("Error when performing tensor tensor product: length of permutation tuple of A must be equal to r + m."); - -// if(ar+m != na.size()) -// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of A must be equal to r + m."); - -// if(ar+m != wa.size()) -// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of A must be equal to r + m."); - -// if(br+m != phib.size()) -// throw std::length_error("Error when performing tensor tensor product: length of permutation tuple of B must be equal to s + m."); - -// if(br+m != nb.size()) -// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of B must be equal to s + m."); - -// if(br+m != wb.size()) -// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of B must be equal to s + m."); - -// if(ar+br != nc.size() && ar!=0 && br!=0) -// throw std::length_error("Error when performing tensor tensor product: length of extent tuple of C must be equal to r + s."); - -// if(ar+br != wc.size() && ar!=0 && br!=0) -// throw std::length_error("Error when performing tensor tensor product: length of stride tuple of C must be equal to r + s."); - - if(a == nullptr || b == nullptr || c == nullptr) - {throw std::length_error("Error when performing tensor tensor product: Pointers shall not be null pointers.");} - - size_t* na_ = new size_t[pa]; - size_t* nb_ = new size_t[pb]; - size_t* wa_ = new size_t[pa]; - size_t* wb_ = new size_t[pb]; -// size_t na_[pa], nb_[pb]; -// size_t wa_[pa], wb_[pb]; - - for(size_t k = 0; k < ar; ++k){ - na_[k] = na[phia[k]-1]; - wa_[k] = wa[phia[k]-1]; - } - - for(size_t k = 0; k < br; ++k){ - nb_[k] = nb[phib[k]-1]; - wb_[k] = wb[phib[k]-1]; - } - - for(size_t k = 0; k < m; ++k){ - na_[k+ar] = na[phia[k+ar]-1]; - wa_[k+ar] = wa[phia[k+ar]-1]; - nb_[k+br] = nb[phib[k+br]-1]; - wb_[k+br] = wb[phib[k+br]-1]; - } - - detail::ttt_recursion(0, ar, br, m, c, nc, wc, a, na_, wa_, b, nb_, wb_); - - delete[] na_; - delete[] nb_; - delete[] wa_; - delete[] wb_; - -} - - - - - -#endif diff --git a/include/boost/numeric/ublas/tensor/algorithms.hpp b/include/boost/numeric/ublas/tensor/algorithms.hpp index 1b4fcb04e..c6b9dba48 100644 --- a/include/boost/numeric/ublas/tensor/algorithms.hpp +++ b/include/boost/numeric/ublas/tensor/algorithms.hpp @@ -1,17 +1,17 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_ALGORITHMS_ -#define _BOOST_UBLAS_TENSOR_ALGORITHMS_ +#ifndef _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP +#define _BOOST_UBLAS_TENSOR_ALGORITHMS_HPP #include @@ -38,11 +38,11 @@ namespace ublas { */ template void copy(const SizeType p, SizeType const*const n, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa) + PointerOut c, SizeType const*const wc, + PointerIn a, SizeType const*const wa) { static_assert( std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::copy: Argument types for pointers are not pointer types."); if( p == 0 ) return; @@ -88,13 +88,13 @@ void copy(const SizeType p, SizeType const*const n, */ template void transform(const SizeType p, - SizeType const*const n, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa, - UnaryOp op) + SizeType const*const n, + PointerOut c, SizeType const*const wc, + PointerIn a, SizeType const*const wa, + UnaryOp op) { static_assert( std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) return; @@ -137,11 +137,11 @@ void transform(const SizeType p, */ template ValueType accumulate(SizeType const p, SizeType const*const n, - PointerIn a, SizeType const*const w, - ValueType k) + PointerIn a, SizeType const*const w, + ValueType k) { static_assert(std::is_pointer::value, - "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) return k; @@ -186,11 +186,11 @@ ValueType accumulate(SizeType const p, SizeType const*const n, template ValueType accumulate(SizeType const p, SizeType const*const n, - PointerIn a, SizeType const*const w, - ValueType k, BinaryOp op) + PointerIn a, SizeType const*const w, + ValueType k, BinaryOp op) { static_assert(std::is_pointer::value, - "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::transform: Argument types for pointers are not pointer types."); if( p == 0 ) @@ -239,12 +239,12 @@ ValueType accumulate(SizeType const p, SizeType const*const n, template void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, - PointerOut c, SizeType const*const wc, - PointerIn a, SizeType const*const wa) + PointerOut c, SizeType const*const wc, + PointerIn a, SizeType const*const wa) { static_assert( std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::trans: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::trans: Argument types for pointers are not pointer types."); if( p < 2) return; @@ -298,10 +298,10 @@ void trans( SizeType const p, SizeType const*const na, SizeType const*const pi, template void trans( SizeType const p, - SizeType const*const na, - SizeType const*const pi, - std::complex* c, SizeType const*const wc, - std::complex* a, SizeType const*const wa) + SizeType const*const na, + SizeType const*const pi, + std::complex* c, SizeType const*const wc, + std::complex* a, SizeType const*const wa) { if( p < 2) return; diff --git a/include/boost/numeric/ublas/tensor/expression.hpp b/include/boost/numeric/ublas/tensor/expression.hpp index fd77f989a..2677a0e6f 100644 --- a/include/boost/numeric/ublas/tensor/expression.hpp +++ b/include/boost/numeric/ublas/tensor/expression.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_EXPRESSIONS_ -#define _BOOST_UBLAS_TENSOR_EXPRESSIONS_ +#ifndef BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP +#define BOOST_UBLAS_TENSOR_EXPRESSIONS_HPP #include #include @@ -50,9 +50,9 @@ namespace detail { **/ template struct tensor_expression - : public ublas_expression + : public ublas_expression { -// static const unsigned complexity = 0; + // static const unsigned complexity = 0; using expression_type = E; using type_category = tensor_tag; using tensor_type = T; @@ -69,7 +69,7 @@ protected : template struct binary_tensor_expression - : public tensor_expression > + : public tensor_expression > { using self_type = binary_tensor_expression; using tensor_type = T; @@ -81,11 +81,11 @@ struct binary_tensor_expression using size_type = typename tensor_type::size_type; explicit binary_tensor_expression(expression_type_left const& l, expression_type_right const& r, binary_operation o) - : el(l) , er(r) , op(o) {} + : el(l) , er(r) , op(o) {} binary_tensor_expression() = delete; binary_tensor_expression(const binary_tensor_expression& l) = delete; binary_tensor_expression(binary_tensor_expression&& l) - : el(l.el), er(l.er), op(l.op) {} + : el(l.el), er(l.er), op(l.op) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(el(i), er(i)); } @@ -130,7 +130,7 @@ auto make_binary_tensor_expression( tensor_expression const& el, vector_ex template struct unary_tensor_expression - : public tensor_expression > + : public tensor_expression > { using self_type = unary_tensor_expression; @@ -145,7 +145,7 @@ struct unary_tensor_expression unary_tensor_expression() = delete; unary_tensor_expression(const unary_tensor_expression& l) = delete; unary_tensor_expression(unary_tensor_expression&& l) - : e(l.e), op(op.l) {} + : e(l.e), op(op.l) {} BOOST_UBLAS_INLINE decltype(auto) operator()(size_type i) const { return op(e(i)); } diff --git a/include/boost/numeric/ublas/tensor/expression_evaluation.hpp b/include/boost/numeric/ublas/tensor/expression_evaluation.hpp index 75e0f9cb0..a7948639a 100644 --- a/include/boost/numeric/ublas/tensor/expression_evaluation.hpp +++ b/include/boost/numeric/ublas/tensor/expression_evaluation.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_ -#define _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_ +#ifndef _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_ +#define _BOOST_UBLAS_TENSOR_EXPRESSIONS_EVALUATION_HPP_ #include #include @@ -90,14 +90,14 @@ template auto retrieve_extents(tensor_expression const& expr) { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); auto const& cast_expr = static_cast(expr); if constexpr ( std::is_same::value ) - return cast_expr.extents(); + return cast_expr.extents(); else - return retrieve_extents(cast_expr); + return retrieve_extents(cast_expr); } /** @brief Retrieves extents of the binary tensor expression @@ -110,19 +110,19 @@ template auto retrieve_extents(binary_tensor_expression const& expr) { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); if constexpr ( std::is_same::value ) - return expr.el.extents(); + return expr.el.extents(); if constexpr ( std::is_same::value ) - return expr.er.extents(); + return expr.er.extents(); else if constexpr ( detail::has_tensor_types::value ) - return retrieve_extents(expr.el); + return retrieve_extents(expr.el); else if constexpr ( detail::has_tensor_types::value ) - return retrieve_extents(expr.er); + return retrieve_extents(expr.er); } /** @brief Retrieves extents of the binary tensor expression @@ -136,13 +136,13 @@ auto retrieve_extents(unary_tensor_expression const& expr) { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::retrieve_extents: Expression to evaluate should contain tensors."); if constexpr ( std::is_same::value ) - return expr.e.extents(); + return expr.e.extents(); else if constexpr ( detail::has_tensor_types::value ) - return retrieve_extents(expr.e); + return retrieve_extents(expr.e); } } // namespace boost::numeric::ublas::detail @@ -162,17 +162,17 @@ template auto all_extents_equal(tensor_expression const& expr, basic_extents const& extents) { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); auto const& cast_expr = static_cast(expr); if constexpr ( std::is_same::value ) - if( extents != cast_expr.extents() ) - return false; + if( extents != cast_expr.extents() ) + return false; if constexpr ( detail::has_tensor_types::value ) - if ( !all_extents_equal(cast_expr, extents)) - return false; + if ( !all_extents_equal(cast_expr, extents)) + return false; return true; @@ -182,23 +182,23 @@ template auto all_extents_equal(binary_tensor_expression const& expr, basic_extents const& extents) { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); if constexpr ( std::is_same::value ) - if(extents != expr.el.extents()) - return false; + if(extents != expr.el.extents()) + return false; if constexpr ( std::is_same::value ) - if(extents != expr.er.extents()) - return false; + if(extents != expr.er.extents()) + return false; if constexpr ( detail::has_tensor_types::value ) - if(!all_extents_equal(expr.el, extents)) - return false; + if(!all_extents_equal(expr.el, extents)) + return false; if constexpr ( detail::has_tensor_types::value ) - if(!all_extents_equal(expr.er, extents)) - return false; + if(!all_extents_equal(expr.er, extents)) + return false; return true; } @@ -209,15 +209,15 @@ auto all_extents_equal(unary_tensor_expression const& expr, basic_extent { static_assert(detail::has_tensor_types>::value, - "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); + "Error in boost::numeric::ublas::detail::all_extents_equal: Expression to evaluate should contain tensors."); if constexpr ( std::is_same::value ) - if(extents != expr.e.extents()) - return false; + if(extents != expr.e.extents()) + return false; if constexpr ( detail::has_tensor_types::value ) - if(!all_extents_equal(expr.e, extents)) - return false; + if(!all_extents_equal(expr.e, extents)) + return false; return true; } @@ -238,10 +238,10 @@ template void eval(tensor_type& lhs, tensor_expression const& expr) { if constexpr (detail::has_tensor_types >::value ) - if(!detail::all_extents_equal(expr, lhs.extents() )) - throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); + if(!detail::all_extents_equal(expr, lhs.extents() )) + throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); - #pragma omp parallel for +#pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) lhs(i) = expr()(i); } @@ -258,10 +258,10 @@ void eval(tensor_type& lhs, tensor_expression const& { if constexpr (detail::has_tensor_types< tensor_type, tensor_expression >::value ) - if(!detail::all_extents_equal( expr, lhs.extents() )) - throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); + if(!detail::all_extents_equal( expr, lhs.extents() )) + throw std::runtime_error("Error in boost::numeric::ublas::tensor: expression contains tensors with different shapes."); - #pragma omp parallel for +#pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) fn(lhs(i), expr()(i)); } @@ -278,7 +278,7 @@ void eval(tensor_type& lhs, tensor_expression const& template void eval(tensor_type& lhs, unary_fn const fn) { - #pragma omp parallel for +#pragma omp parallel for for(auto i = 0u; i < lhs.size(); ++i) fn(lhs(i)); } diff --git a/include/boost/numeric/ublas/tensor/extents.hpp b/include/boost/numeric/ublas/tensor/extents.hpp index 11bdc0ea5..5d4bf8e5c 100644 --- a/include/boost/numeric/ublas/tensor/extents.hpp +++ b/include/boost/numeric/ublas/tensor/extents.hpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // @@ -22,7 +22,9 @@ #include -namespace boost { namespace numeric { namespace ublas { +namespace boost { +namespace numeric { +namespace ublas { /** @brief Template class for storing tensor extents with runtime variable size. @@ -51,7 +53,7 @@ class basic_extents * @code auto ex = basic_extents{}; */ constexpr explicit basic_extents() - : _base{} + : _base{} { } @@ -64,7 +66,7 @@ class basic_extents * @param b one-dimensional std::vector container */ explicit basic_extents(base_type const& b) - : _base(b) + : _base(b) { if (!this->valid()){ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements."); @@ -80,7 +82,7 @@ class basic_extents * @param b one-dimensional container of type std::vector */ explicit basic_extents(base_type && b) - : _base(std::move(b)) + : _base(std::move(b)) { if (!this->valid()){ throw std::length_error("Error in basic_extents::basic_extents() : shape tuple is not a valid permutation: has zero elements."); @@ -96,7 +98,7 @@ class basic_extents * @param l one-dimensional list of type std::initializer */ basic_extents(std::initializer_list l) - : basic_extents( base_type(std::move(l)) ) + : basic_extents( base_type(std::move(l)) ) { } @@ -110,19 +112,19 @@ class basic_extents * @param last iterator pointing to the next position after the last element */ basic_extents(const_iterator first, const_iterator last) - : basic_extents ( base_type( first,last ) ) + : basic_extents ( base_type( first,last ) ) { } /** @brief Copy constructs basic_extents */ basic_extents(basic_extents const& l ) - : _base(l._base) + : _base(l._base) { } /** @brief Move constructs basic_extents */ basic_extents(basic_extents && l ) noexcept - : _base(std::move(l._base)) + : _base(std::move(l._base)) { } @@ -146,9 +148,10 @@ class basic_extents */ bool is_scalar() const { - return _base.size() != 0 && - std::all_of(_base.begin(), _base.end(), - [](const_reference a){ return a == 1;}); + return + _base.size() != 0 && + std::all_of(_base.begin(), _base.end(), + [](const_reference a){ return a == 1;}); } /** @brief Returns true if this has a vector shape @@ -168,9 +171,10 @@ class basic_extents auto greater_one = [](const_reference a){ return a > 1;}; auto equal_one = [](const_reference a){ return a == 1;}; - return std::any_of(_base.begin(), _base.begin()+2, greater_one) && - std::any_of(_base.begin(), _base.begin()+2, equal_one ) && - std::all_of(_base.begin()+2, _base.end(), equal_one); + return + std::any_of(_base.begin(), _base.begin()+2, greater_one) && + std::any_of(_base.begin(), _base.begin()+2, equal_one ) && + std::all_of(_base.begin()+2, _base.end(), equal_one); } /** @brief Returns true if this has a matrix shape @@ -186,8 +190,9 @@ class basic_extents auto greater_one = [](const_reference a){ return a > 1;}; auto equal_one = [](const_reference a){ return a == 1;}; - return std::all_of(_base.begin(), _base.begin()+2, greater_one) && - std::all_of(_base.begin()+2, _base.end(), equal_one ); + return + std::all_of(_base.begin(), _base.begin()+2, greater_one) && + std::all_of(_base.begin()+2, _base.end(), equal_one ); } /** @brief Returns true if this is has a tensor shape @@ -244,8 +249,10 @@ class basic_extents /** @brief Returns true if size > 1 and all elements > 0 */ bool valid() const { - return this->size() > 1 && std::none_of(_base.begin(), _base.end(), - [](const_reference a){ return a == value_type(0); }); + return + this->size() > 1 && + std::none_of(_base.begin(), _base.end(), + [](const_reference a){ return a == value_type(0); }); } /** @brief Returns the number of elements a tensor holds with this */ diff --git a/include/boost/numeric/ublas/tensor/functions.hpp b/include/boost/numeric/ublas/tensor/functions.hpp index 8fa93e0f6..e2043ceb1 100644 --- a/include/boost/numeric/ublas/tensor/functions.hpp +++ b/include/boost/numeric/ublas/tensor/functions.hpp @@ -1,17 +1,17 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_FUNCTIONS_ -#define _BOOST_UBLAS_TENSOR_FUNCTIONS_ +#ifndef BOOST_UBLAS_TENSOR_FUNCTIONS_HPP +#define BOOST_UBLAS_TENSOR_FUNCTIONS_HPP #include @@ -67,19 +67,19 @@ auto prod(tensor const& a, vector const& b, const std::size_t m) auto const p = std::size_t(a.rank()); if( m == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: Contraction mode must be greater than zero."); + throw std::length_error("error in boost::numeric::ublas::prod(ttv): contraction mode must be greater than zero."); if( p < m ) - throw std::length_error("Error in boost::numeric::ublas::prod: Rank must be greater equal the modus."); + throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than or equal to the modus."); if( p == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: Rank must be greater than zero."); + throw std::length_error("error in boost::numeric::ublas::prod(ttv): rank of tensor must be greater than zero."); if( a.empty() ) - throw std::length_error("Error in boost::numeric::ublas::prod: tensor should not be empty."); + throw std::length_error("error in boost::numeric::ublas::prod(ttv): first argument tensor should not be empty."); if( b.size() == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: vector should not be empty."); + throw std::length_error("error in boost::numeric::ublas::prod(ttv): second argument vector should not be empty."); auto nc = ebase_type(std::max(p-1, size_type(2)) , size_type(1)); @@ -95,9 +95,9 @@ auto prod(tensor const& a, vector const& b, const std::size_t m) auto bb = &(b(0)); ttv(m, p, - c.data(), c.extents().data(), c.strides().data(), - a.data(), a.extents().data(), a.strides().data(), - bb, nb.data(), nb.data()); + c.data(), c.extents().data(), c.strides().data(), + a.data(), a.extents().data(), a.strides().data(), + bb, nb.data(), nb.data()); return c; @@ -130,19 +130,19 @@ auto prod(tensor const& a, matrix const& b, const std::size_t m) auto const p = a.rank(); if( m == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: Contraction mode must be greater than zero."); + throw std::length_error("error in boost::numeric::ublas::prod(ttm): contraction mode must be greater than zero."); if( p < m || m > a.extents().size()) - throw std::length_error("Error in boost::numeric::ublas::prod: Rank must be greater equal the modus."); + throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater equal the modus."); if( p == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: Rank must be greater than zero."); + throw std::length_error("error in boost::numeric::ublas::prod(ttm): rank of the tensor must be greater than zero."); if( a.empty() ) - throw std::length_error("Error in boost::numeric::ublas::prod: tensor should not be empty."); + throw std::length_error("error in boost::numeric::ublas::prod(ttm): first argument tensor should not be empty."); if( b.size1()*b.size2() == 0) - throw std::length_error("Error in boost::numeric::ublas::prod: matrix should not be empty."); + throw std::length_error("error in boost::numeric::ublas::prod(ttm): second argument matrix should not be empty."); auto nc = a.extents().base(); @@ -156,9 +156,9 @@ auto prod(tensor const& a, matrix const& b, const std::size_t m) auto bb = &(b(0,0)); ttm(m, p, - c.data(), c.extents().data(), c.strides().data(), - a.data(), a.extents().data(), a.strides().data(), - bb, nb.data(), wb.data()); + c.data(), c.extents().data(), c.strides().data(), + a.data(), a.extents().data(), a.strides().data(), + bb, nb.data(), wb.data()); return c; @@ -183,7 +183,7 @@ auto prod(tensor const& a, matrix const& b, const std::size_t m) */ template auto prod(tensor const& a, tensor const& b, - std::vector const& phia, std::vector const& phib) + std::vector const& phia, std::vector const& phib) { using tensor_type = tensor; @@ -197,21 +197,21 @@ auto prod(tensor const& a, tensor const& b, auto const q = size_type(phia.size()); if(pa == 0ul) - throw std::runtime_error("Error in ublas::prod: order of left-hand side tensor must be greater than 0."); + throw std::runtime_error("error in ublas::prod: order of left-hand side tensor must be greater than 0."); if(pb == 0ul) - throw std::runtime_error("Error in ublas::prod: order of right-hand side tensor must be greater than 0."); + throw std::runtime_error("error in ublas::prod: order of right-hand side tensor must be greater than 0."); if(pa < q) - throw std::runtime_error("Error in ublas::prod: number of contraction dimensions cannot be greater than the order of the left-hand side tensor."); + throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the left-hand side tensor."); if(pb < q) - throw std::runtime_error("Error in ublas::prod: number of contraction dimensions cannot be greater than the order of the right-hand side tensor."); + throw std::runtime_error("error in ublas::prod: number of contraction dimensions cannot be greater than the order of the right-hand side tensor."); if(q != phib.size()) - throw std::runtime_error("Error in ublas::prod: permutation tuples must have the same length."); + throw std::runtime_error("error in ublas::prod: permutation tuples must have the same length."); if(pa < phia.size()) - throw std::runtime_error("Error in ublas::prod: permutation tuple for the left-hand side tensor cannot be greater than the corresponding order."); + throw std::runtime_error("error in ublas::prod: permutation tuple for the left-hand side tensor cannot be greater than the corresponding order."); if(pb < phib.size()) - throw std::runtime_error("Error in ublas::prod: permutation tuple for the right-hand side tensor cannot be greater than the corresponding order."); + throw std::runtime_error("error in ublas::prod: permutation tuple for the right-hand side tensor cannot be greater than the corresponding order."); auto const& na = a.extents(); @@ -219,7 +219,7 @@ auto prod(tensor const& a, tensor const& b, for(auto i = 0ul; i < q; ++i) if( na.at(phia.at(i)-1) != nb.at(phib.at(i)-1)) - throw std::runtime_error("Error in ublas::prod: permutations of the extents are not correct."); + throw std::runtime_error("error in ublas::prod: permutations of the extents are not correct."); auto const r = pa - q; auto const s = pb - q; @@ -234,7 +234,7 @@ auto prod(tensor const& a, tensor const& b, for(auto i = 0ul; i < phia.size(); ++i) * std::remove(phia1.begin(), phia1.end(), phia.at(i)) = phia.at(i); - //phia1.erase( std::remove(phia1.begin(), phia1.end(), phia.at(i)), phia1.end() ) ; + //phia1.erase( std::remove(phia1.begin(), phia1.end(), phia.at(i)), phia1.end() ) ; assert(phia1.size() == pa); @@ -243,14 +243,14 @@ auto prod(tensor const& a, tensor const& b, for(auto i = 0ul; i < phib.size(); ++i) * std::remove(phib1.begin(), phib1.end(), phib.at(i)) = phib.at(i) ; - //phib1.erase( std::remove(phib1.begin(), phib1.end(), phia.at(i)), phib1.end() ) ; + //phib1.erase( std::remove(phib1.begin(), phib1.end(), phia.at(i)), phib1.end() ) ; assert(phib1.size() == pb); for(auto i = 0ul; i < s; ++i) nc[ r + i ] = nb[ phib1[ i ] - 1 ]; -// std::copy( phib.begin(), phib.end(), phib1.end() ); + // std::copy( phib.begin(), phib.end(), phib1.end() ); assert( phia1.size() == pa ); assert( phib1.size() == pb ); @@ -258,10 +258,10 @@ auto prod(tensor const& a, tensor const& b, auto c = tensor_type(extents_type(nc), value_type{}); ttt(pa, pb, q, - phia1.data(), phib1.data(), - c.data(), c.extents().data(), c.strides().data(), - a.data(), a.extents().data(), a.strides().data(), - b.data(), b.extents().data(), b.strides().data()); + phia1.data(), phib1.data(), + c.data(), c.extents().data(), c.strides().data(), + a.data(), a.extents().data(), a.strides().data(), + b.data(), b.extents().data(), b.strides().data()); return c; } @@ -287,7 +287,7 @@ auto prod(tensor const& a, tensor const& b, */ template auto prod(tensor const& a, tensor const& b, - std::vector const& phi) + std::vector const& phi) { return prod(a, b, phi, phi); } @@ -310,17 +310,17 @@ auto inner_prod(tensor const& a, tensor const& b) using value_type = typename tensor::value_type; if( a.rank() != b.rank() ) - throw std::length_error("Error in boost::numeric::ublas::inner_prod: Rank of both tensors must be the same."); + throw std::length_error("error in boost::numeric::ublas::inner_prod: Rank of both tensors must be the same."); if( a.empty() || b.empty()) - throw std::length_error("Error in boost::numeric::ublas::inner_prod: Tensors should not be empty."); + throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensors should not be empty."); if( a.extents() != b.extents()) - throw std::length_error("Error in boost::numeric::ublas::inner_prod: Tensor extents should be the same."); + throw std::length_error("error in boost::numeric::ublas::inner_prod: Tensor extents should be the same."); return inner(a.rank(), a.extents().data(), - a.data(), a.strides().data(), - b.data(), b.strides().data(), value_type{0}); + a.data(), a.strides().data(), + b.data(), b.strides().data(), value_type{0}); } /** @brief Computes the outer product of two tensors @@ -341,7 +341,7 @@ auto outer_prod(tensor const& a, tensor const& b) using extents_type = typename tensor_type::extents_type; if( a.empty() || b.empty() ) - throw std::runtime_error("Error in boost::numeric::ublas::outer_prod: tensors should not be empty."); + throw std::runtime_error("error in boost::numeric::ublas::outer_prod: tensors should not be empty."); auto nc = typename extents_type::base_type(a.rank() + b.rank()); for(auto i = 0u; i < a.rank(); ++i) @@ -353,8 +353,8 @@ auto outer_prod(tensor const& a, tensor const& b) auto c = tensor_type(extents_type(nc)); outer(c.data(), c.rank(), c.extents().data(), c.strides().data(), - a.data(), a.rank(), a.extents().data(), a.strides().data(), - b.data(), b.rank(), b.extents().data(), b.strides().data()); + a.data(), a.rank(), a.extents().data(), a.strides().data(), + b.data(), b.rank(), b.extents().data(), b.strides().data()); return c; } @@ -376,7 +376,7 @@ auto trans(tensor const& a, std::vector const& tau) { using tensor_type = tensor; using extents_type = typename tensor_type::extents_type; -// using strides_type = typename tensor_type::strides_type; + // using strides_type = typename tensor_type::strides_type; if( a.empty() ) return tensor{}; @@ -388,24 +388,24 @@ auto trans(tensor const& a, std::vector const& tau) for(auto i = 0u; i < p; ++i) nc.at(tau.at(i)-1) = na.at(i); -// auto wc = strides_type(extents_type(nc)); + // auto wc = strides_type(extents_type(nc)); auto c = tensor_type(extents_type(nc)); trans( a.rank(), a.extents().data(), tau.data(), - c.data(), c.strides().data(), - a.data(), a.strides().data()); + c.data(), c.strides().data(), + a.data(), a.strides().data()); -// auto wc_pi = typename strides_type::base_type (p); -// for(auto i = 0u; i < p; ++i) -// wc_pi.at(tau.at(i)-1) = c.strides().at(i); + // auto wc_pi = typename strides_type::base_type (p); + // for(auto i = 0u; i < p; ++i) + // wc_pi.at(tau.at(i)-1) = c.strides().at(i); -//copy(a.rank(), -// a.extents().data(), -// c.data(), wc_pi.data(), -// a.data(), a.strides().data() ); + //copy(a.rank(), + // a.extents().data(), + // c.data(), wc_pi.data(), + // a.data(), a.strides().data() ); return c; } @@ -433,10 +433,10 @@ auto norm(detail::tensor_expression const& expr) auto a = tensor_type( expr ); if( a.empty() ) - throw std::runtime_error("Error in boost::numeric::ublas::norm: tensors should not be empty."); + throw std::runtime_error("error in boost::numeric::ublas::norm: tensors should not be empty."); return std::sqrt( accumulate( a.order(), a.extents().data(), a.data(), a.strides().data(), value_type{}, - [](auto const& l, auto const& r){ return l + r*r; } ) ) ; + [](auto const& l, auto const& r){ return l + r*r; } ) ) ; } @@ -463,7 +463,7 @@ auto real(detail::tensor_expression,F,A>,D> const& expr) using tensor_type = tensor::template rebind>; if( detail::retrieve_extents( expr ).empty() ) - throw std::runtime_error("Error in boost::numeric::ublas::real: tensors should not be empty."); + throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty."); auto a = tensor_complex_type( expr ); auto c = tensor_type( a.extents() ); @@ -497,7 +497,7 @@ auto imag(detail::tensor_expression,F,A>,D> const& expr) using tensor_type = tensor::template rebind>; if( detail::retrieve_extents( expr ).empty() ) - throw std::runtime_error("Error in boost::numeric::ublas::real: tensors should not be empty."); + throw std::runtime_error("error in boost::numeric::ublas::real: tensors should not be empty."); auto a = tensor_complex_type( expr ); auto c = tensor_type( a.extents() ); @@ -526,7 +526,7 @@ auto conj(detail::tensor_expression const& expr) using tensor_complex_type = tensor; if( detail::retrieve_extents( expr ).empty() ) - throw std::runtime_error("Error in boost::numeric::ublas::conj: tensors should not be empty."); + throw std::runtime_error("error in boost::numeric::ublas::conj: tensors should not be empty."); auto a = tensor_type( expr ); auto c = tensor_complex_type( a.extents() ); diff --git a/include/boost/numeric/ublas/tensor/index.hpp b/include/boost/numeric/ublas/tensor/index.hpp index 336500008..a8a40deb8 100644 --- a/include/boost/numeric/ublas/tensor/index.hpp +++ b/include/boost/numeric/ublas/tensor/index.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_INDEX_HPP_ -#define _BOOST_UBLAS_TENSOR_INDEX_HPP_ +#ifndef BOOST_UBLAS_TENSOR_INDEX_HPP +#define BOOST_UBLAS_TENSOR_INDEX_HPP #include diff --git a/include/boost/numeric/ublas/tensor/multi_index.hpp b/include/boost/numeric/ublas/tensor/multi_index.hpp index 7b85b56ed..3cc86e2fd 100644 --- a/include/boost/numeric/ublas/tensor/multi_index.hpp +++ b/include/boost/numeric/ublas/tensor/multi_index.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP_ -#define _BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP_ +#ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP +#define BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP #include @@ -49,17 +49,17 @@ class multi_index template constexpr multi_index(index::index_type const& i, indexes ... is ) - : _base{i(), is()... } + : _base{i(), is()... } { static_assert( sizeof...(is)+1 == N, - "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." ); + "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." ); static_assert( valid_multi_index, indexes ...> >::value, - "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." ); + "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." ); } multi_index(multi_index const& other) - : _base(other._base) + : _base(other._base) { } @@ -94,7 +94,7 @@ auto array_to_vector(multi_index const& lhs, multi_index const& rhs) for(auto j = 0u; j < M; ++j) if ( lhs.at(i) == rhs.at(j) && lhs.at(i) != boost::numeric::ublas::index::_()) pair_of_vector.first .push_back( i+1 ), - pair_of_vector.second.push_back( j+1 ); + pair_of_vector.second.push_back( j+1 ); return pair_of_vector; } diff --git a/include/boost/numeric/ublas/tensor/multi_index_utility.hpp b/include/boost/numeric/ublas/tensor/multi_index_utility.hpp index d4a77355f..f04c0e867 100644 --- a/include/boost/numeric/ublas/tensor/multi_index_utility.hpp +++ b/include/boost/numeric/ublas/tensor/multi_index_utility.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ -#define _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_ +#ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP +#define BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP #include @@ -179,7 +179,7 @@ template struct number_equal_indexes { static constexpr unsigned value = - detail::number_equal_indexes_impl< std::decay_t, std::decay_t>::value; + detail::number_equal_indexes_impl< std::decay_t, std::decay_t>::value; }; } // namespace ublas @@ -259,7 +259,7 @@ struct index_position_pairs_impl using get_index_type = index_position; using next_type = index_position_pairs_impl; if constexpr ( has_index_type::value && index_type::value != 0) - out[p++] = std::make_pair(r-1,get_index_type::value); + out[p++] = std::make_pair(r-1,get_index_type::value); next_type::run( out, lhs, rhs, p ); } }; @@ -274,7 +274,7 @@ struct index_position_pairs_impl using has_index_type = has_index; using get_index_type = index_position; if constexpr ( has_index_type::value && index_type::value != 0 ) - out[p] = std::make_pair(m-1,get_index_type::value); + out[p] = std::make_pair(m-1,get_index_type::value); } }; @@ -332,8 +332,8 @@ template constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence ) { return std::make_pair( - std::vector{std::get<0>( std::get(array) )+1 ...} , - std::vector{std::get<1>( std::get(array) )+1 ...} ); + std::vector{std::get<0>( std::get(array) )+1 ...} , + std::vector{std::get<1>( std::get(array) )+1 ...} ); } } // namespace detail diff --git a/include/boost/numeric/ublas/tensor/multiplication.hpp b/include/boost/numeric/ublas/tensor/multiplication.hpp index 698b6b1ef..f415a3e2f 100644 --- a/include/boost/numeric/ublas/tensor/multiplication.hpp +++ b/include/boost/numeric/ublas/tensor/multiplication.hpp @@ -1,17 +1,17 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_MULTIPLICATION_ -#define _BOOST_UBLAS_TENSOR_MULTIPLICATION_ +#ifndef BOOST_UBLAS_TENSOR_MULTIPLICATION +#define BOOST_UBLAS_TENSOR_MULTIPLICATION #include @@ -51,11 +51,11 @@ namespace recursive { template void ttt(SizeType const k, - SizeType const r, SizeType const s, SizeType const q, - SizeType const*const phia, SizeType const*const phib, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + SizeType const r, SizeType const s, SizeType const q, + SizeType const*const phia, SizeType const*const phib, + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { @@ -115,10 +115,10 @@ void ttt(SizeType const k, template void ttt(SizeType const k, - SizeType const r, SizeType const s, SizeType const q, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + SizeType const r, SizeType const s, SizeType const q, + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { @@ -168,9 +168,9 @@ void ttt(SizeType const k, template void ttm(SizeType const m, SizeType const r, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(r == m) { @@ -215,9 +215,9 @@ void ttm(SizeType const m, SizeType const r, */ template void ttm0( SizeType const r, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(r > 1){ @@ -269,9 +269,9 @@ void ttm0( SizeType const r, template void ttv( SizeType const m, SizeType const r, SizeType const q, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b) { if(r == m) { @@ -309,9 +309,9 @@ void ttv( SizeType const m, SizeType const r, SizeType const q, */ template void ttv0(SizeType const r, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b) { if(r > 1){ @@ -346,9 +346,9 @@ void ttv0(SizeType const r, */ template void mtv(SizeType const m, - PointerOut c, SizeType const*const , SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b) + PointerOut c, SizeType const*const , SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b) { // decides whether matrix multiplied with vector or vector multiplied with matrix const auto o = (m == 0) ? 1 : 0; @@ -379,8 +379,8 @@ void mtv(SizeType const m, */ template void mtm(PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { // C(i,j) = A(i,k) * B(k,j) @@ -424,9 +424,9 @@ void mtm(PointerOut c, SizeType const*const nc, SizeType const*const wc, */ template value_t inner(SizeType const r, SizeType const*const n, - PointerIn1 a, SizeType const*const wa, - PointerIn2 b, SizeType const*const wb, - value_t v) + PointerIn1 a, SizeType const*const wa, + PointerIn2 b, SizeType const*const wb, + value_t v) { if(r == 0) for(auto i0 = 0u; i0 < n[0]; a += wa[0], b += wb[0], ++i0) @@ -440,9 +440,9 @@ value_t inner(SizeType const r, SizeType const*const n, template void outer_2x2(SizeType const pa, - PointerOut c, SizeType const*const , SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const , SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { // assert(rc == 3); // assert(ra == 1); @@ -491,9 +491,9 @@ void outer_2x2(SizeType const pa, */ template void outer(SizeType const pa, - SizeType const rc, PointerOut c, SizeType const*const nc, SizeType const*const wc, - SizeType const ra, PointerIn1 a, SizeType const*const na, SizeType const*const wa, - SizeType const rb, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + SizeType const rc, PointerOut c, SizeType const*const nc, SizeType const*const wc, + SizeType const ra, PointerIn1 a, SizeType const*const na, SizeType const*const wa, + SizeType const rb, PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(rb > 1) for(auto ib = 0u; ib < nb[rb]; b += wb[rb], c += wc[rc], ++ib) @@ -535,11 +535,11 @@ void outer(SizeType const pa, template void outer(SizeType const k, - SizeType const r, SizeType const s, - SizeType const*const phia, SizeType const*const phib, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + SizeType const r, SizeType const s, + SizeType const*const phia, SizeType const*const phib, + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { if(k < r) { @@ -610,12 +610,12 @@ namespace ublas { */ template void ttv(SizeType const m, SizeType const p, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - const PointerIn1 a, SizeType const*const na, SizeType const*const wa, - const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + const PointerIn1 a, SizeType const*const na, SizeType const*const wa, + const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer::value & std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::ttv: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::ttv: Argument types for pointers are not pointer types."); if( m == 0) throw std::length_error("Error in boost::numeric::ublas::ttv: Contraction mode must be greater than zero."); @@ -680,13 +680,13 @@ void ttv(SizeType const m, SizeType const p, template void ttm(SizeType const m, SizeType const p, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - const PointerIn1 a, SizeType const*const na, SizeType const*const wa, - const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + const PointerIn1 a, SizeType const*const na, SizeType const*const wa, + const PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer::value & std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( m == 0 ) throw std::length_error("Error in boost::numeric::ublas::ttm: Contraction mode must be greater than zero."); @@ -750,13 +750,13 @@ void ttm(SizeType const m, SizeType const p, template void ttt(SizeType const pa, SizeType const pb, SizeType const q, - SizeType const*const phia, SizeType const*const phib, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + SizeType const*const phia, SizeType const*const phib, + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer::value & std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( pa == 0 || pb == 0) throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero."); @@ -818,12 +818,12 @@ void ttt(SizeType const pa, SizeType const pb, SizeType const q, template void ttt(SizeType const pa, SizeType const pb, SizeType const q, - PointerOut c, SizeType const*const nc, SizeType const*const wc, - PointerIn1 a, SizeType const*const na, SizeType const*const wa, - PointerIn2 b, SizeType const*const nb, SizeType const*const wb) + PointerOut c, SizeType const*const nc, SizeType const*const wc, + PointerIn1 a, SizeType const*const na, SizeType const*const wa, + PointerIn2 b, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer::value & std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); + "Static error in boost::numeric::ublas::ttm: Argument types for pointers are not pointer types."); if( pa == 0 || pb == 0) throw std::length_error("Error in boost::numeric::ublas::ttt: tensor order must be greater zero."); @@ -882,12 +882,12 @@ void ttt(SizeType const pa, SizeType const pb, SizeType const q, */ template auto inner(const SizeType p, SizeType const*const n, - const PointerIn1 a, SizeType const*const wa, - const PointerIn2 b, SizeType const*const wb, - value_t v) + const PointerIn1 a, SizeType const*const wa, + const PointerIn2 b, SizeType const*const wb, + value_t v) { static_assert( std::is_pointer::value && std::is_pointer::value, - "Static error in boost::numeric::ublas::inner: Argument types for pointers must be pointer types."); + "Static error in boost::numeric::ublas::inner: Argument types for pointers must be pointer types."); if(p<2) throw std::length_error("Error in boost::numeric::ublas::inner: Rank must be greater than zero."); if(a == nullptr || b == nullptr) @@ -919,11 +919,11 @@ auto inner(const SizeType p, SizeType const*const n, */ template void outer(PointerOut c, SizeType const pc, SizeType const*const nc, SizeType const*const wc, - const PointerIn1 a, SizeType const pa, SizeType const*const na, SizeType const*const wa, - const PointerIn2 b, SizeType const pb, SizeType const*const nb, SizeType const*const wb) + const PointerIn1 a, SizeType const pa, SizeType const*const na, SizeType const*const wa, + const PointerIn2 b, SizeType const pb, SizeType const*const nb, SizeType const*const wb) { static_assert( std::is_pointer::value & std::is_pointer::value & std::is_pointer::value, - "Static error in boost::numeric::ublas::outer: argument types for pointers must be pointer types."); + "Static error in boost::numeric::ublas::outer: argument types for pointers must be pointer types."); if(pa < 2u || pb < 2u) throw std::length_error("Error in boost::numeric::ublas::outer: number of extents of lhs and rhs tensor must be equal or greater than two."); if((pa + pb) != pc) diff --git a/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp b/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp index 7ae9ffb2c..c9de6d30c 100644 --- a/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp +++ b/include/boost/numeric/ublas/tensor/operators_arithmetic.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_ -#define _BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_ +#ifndef BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP +#define BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP #include "expression.hpp" #include "expression_evaluation.hpp" diff --git a/include/boost/numeric/ublas/tensor/operators_comparison.hpp b/include/boost/numeric/ublas/tensor/operators_comparison.hpp index b44938ca2..e54b47af4 100644 --- a/include/boost/numeric/ublas/tensor/operators_comparison.hpp +++ b/include/boost/numeric/ublas/tensor/operators_comparison.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_ -#define _BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_ +#ifndef BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP +#define BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP #include #include diff --git a/include/boost/numeric/ublas/tensor/ostream.hpp b/include/boost/numeric/ublas/tensor/ostream.hpp index 5f2dd3840..74ee77ea6 100644 --- a/include/boost/numeric/ublas/tensor/ostream.hpp +++ b/include/boost/numeric/ublas/tensor/ostream.hpp @@ -1,16 +1,16 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // -#ifndef _BOOST_UBLAS_TENSOR_OSTREAM_ -#define _BOOST_UBLAS_TENSOR_OSTREAM_ +#ifndef BOOST_UBLAS_TENSOR_OSTREAM_HPP +#define BOOST_UBLAS_TENSOR_OSTREAM_HPP #include #include diff --git a/include/boost/numeric/ublas/tensor/strides.hpp b/include/boost/numeric/ublas/tensor/strides.hpp index 0595b16bd..53de553bb 100644 --- a/include/boost/numeric/ublas/tensor/strides.hpp +++ b/include/boost/numeric/ublas/tensor/strides.hpp @@ -1,18 +1,18 @@ // -// Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com +// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of -// Fraunhofer IOSB, Ettlingen Germany +// Fraunhofer IOSB, Ettlingen, Germany // /// \file strides.hpp Definition for the basic_strides template class -#ifndef _BOOST_UBLAS_TENSOR_STRIDES_ -#define _BOOST_UBLAS_TENSOR_STRIDES_ +#ifndef BOOST_UBLAS_TENSOR_STRIDES_HPP +#define BOOST_UBLAS_TENSOR_STRIDES_HPP #include #include @@ -20,12 +20,13 @@ #include #include #include - #include #include -namespace boost { namespace numeric { namespace ublas { +namespace boost { +namespace numeric { +namespace ublas { using first_order = column_major; using last_order = row_major; @@ -243,6 +244,8 @@ auto access(std::size_t sum, basic_strides const& w, s } -}}} +} +} +} #endif diff --git a/include/boost/numeric/ublas/tensor/tensor.hpp b/include/boost/numeric/ublas/tensor/tensor.hpp index 90662e021..ea4521c29 100644 --- a/include/boost/numeric/ublas/tensor/tensor.hpp +++ b/include/boost/numeric/ublas/tensor/tensor.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 +// Copyright (c) 2018-2019 // Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See @@ -13,8 +13,8 @@ /// \file tensor.hpp Definition for the tensor template class -#ifndef _BOOST_UBLAS_TENSOR_IMPL_ -#define _BOOST_UBLAS_TENSOR_IMPL_ +#ifndef BOOST_UBLAS_TENSOR_IMPL_HPP +#define BOOST_UBLAS_TENSOR_IMPL_HPP #include diff --git a/include/boost/numeric/ublas/vector_of_vector.hpp b/include/boost/numeric/ublas/vector_of_vector.hpp index de87a668a..e18c9a908 100644 --- a/include/boost/numeric/ublas/vector_of_vector.hpp +++ b/include/boost/numeric/ublas/vector_of_vector.hpp @@ -66,7 +66,7 @@ namespace boost { namespace numeric { namespace ublas { storage_invariants (); } BOOST_UBLAS_INLINE - generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0): + generalized_vector_of_vector (size_type size1, size_type size2, size_type /*non_zeros = 0*/): matrix_container (), size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) { const size_type sizeM = layout_type::size_M (size1_, size2_); @@ -84,7 +84,7 @@ namespace boost { namespace numeric { namespace ublas { } template BOOST_UBLAS_INLINE - generalized_vector_of_vector (const matrix_expression &ae, size_type non_zeros = 0): + generalized_vector_of_vector (const matrix_expression &ae, size_type /*non_zeros = 0*/): matrix_container (), size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) { const size_type sizeM = layout_type::size_M (size1_, size2_); diff --git a/include/boost/numeric/ublas/vector_sparse.hpp b/include/boost/numeric/ublas/vector_sparse.hpp index 134a62061..0a021b063 100644 --- a/include/boost/numeric/ublas/vector_sparse.hpp +++ b/include/boost/numeric/ublas/vector_sparse.hpp @@ -397,7 +397,7 @@ namespace boost { namespace numeric { namespace ublas { // Reserving BOOST_UBLAS_INLINE - void reserve (size_type non_zeros = 0, bool preserve = true) { + void reserve (size_type non_zeros, bool /*preserve*/ = true) { detail::map_reserve (data (), restrict_capacity (non_zeros)); } diff --git a/test/Jamfile b/test/Jamfile index 598a5f768..26b67b045 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -51,7 +51,7 @@ project boost-ublas-test : requirements BOOST_UBLAS_NO_EXCEPTIONS vacpp:"BOOST_UBLAS_NO_ELEMENT_PROXIES" - gcc:"-Wall -pedantic -Wextra -Wno-unknown-pragmas -std=c++17" + gcc:"-Wall -Wno-unknown-pragmas" msvc:/bigobj msvc:"/W4" # == all # The define of macros below prevent warnings about the checked versions of SCL and CRT libraries. diff --git a/test/tensor/Jamfile b/test/tensor/Jamfile new file mode 100644 index 000000000..0bbf2c569 --- /dev/null +++ b/test/tensor/Jamfile @@ -0,0 +1,42 @@ +# Boost.uBLAS +# +# Copyright (c) 2018 Cem Bassoy +# +# Use, modification and distribution is subject to the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +project boost/ublas/test/tensor + : requirements + # these tests require C++17 + 11:no + gcc:"-Wall -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-but-set-variable" + ; + +alias unit_test_framework + : # sources + /boost//unit_test_framework + ; + +# make aliases explicit so the libraries will only be built when requested +explicit unit_test_framework ; + + + +test-suite boost-ublas-tensor-test + : + [ run test_tensor.cpp + test_strides.cpp + test_operators_comparison.cpp + test_operators_arithmetic.cpp + test_multiplication.cpp + test_multi_index_utility.cpp + test_multi_index.cpp + test_functions.cpp + test_extents.cpp + test_expression_evaluation.cpp + test_einstein_notation.cpp + test_algorithms.cpp + test_tensor_matrix_vector.cpp + unit_test_framework ] + ; diff --git a/test/tensor/Jamfile.v2 b/test/tensor/Jamfile.v2 deleted file mode 100644 index 7e7ff0a0b..000000000 --- a/test/tensor/Jamfile.v2 +++ /dev/null @@ -1,22 +0,0 @@ -# Boost.uBLAS -# -# Copyright (c) 2018 Cem Bassoy -# -# Use, modification and distribution is subject to the Boost Software License, -# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -alias unit_test_framework - : # sources - /boost//unit_test_framework - ; - -# make aliases explicit so the libraries will only be built when requested -explicit unit_test_framework ; - - - -test-suite boost-ublas-tensor-test - : - [ run test_tensor.cpp unit_test_framework ] - ; \ No newline at end of file diff --git a/test/tensor/test_algorithms.cpp b/test/tensor/test_algorithms.cpp index 265c5b088..4215fc2a1 100644 --- a/test/tensor/test_algorithms.cpp +++ b/test/tensor/test_algorithms.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -22,27 +22,29 @@ BOOST_AUTO_TEST_SUITE ( test_tensor_algorithms, - * boost::unit_test::depends_on("test_extents") - * boost::unit_test::depends_on("test_strides")) ; + * boost::unit_test::depends_on("test_extents") + * boost::unit_test::depends_on("test_strides")) using test_types = zip>::with_t; using test_types2 = std::tuple>; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::shape; - fixture() : extents { - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{4,1,3}, // 6 - extents_type{1,2,3}, // 7 - extents_type{4,2,3}, // 8 - extents_type{4,2,3,5} // 9 - } - {} + fixture() + : extents { + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{4,1,3}, // 6 + extents_type{1,2,3}, // 7 + extents_type{4,2,3}, // 8 + extents_type{4,2,3,5} } // 9 + { + } std::vector extents; }; @@ -79,12 +81,12 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_copy, value, test_type using size_type = typename ublas::strides::value_type; size_type const*const p0 = nullptr; - BOOST_CHECK_THROW( ublas::copy( n.size(), p0, c.data(), wc.data(), b.data(), wb.data() ), std::runtime_error ); - BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), p0, b.data(), wb.data() ), std::runtime_error ); - BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), p0 ), std::runtime_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), p0, c.data(), wc.data(), b.data(), wb.data() ), std::length_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), p0, b.data(), wb.data() ), std::length_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c.data(), wc.data(), b.data(), p0 ), std::length_error ); value_type* c0 = nullptr; - BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c0, wc.data(), b.data(), wb.data() ), std::runtime_error ); + BOOST_CHECK_THROW( ublas::copy( n.size(), n.data(), c0, wc.data(), b.data(), wb.data() ), std::length_error ); } // special case rank == 0 @@ -162,12 +164,12 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_accumulate, value, tes auto const s = n.product(); auto a = vector_type(n.product()); -// auto b = vector_type(n.product()); -// auto c = vector_type(n.product()); + // auto b = vector_type(n.product()); + // auto c = vector_type(n.product()); auto wa = ublas::strides(n); -// auto wb = ublas::strides (n); -// auto wc = ublas::strides(n); + // auto wb = ublas::strides (n); + // auto wc = ublas::strides(n); auto v = value_type{}; for(auto i = 0ul; i < a.size(); ++i, v+=value_type(1)){ @@ -180,7 +182,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_accumulate, value, tes auto acc2 = ublas::accumulate( n.size(), n.data(), a.data(), wa.data(), v, - [](auto const& l, auto const& r){return l + r; }); + [](auto const& l, auto const& r){return l + r; }); BOOST_CHECK_EQUAL( acc2, value_type( s*(s+1) / 2 ) ); @@ -283,5 +285,4 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_algorithms_trans, value, test_typ } -BOOST_AUTO_TEST_SUITE_END(); - +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_einstein_notation.cpp b/test/tensor/test_einstein_notation.cpp index 7d23f3a90..b0326c80c 100644 --- a/test/tensor/test_einstein_notation.cpp +++ b/test/tensor/test_einstein_notation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -19,7 +19,7 @@ #include "utility.hpp" -BOOST_AUTO_TEST_SUITE ( test_einstein_notation, * boost::unit_test::depends_on("test_multi_index") ) ; +BOOST_AUTO_TEST_SUITE ( test_einstein_notation, * boost::unit_test::depends_on("test_multi_index") ) using test_types = zip>::with_t; @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types { auto A = tensor_type{5,3}; auto B = tensor_type{3,4}; -// auto C = tensor_type{4,5,6}; + // auto C = tensor_type{4,5,6}; for(auto j = 0u; j < A.extents().at(1); ++j) for(auto i = 0u; i < A.extents().at(0); ++i) @@ -45,19 +45,19 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types for(auto j = 0u; j < B.extents().at(1); ++j) for(auto i = 0u; i < B.extents().at(0); ++i) - B.at( i,j ) = value_type(i+1); + B.at( i,j ) = value_type(i+1); auto AB = A(_,_e) * B(_e,_); -// std::cout << "A = " << A << std::endl; -// std::cout << "B = " << B << std::endl; -// std::cout << "AB = " << AB << std::endl; + // std::cout << "A = " << A << std::endl; + // std::cout << "B = " << B << std::endl; + // std::cout << "AB = " << AB << std::endl; for(auto j = 0u; j < AB.extents().at(1); ++j) for(auto i = 0u; i < AB.extents().at(0); ++i) - BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(A.at( i,0 ) * ( B.extents().at(0) * (B.extents().at(0)+1) / 2 )) ); + BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(A.at( i,0 ) * ( B.extents().at(0) * (B.extents().at(0)+1) / 2 )) ); } @@ -79,16 +79,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types auto AB = A(_d,_,_f) * B(_f,_d,_); -// std::cout << "A = " << A << std::endl; -// std::cout << "B = " << B << std::endl; -// std::cout << "AB = " << AB << std::endl; + // std::cout << "A = " << A << std::endl; + // std::cout << "B = " << B << std::endl; + // std::cout << "AB = " << AB << std::endl; // n*(n+1)/2; auto const nf = ( B.extents().at(0) * (B.extents().at(0)+1) / 2 ); auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 ); for(auto j = 0u; j < AB.extents().at(1); ++j) for(auto i = 0u; i < AB.extents().at(0); ++i) - BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(nf * nd) ); + BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(nf * nd) ); } @@ -113,10 +113,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 ); for(auto i = 0u; i < AB.extents().at(0); ++i) - BOOST_CHECK_EQUAL ( AB.at( i ) , value_type(nf * nd) ); + BOOST_CHECK_EQUAL ( AB.at( i ) , value_type(nf * nd) ); } } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_expression.cpp b/test/tensor/test_expression.cpp index d9207bb78..ae3ce2050 100644 --- a/test/tensor/test_expression.cpp +++ b/test/tensor/test_expression.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -25,27 +25,29 @@ using test_types = zip>::with_t; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::shape; - fixture() : extents{ - extents_type{}, // 0 - - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{1,2,3}, // 6 - extents_type{1,1,2,3}, // 7 - extents_type{1,2,3,1,1}, // 8 - - extents_type{4,2,3}, // 9 - extents_type{4,2,1,3}, // 10 - extents_type{4,2,1,3,1}, // 11 - extents_type{1,4,2,1,3,1}, // 12 - } // 13 - {} + fixture() + : extents { + extents_type{}, // 0 + + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{1,2,3}, // 6 + extents_type{1,1,2,3}, // 7 + extents_type{1,2,3,1,1}, // 8 + + extents_type{4,2,3}, // 9 + extents_type{4,2,1,3}, // 10 + extents_type{4,2,1,3,1}, // 11 + extents_type{1,4,2,1,3,1} } // 12 + { + } std::vector extents; }; @@ -80,7 +82,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_unary_expression, value, test_typ using namespace boost::numeric; using value_type = typename value::first_type; using layout_type = typename value::second_type; - using tensor_type = ublas::tensor; + using tensor_type = ublas::tensor; auto uplus1 = std::bind( std::plus{}, std::placeholders::_1, value_type(1) ); @@ -88,7 +90,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_unary_expression, value, test_typ auto t = tensor_type(e); auto v = value_type{}; - for(auto& tt: t){ tt = v; v+=value_type{1}; } + for(auto& tt: t) { tt = v; v+=value_type{1}; } const auto uexpr = ublas::detail::make_unary_tensor_expression( t, uplus1 ); diff --git a/test/tensor/test_expression_evaluation.cpp b/test/tensor/test_expression_evaluation.cpp index d771d0c9a..002d51a2b 100644 --- a/test/tensor/test_expression_evaluation.cpp +++ b/test/tensor/test_expression_evaluation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -22,27 +22,29 @@ using test_types = zip>::with_t; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::shape; - fixture() : extents{ - extents_type{}, // 0 - - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{1,2,3}, // 6 - extents_type{1,1,2,3}, // 7 - extents_type{1,2,3,1,1}, // 8 - - extents_type{4,2,3}, // 9 - extents_type{4,2,1,3}, // 10 - extents_type{4,2,1,3,1}, // 11 - extents_type{1,4,2,1,3,1}, // 12 - } // 13 - {} + fixture() + : extents{ + extents_type{}, // 0 + + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{1,2,3}, // 6 + extents_type{1,1,2,3}, // 7 + extents_type{1,2,3,1,1}, // 8 + + extents_type{4,2,3}, // 9 + extents_type{4,2,1,3}, // 10 + extents_type{4,2,1,3,1}, // 11 + extents_type{1,4,2,1,3,1}} // 12 + { + } std::vector extents; }; diff --git a/test/tensor/test_extents.cpp b/test/tensor/test_extents.cpp index db73e74db..9fbeee949 100644 --- a/test/tensor/test_extents.cpp +++ b/test/tensor/test_extents.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -8,7 +8,7 @@ #include #include -BOOST_AUTO_TEST_SUITE ( test_extents ); +BOOST_AUTO_TEST_SUITE ( test_extents ) //*boost::unit_test::label("extents") @@ -64,23 +64,23 @@ BOOST_AUTO_TEST_CASE(test_extents_ctor) struct fixture { using extents_type = boost::numeric::ublas::basic_extents; fixture() : extents{ - extents_type{}, // 0 - - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{1,2,3}, // 6 - extents_type{1,1,2,3}, // 7 - extents_type{1,2,3,1,1}, // 8 - - extents_type{4,2,3}, // 9 - extents_type{4,2,1,3}, // 10 - extents_type{4,2,1,3,1}, // 11 - extents_type{1,4,2,1,3,1}, // 12 - } // 13 + extents_type{}, // 0 + + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{1,2,3}, // 6 + extents_type{1,1,2,3}, // 7 + extents_type{1,2,3,1,1}, // 8 + + extents_type{4,2,3}, // 9 + extents_type{4,2,1,3}, // 10 + extents_type{4,2,1,3,1}, // 11 + extents_type{1,4,2,1,3,1}, // 12 +} // 13 {} std::vector extents; }; @@ -445,5 +445,5 @@ BOOST_FIXTURE_TEST_CASE(test_extents_product, fixture, *boost::unit_test::label( } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_functions.cpp b/test/tensor/test_functions.cpp index acb1fb5ee..64ecda396 100644 --- a/test/tensor/test_functions.cpp +++ b/test/tensor/test_functions.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -21,7 +21,7 @@ #include "utility.hpp" -BOOST_AUTO_TEST_SUITE ( test_tensor_functions, * boost::unit_test::depends_on("test_tensor_contraction") ) ; +BOOST_AUTO_TEST_SUITE ( test_tensor_functions, * boost::unit_test::depends_on("test_tensor_contraction") ) using test_types = zip>::with_t; @@ -29,20 +29,22 @@ using test_types = zip>::with_t::with_t; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::shape; - fixture() : extents { - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{4,1,3}, // 6 - extents_type{1,2,3}, // 7 - extents_type{4,2,3}, // 8 - extents_type{4,2,3,5} // 9 - } - {} + fixture() + : extents { + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{4,1,3}, // 6 + extents_type{1,2,3}, // 7 + extents_type{4,2,3}, // 8 + extents_type{4,2,3,5}} // 9 + { + } std::vector extents; }; @@ -186,26 +188,26 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_prod_tensor_2, value, test_types, auto nb = permute_extents( pi, na ); auto b = tensor_type( nb, value_type{3} ); - // the number of contractions is changed. - for( auto q = 0ul; q <= pa; ++q) { // pa + // the number of contractions is changed. + for( auto q = 0ul; q <= pa; ++q) { // pa - auto phia = std::vector ( q ); // concatenation for a - auto phib = std::vector ( q ); // concatenation for b + auto phia = std::vector ( q ); // concatenation for a + auto phib = std::vector ( q ); // concatenation for b - std::iota(phia.begin(), phia.end(), 1ul); - std::transform( phia.begin(), phia.end(), phib.begin(), - [&pi] ( std::size_t i ) { return pi.at(i-1); } ); + std::iota(phia.begin(), phia.end(), 1ul); + std::transform( phia.begin(), phia.end(), phib.begin(), + [&pi] ( std::size_t i ) { return pi.at(i-1); } ); - auto c = ublas::prod(a, b, phia, phib); + auto c = ublas::prod(a, b, phia, phib); - auto acc = value_type(1); - for(auto i = 0ul; i < q; ++i) - acc *= a.extents().at(phia.at(i)-1); + auto acc = value_type(1); + for(auto i = 0ul; i < q; ++i) + acc *= a.extents().at(phia.at(i)-1); - for(auto i = 0ul; i < c.size(); ++i) - BOOST_CHECK_EQUAL( c[i] , acc * a[0] * b[0] ); + for(auto i = 0ul; i < c.size(); ++i) + BOOST_CHECK_EQUAL( c[i] , acc * a[0] * b[0] ); - } + } std::next_permutation(pi.begin(), pi.end()); } @@ -447,5 +449,5 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_trans, value, test_types, fixture } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_multi_index.cpp b/test/tensor/test_multi_index.cpp index a8ca4d7d5..d6448de22 100644 --- a/test/tensor/test_multi_index.cpp +++ b/test/tensor/test_multi_index.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -20,7 +21,7 @@ #include "utility.hpp" -BOOST_AUTO_TEST_SUITE ( test_multi_index ) ; +BOOST_AUTO_TEST_SUITE ( test_multi_index ) using test_types = zip>::with_t; @@ -91,12 +92,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_multi_index_class_generation, value, using tensor_type = tensor; auto t = std::make_tuple ( - index::_a, // 0 - index::_b, // 1 - index::_c, // 2 - index::_d, // 3 - index::_e // 4 - ); + index::_a, // 0 + index::_b, // 1 + index::_c, // 2 + index::_d, // 3 + index::_e // 4 + ); { auto a = tensor_type(shape{2,3}, value_type{2}); @@ -141,5 +142,5 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_multi_index_class_generation, value, } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_multi_index_utility.cpp b/test/tensor/test_multi_index_utility.cpp index a83ece0d0..2f31a58f2 100644 --- a/test/tensor/test_multi_index_utility.cpp +++ b/test/tensor/test_multi_index_utility.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -14,7 +14,7 @@ #include -BOOST_AUTO_TEST_SUITE ( test_multi_index_utility ) ; +BOOST_AUTO_TEST_SUITE ( test_multi_index_utility ) BOOST_AUTO_TEST_CASE ( test_multi_index_has_index ) @@ -560,5 +560,5 @@ BOOST_AUTO_TEST_CASE ( test_multi_index_array_to_vector ) -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_multiplication.cpp b/test/tensor/test_multiplication.cpp index 5c23e5a02..2f1570d15 100644 --- a/test/tensor/test_multiplication.cpp +++ b/test/tensor/test_multiplication.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -22,7 +22,7 @@ #include -BOOST_AUTO_TEST_SUITE (test_tensor_contraction) ; +BOOST_AUTO_TEST_SUITE (test_tensor_contraction) using test_types = zip>::with_t; @@ -30,21 +30,23 @@ using test_types = zip>::with_t::with_t; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::shape; - fixture() : extents { - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - extents_type{2,3}, // 4 - extents_type{5,4}, // 5 - extents_type{2,3,1}, // 6 - extents_type{4,1,3}, // 7 - extents_type{1,2,3}, // 8 - extents_type{4,2,3}, // 9 - extents_type{4,2,3,5} // 10 - } - {} + fixture() + : extents { + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + extents_type{2,3}, // 4 + extents_type{5,4}, // 5 + extents_type{2,3,1}, // 6 + extents_type{4,1,3}, // 7 + extents_type{1,2,3}, // 8 + extents_type{4,2,3}, // 9 + extents_type{4,2,3,5}} // 10 + { + } std::vector extents; }; @@ -85,10 +87,10 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(test_tensor_mtv, value, test_types, fixture ) auto c = vector_type (nc.product(), value_type{0}); ublas::detail::recursive::mtv( - size_type(m), - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data()); + size_type(m), + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data()); for(auto i = 0u; i < c.size(); ++i) @@ -107,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_mtm, value, test_types, fixture ) using strides_type = ublas::strides; using vector_type = std::vector; using extents_type = ublas::shape; -// using extents_type_base = typename extents_type::base_type; + // using extents_type_base = typename extents_type::base_type; for(auto const& na : extents) { @@ -119,25 +121,25 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_mtm, value, test_types, fixture ) auto wa = strides_type (na); auto nb = extents_type {na[1],na[0]}; - auto wb = strides_type (nb); - auto b = vector_type (nb.product(), value_type{1} ); + auto wb = strides_type (nb); + auto b = vector_type (nb.product(), value_type{1} ); - auto nc = extents_type {na[0],nb[1]}; - auto wc = strides_type (nc); - auto c = vector_type (nc.product()); + auto nc = extents_type {na[0],nb[1]}; +auto wc = strides_type (nc); +auto c = vector_type (nc.product()); - ublas::detail::recursive::mtm( - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data(), nb.data(), wb.data()); +ublas::detail::recursive::mtm( + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data(), nb.data(), wb.data()); - for(auto i = 0u; i < c.size(); ++i) - BOOST_CHECK_EQUAL( c[i] , value_type(na[1]) * a[0] ); +for(auto i = 0u; i < c.size(); ++i) +BOOST_CHECK_EQUAL( c[i] , value_type(na[1]) * a[0] ); - } +} } @@ -173,9 +175,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttv, value, test_types, fixture ) auto c = vector_type (nc.product(), value_type{0}); ublas::ttv(size_type(m+1), na.size(), - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data(), nb.data(), wb.data()); + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data(), nb.data(), wb.data()); for(auto i = 0u; i < c.size(); ++i) @@ -212,9 +214,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttm, value, test_types, fixture ) auto c = vector_type (nc.product(), value_type{0}); ublas::ttm(size_type(m+1), na.size(), - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data(), nb.data(), wb.data()); + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data(), nb.data(), wb.data()); for(auto i = 0u; i < c.size(); ++i) BOOST_CHECK_EQUAL( c[i] , value_type(na[m]) * a[i] ); @@ -267,7 +269,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt_permutation, value, test_type // different permutation tuples for // right-hand side - for(auto const& na : extents) { + for(auto const& na : extents) { auto wa = strides_type(na); auto a = vector_type(na.product(), value_type{2}); @@ -310,10 +312,10 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt_permutation, value, test_type auto c = vector_type ( nc.product(), value_type(0) ); ublas::ttt(pa,pb,q, - pia.data(), pib_inv.data(), - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data(), nb.data(), wb.data()); + pia.data(), pib_inv.data(), + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data(), nb.data(), wb.data()); auto acc = value_type(1); @@ -361,13 +363,13 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt, value, test_types, fixture ) auto b = vector_type(nb.product(), value_type{3}); auto pb = nb.size(); -// std::cout << "na = "; -// std::copy(na.begin(), na.end(), std::ostream_iterator(std::cout, " ")); -// std::cout << std::endl; + // std::cout << "na = "; + // std::copy(na.begin(), na.end(), std::ostream_iterator(std::cout, " ")); + // std::cout << std::endl; -// std::cout << "nb = "; -// std::copy(nb.begin(), nb.end(), std::ostream_iterator(std::cout, " ")); -// std::cout << std::endl; + // std::cout << "nb = "; + // std::copy(nb.begin(), nb.end(), std::ostream_iterator(std::cout, " ")); + // std::cout << std::endl; // the number of contractions is changed. @@ -390,14 +392,14 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_ttt, value, test_types, fixture ) auto wc = strides_type ( nc ); auto c = vector_type ( nc.product(), value_type{0} ); -// std::cout << "nc = "; -// std::copy(nc.begin(), nc.end(), std::ostream_iterator(std::cout, " ")); -// std::cout << std::endl; + // std::cout << "nc = "; + // std::copy(nc.begin(), nc.end(), std::ostream_iterator(std::cout, " ")); + // std::cout << std::endl; ublas::ttt(pa,pb,q, - c.data(), nc.data(), wc.data(), - a.data(), na.data(), wa.data(), - b.data(), nb.data(), wb.data()); + c.data(), nc.data(), wc.data(), + a.data(), na.data(), wa.data(), + b.data(), nb.data(), wb.data()); auto acc = value_type(1); @@ -473,8 +475,8 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_outer, value, test_types, fixture auto wc = strides_type(extents_type(nc)); ublas::outer(c.data(), nc.size(), nc.data(), wc.data(), - a.data(), na.size(), na.data(), wa.data(), - b.data(), nb.size(), nb.data(), wb.data()); + a.data(), na.size(), na.data(), wa.data(), + b.data(), nb.size(), nb.data(), wb.data()); for(auto const& cc : c) BOOST_CHECK_EQUAL( cc , a[0]*b[0] ); @@ -485,5 +487,5 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_outer, value, test_types, fixture } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_operators_arithmetic.cpp b/test/tensor/test_operators_arithmetic.cpp index f4e96afe4..8bab76192 100644 --- a/test/tensor/test_operators_arithmetic.cpp +++ b/test/tensor/test_operators_arithmetic.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -11,8 +11,8 @@ -#include #include + #include #include #include "utility.hpp" @@ -22,25 +22,27 @@ using double_extended = boost::multiprecision::cpp_bin_float_double_extended; using test_types = zip::with_t; -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::basic_extents; - fixture() : extents{ - extents_type{}, // 0 - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{4,1,3}, // 6 - extents_type{1,2,3}, // 7 - extents_type{4,2,3}, // 8 - extents_type{4,2,3,5} // 9 - } - {} + fixture() + : extents{ + extents_type{}, // 0 + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{4,1,3}, // 6 + extents_type{1,2,3}, // 7 + extents_type{4,2,3}, // 8 + extents_type{4,2,3,5}} // 9 + { + } std::vector extents; }; -BOOST_AUTO_TEST_SUITE(test_tensor_arithmetic_operations, * boost::unit_test::depends_on("test_tensor")); +BOOST_AUTO_TEST_SUITE(test_tensor_arithmetic_operations, * boost::unit_test::depends_on("test_tensor")) @@ -262,4 +264,4 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_assign_arithmetic_operations, valu } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_operators_comparison.cpp b/test/tensor/test_operators_comparison.cpp index 8b0bb0826..f076e9c1e 100644 --- a/test/tensor/test_operators_comparison.cpp +++ b/test/tensor/test_operators_comparison.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -25,7 +25,8 @@ using test_types = zip::with_t; - fixture() : extents{ + fixture() + : extents{ extents_type{}, // 0 extents_type{1,1}, // 1 extents_type{1,2}, // 2 @@ -35,13 +36,13 @@ struct fixture { extents_type{4,1,3}, // 6 extents_type{1,2,3}, // 7 extents_type{4,2,3}, // 8 - extents_type{4,2,3,5} // 9 - } - {} + extents_type{4,2,3,5}} // 9 + { + } std::vector extents; }; -BOOST_AUTO_TEST_SUITE(test_tensor_comparison, * boost::unit_test::depends_on("test_tensor")); +BOOST_AUTO_TEST_SUITE(test_tensor_comparison, * boost::unit_test::depends_on("test_tensor")) BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_comparison, value, test_types, fixture) @@ -242,4 +243,4 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_comparison_with_scalar, value, te } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_strides.cpp b/test/tensor/test_strides.cpp index d42cf44e9..3a29e660a 100644 --- a/test/tensor/test_strides.cpp +++ b/test/tensor/test_strides.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -18,7 +18,7 @@ //BOOST_AUTO_TEST_SUITE(test_strides, * boost::unit_test::depends_on("test_extents")); -BOOST_AUTO_TEST_SUITE(test_strides); +BOOST_AUTO_TEST_SUITE(test_strides) using test_types = std::tuple; @@ -169,4 +169,4 @@ BOOST_AUTO_TEST_CASE( test_strides_ctor_access_last_order) } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index 8f873e6a3..400e86245 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -21,7 +21,7 @@ #include "utility.hpp" //BOOST_AUTO_TEST_SUITE ( test_tensor, * boost::unit_test::depends_on("test_extents") ) ; -BOOST_AUTO_TEST_SUITE ( test_tensor ) ; +BOOST_AUTO_TEST_SUITE ( test_tensor ) using test_types = zip>::with_t; @@ -70,21 +70,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_ctor, value, test_types) } -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::basic_extents; - fixture() : extents{ - extents_type{}, // 0 - extents_type{1,1}, // 1 - extents_type{1,2}, // 2 - extents_type{2,1}, // 3 - extents_type{2,3}, // 4 - extents_type{2,3,1}, // 5 - extents_type{4,1,3}, // 6 - extents_type{1,2,3}, // 7 - extents_type{4,2,3}, // 8 - extents_type{4,2,3,5} // 9 - } - {} + fixture() + : extents { + extents_type{}, // 0 + extents_type{1,1}, // 1 + extents_type{1,2}, // 2 + extents_type{2,1}, // 3 + extents_type{2,3}, // 4 + extents_type{2,3,1}, // 5 + extents_type{4,1,3}, // 6 + extents_type{1,2,3}, // 7 + extents_type{4,2,3}, // 8 + extents_type{4,2,3,5}} // 9 + { + } std::vector extents; }; @@ -355,7 +357,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_read_write_multi_index_access_at, v+=value_type{1}; } - if(t.rank() == 1) check1(t); + if(t.rank() == 1) check1(t); else if(t.rank() == 2) check2(t); else if(t.rank() == 3) check3(t); else if(t.rank() == 4) check4(t); @@ -468,4 +470,4 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_standard_iterator, value, test_ty } } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/test_tensor_matrix_vector.cpp b/test/tensor/test_tensor_matrix_vector.cpp index e30b5d4fc..3e34047dd 100644 --- a/test/tensor/test_tensor_matrix_vector.cpp +++ b/test/tensor/test_tensor_matrix_vector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Cem Bassoy +// Copyright (c) 2018-2019 Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -20,7 +20,7 @@ // BOOST_AUTO_TEST_SUITE ( test_tensor_matrix_interoperability, * boost::unit_test::depends_on("test_tensor") ) ; -BOOST_AUTO_TEST_SUITE ( test_tensor_matrix_interoperability ) ; +BOOST_AUTO_TEST_SUITE ( test_tensor_matrix_interoperability ) using test_types = zip::with_t; @@ -95,9 +95,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( test_tensor_vector_copy_ctor, value, test_types) } -struct fixture { +struct fixture +{ using extents_type = boost::numeric::ublas::basic_extents; - fixture() : extents{ + fixture() + : extents{ extents_type{1,1}, // 1 extents_type{1,2}, // 2 extents_type{2,1}, // 3 @@ -105,9 +107,9 @@ struct fixture { extents_type{9,7}, // 5 extents_type{9,11}, // 6 extents_type{12,12}, // 7 - extents_type{15,17}, // 8 - } - {} + extents_type{15,17}} // 8 + { + } std::vector extents; }; @@ -466,5 +468,5 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE( test_tensor_matrix_vector_expressions, value, } -BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tensor/utility.hpp b/test/tensor/utility.hpp index e071ee101..b2ef266e6 100644 --- a/test/tensor/utility.hpp +++ b/test/tensor/utility.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 +// Copyright (c) 2018-2019 // Cem Bassoy // // Distributed under the Boost Software License, Version 1.0. (See diff --git a/test/triangular_layout.cpp b/test/triangular_layout.cpp index 815643d37..f4da9752b 100644 --- a/test/triangular_layout.cpp +++ b/test/triangular_layout.cpp @@ -14,126 +14,126 @@ namespace ublas = boost::numeric::ublas; int main() { - int sz = 4; - ublas::symmetric_matrix UpCol (sz, sz); - ublas::symmetric_matrix UpRow (sz, sz); - ublas::symmetric_matrix LoCol (sz, sz); - ublas::symmetric_matrix LoRow (sz, sz); - - ublas::triangular_matrix TrUpCol (sz, sz); - ublas::triangular_matrix TrUpRow (sz, sz); - ublas::triangular_matrix TrLoCol (sz, sz); - ublas::triangular_matrix TrLoRow (sz, sz); - - for(int i=0; i UpCol (sz, sz); + ublas::symmetric_matrix UpRow (sz, sz); + ublas::symmetric_matrix LoCol (sz, sz); + ublas::symmetric_matrix LoRow (sz, sz); + + ublas::triangular_matrix TrUpCol (sz, sz); + ublas::triangular_matrix TrUpRow (sz, sz); + ublas::triangular_matrix TrLoCol (sz, sz); + ublas::triangular_matrix TrLoRow (sz, sz); + + for(int i=0; i Date: Sat, 2 Mar 2019 11:20:34 -0500 Subject: [PATCH 73/73] Adjust metadata and documentation. --- doc/index.html | 35 +++++++++++++---------------------- doc/release_notes.html | 9 +++++++++ meta/libraries.json | 5 +++-- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/doc/index.html b/doc/index.html index 2e1bedcd8..bedf58133 100644 --- a/doc/index.html +++ b/doc/index.html @@ -349,8 +349,11 @@

    Documentation

    +

    Release notes

    +Release notes can be found here. + -

    Known limitations:

    +

    Known limitations

    • The implementation assumes a linear memory address model.
    • @@ -360,27 +363,14 @@

      Known limitations:

      Further Information

      -

      Project Location and Download

      - -

      The latest stable release of uBLAS is part of the Boost libraries.

      - -

      Documentation and Discussion

      - -

      Visit the Effective -uBLAS wiki for up to date information and contributions.

      - -

      There is also an active uBLAS mailing list where uBLAS specific user and -development questions are answered.

      - -

      uBLAS and Boost Project

      - -

      There is also an active uBLAS mailing list where uBLAS specific from the -latest uBLAS project code. You can view the Boost -CVS archive directly. You will find the library here. Documentation and test -programs reside here.

      + -

      Authors and Credits

      +

      Authors and Credits

      uBLAS initially was written by Joerg Walter and Mathias Koch. We would like to thank all, which supported and contributed to the development of this library: David Abrahams, Ed Brey, Fernando Cacciola, Juan Jose Gomez Cadenas, @@ -388,7 +378,8 @@

      Authors and Credits

      John Maddock, Jens Maurer, Alexei Novakov, Gary Powell, Joachim Pyras, Peter Schmitteckert, Jeremy Siek, Markus Steffl, Michael Stevens, Benedikt Weber, Martin Weiser, Gunter Winkler, Marc Zimmermann, Marco Guazzone, Nasos Iliopoulus, the members of Boost and all others contributors around the world. I promise I will try to add their names to this list.

      -This library is currently maintained by David Bellot. +This library is currently maintained by David Bellot and Stefan Seefeld. +

      Frequently Asked Questions

      Q: Should I use uBLAS for new projects?
      diff --git a/doc/release_notes.html b/doc/release_notes.html index 2a10e07e7..806d794dc 100644 --- a/doc/release_notes.html +++ b/doc/release_notes.html @@ -18,6 +18,15 @@

      logoBoost Basic Line
      +

      Release 1.70.0

      + +

      improvements

      + +
        +
      • Add support for GPU-accelerated operations via Boost.Compute
      • +
      • Add support for a new (arbitrary-rank) tensor type and associated operations.
      • +
      +

      Release 1.52.0

      improvements

      diff --git a/meta/libraries.json b/meta/libraries.json index 68be73760..df121c3c3 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -5,11 +5,12 @@ "Joerg Walter", "Mathias Koch" ], - "description": "uBLAS provides matrix and vector classes as well as basic linear algebra routines. Several dense, packed and sparse storage schemes are supported.", + "description": "uBLAS provides tensor, matrix, and vector classes as well as basic linear algebra routines. Several dense, packed and sparse storage schemes are supported.", "category": [ "Math" ], "maintainers": [ - "David Bellot " + "David Bellot ", + "Stefan Seefeld " ] }